MIPI - Physical Interface for MIDI Files
Loading...
Searching...
No Matches
json.hpp
Go to the documentation of this file.
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.12.0
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013-2026 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-2026 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-2026 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-2026 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-2026 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-2026 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-2026 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-2026 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-2026 Niels Lohmann <https://nlohmann.me>
251// SPDX-License-Identifier: MIT
252
253
254
255// #include <nlohmann/detail/abi_macros.hpp>
256
257
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
270
271
273namespace detail
274{
275
276// https://en.cppreference.com/w/cpp/experimental/is_detected
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>
324 std::is_convertible<detected_t<Op, Args...>, To>;
325
326} // namespace detail
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-2026 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
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
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
2972namespace detail
2973{
2974
2976// JSON type enumeration //
2978
3003enum class value_t : std::uint8_t
3004{
3005 null,
3006 object,
3007 array,
3008 string,
3009 boolean,
3012 number_float,
3013 binary,
3014 discarded
3015};
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
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-2026 Niels Lohmann <https://nlohmann.me>
3077// SPDX-License-Identifier: MIT
3078
3079
3080
3081// #include <nlohmann/detail/abi_macros.hpp>
3082
3083
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
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-2026 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
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
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-2026 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
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{
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>
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>
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>
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
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-2026 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-2026 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
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>
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
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-2026 Niels Lohmann <https://nlohmann.me>
3455// SPDX-License-Identifier: MIT
3456
3457
3458
3459// #include <nlohmann/detail/macro_scope.hpp>
3460
3461
3463
3465
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-2026 Niels Lohmann <https://nlohmann.me>
3475// SPDX-License-Identifier: MIT
3476
3477
3478
3479// #include <nlohmann/detail/macro_scope.hpp>
3480
3481
3483
3485
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-2026 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
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
3556
3559 template<class Key, class T, class IgnoredLess, class Allocator>
3560 struct ordered_map;
3561
3565
3567
3568#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3569
3570
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
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>
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 =
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 =
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>
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
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
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>
3880
3881template<typename T>
3883{
3884 private:
3885 using t_ref = typename std::add_lvalue_reference<T>::type;
3886
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>
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,
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,
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{
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,
4055 BasicJsonType,
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 BasicJsonType, typename CompatibleReferenceType>
4108{
4110 using CVType = typename std::remove_reference<CompatibleReferenceType>::type;
4111 using Type = typename std::remove_cv<CVType>::type;
4112 constexpr static bool value = std::is_reference<CompatibleReferenceType>::value &&
4113 (!std::is_const<typename std::remove_reference<BasicJsonType>::type>::value || std::is_const<CVType>::value) &&
4114 (std::is_same<typename JsonType::boolean_t, Type>::value ||
4115 std::is_same<typename JsonType::number_float_t, Type>::value ||
4116 std::is_same<typename JsonType::number_integer_t, Type>::value ||
4117 std::is_same<typename JsonType::number_unsigned_t, Type>::value ||
4118 std::is_same<typename JsonType::string_t, Type>::value ||
4119 std::is_same<typename JsonType::binary_t, Type>::value ||
4120 std::is_same<typename JsonType::object_t, Type>::value ||
4121 std::is_same<typename JsonType::array_t, Type>::value);
4122};
4123
4124template<typename BasicJsonType, typename CompatibleReferenceType>
4126 : is_compatible_reference_type_impl<BasicJsonType, CompatibleReferenceType> {};
4127
4128template<typename T1, typename T2>
4129struct is_constructible_tuple : std::false_type {};
4130
4131template<typename T1, typename... Args>
4132struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
4133
4134template<typename BasicJsonType, typename T>
4135struct is_json_iterator_of : std::false_type {};
4136
4137template<typename BasicJsonType>
4138struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
4139
4140template<typename BasicJsonType>
4141struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
4142{};
4143
4144// checks if a given type T is a template specialization of Primary
4145template<template <typename...> class Primary, typename T>
4146struct is_specialization_of : std::false_type {};
4147
4148template<template <typename...> class Primary, typename... Args>
4149struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
4150
4151template<typename T>
4153
4154// checks if B is a json_pointer<A>
4155template <typename A, typename B>
4156struct is_json_pointer_of : std::false_type {};
4157
4158template <typename A>
4159struct is_json_pointer_of<A, ::nlohmann::json_pointer<A>> : std::true_type {};
4160
4161template <typename A>
4162struct is_json_pointer_of<A, ::nlohmann::json_pointer<A>&> : std::true_type {};
4163
4164// checks if A and B are comparable using Compare functor
4165template<typename Compare, typename A, typename B, typename = void>
4166struct is_comparable : std::false_type {};
4167
4168// We exclude json_pointer here, because the checks using Compare(A, B) will
4169// use json_pointer::operator string_t() which triggers a deprecation warning
4170// for GCC. See https://github.com/nlohmann/json/issues/4621. The call to
4171// is_json_pointer_of can be removed once the deprecated function has been
4172// removed.
4173template<typename Compare, typename A, typename B>
4174struct is_comparable < Compare, A, B, enable_if_t < !is_json_pointer_of<A, B>::value
4175&& std::is_constructible <decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>()))>::value
4176&& std::is_constructible <decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))>::value
4177>> : std::true_type {};
4178
4179template<typename T>
4180using detect_is_transparent = typename T::is_transparent;
4181
4182// type trait to check if KeyType can be used as an object key (without a BasicJsonType)
4183// see is_usable_as_basic_json_key_type below
4184template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4185 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4186using is_usable_as_key_type = typename std::conditional <
4188 && !(ExcludeObjectKeyType && std::is_same<KeyType,
4189 ObjectKeyType>::value)
4190 && (!RequireTransparentComparator
4191 || is_detected <detect_is_transparent, Comparator>::value)
4193 std::true_type,
4194 std::false_type >::type;
4195
4196// type trait to check if KeyType can be used as an object key
4197// true if:
4198// - KeyType is comparable with BasicJsonType::object_t::key_type
4199// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4200// - the comparator is transparent or RequireTransparentComparator is false
4201// - KeyType is not a JSON iterator or json_pointer
4202template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4203 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4204using is_usable_as_basic_json_key_type = typename std::conditional <
4205 (is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4206 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4207 RequireTransparentComparator, ExcludeObjectKeyType>::value
4209#ifdef JSON_HAS_CPP_17
4210 || std::is_convertible<KeyType, std::string_view>::value
4211#endif
4212 , std::true_type,
4213 std::false_type >::type;
4214
4215template<typename ObjectType, typename KeyType>
4216using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4217
4218// type trait to check if object_t has an erase() member functions accepting KeyType
4219template<typename BasicJsonType, typename KeyType>
4220using has_erase_with_key_type = typename std::conditional <
4221 is_detected <
4223 typename BasicJsonType::object_t, KeyType >::value,
4224 std::true_type,
4225 std::false_type >::type;
4226
4227// a naive helper to check if a type is an ordered_map (exploits the fact that
4228// ordered_map inherits capacity() from std::vector)
4229template <typename T>
4231{
4232 using one = char;
4233
4234 struct two
4235 {
4236 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4237 };
4238
4239 template <typename C> static one test( decltype(&C::capacity) ) ;
4240 template <typename C> static two test(...);
4241
4242 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg,cppcoreguidelines-use-enum-class)
4243};
4244
4245// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4246template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4248{
4249 return static_cast<T>(value);
4250}
4251
4252template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4254{
4255 return value;
4256}
4257
4258template<typename... Types>
4260
4261template<typename... Types>
4263
4264template<typename... Types>
4266
4267// there's a disjunction trait in another PR; replace when merged
4268template<typename... Types>
4269using same_sign = std::integral_constant < bool,
4270 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4271
4272template<typename OfType, typename T>
4273using never_out_of_range = std::integral_constant < bool,
4274 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4275 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4276
4277template<typename OfType, typename T,
4278 bool OfTypeSigned = std::is_signed<OfType>::value,
4279 bool TSigned = std::is_signed<T>::value>
4281
4282template<typename OfType, typename T>
4283struct value_in_range_of_impl2<OfType, T, false, false>
4284{
4285 static constexpr bool test(T val)
4286 {
4287 using CommonType = typename std::common_type<OfType, T>::type;
4288 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4289 }
4290};
4291
4292template<typename OfType, typename T>
4293struct value_in_range_of_impl2<OfType, T, true, false>
4294{
4295 static constexpr bool test(T val)
4296 {
4297 using CommonType = typename std::common_type<OfType, T>::type;
4298 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4299 }
4300};
4301
4302template<typename OfType, typename T>
4303struct value_in_range_of_impl2<OfType, T, false, true>
4304{
4305 static constexpr bool test(T val)
4306 {
4307 using CommonType = typename std::common_type<OfType, T>::type;
4308 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4309 }
4310};
4311
4312template<typename OfType, typename T>
4313struct value_in_range_of_impl2<OfType, T, true, true>
4314{
4315 static constexpr bool test(T val)
4316 {
4317 using CommonType = typename std::common_type<OfType, T>::type;
4318 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4319 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4320 }
4321};
4322
4323template<typename OfType, typename T,
4324 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4327
4328template<typename OfType, typename T>
4329struct value_in_range_of_impl1<OfType, T, false>
4330{
4331 static constexpr bool test(T val)
4332 {
4334 }
4335};
4336
4337template<typename OfType, typename T>
4338struct value_in_range_of_impl1<OfType, T, true>
4339{
4340 static constexpr bool test(T /*val*/)
4341 {
4342 return true;
4343 }
4344};
4345
4346template<typename OfType, typename T>
4347constexpr bool value_in_range_of(T val)
4348{
4350}
4351
4352template<bool Value>
4353using bool_constant = std::integral_constant<bool, Value>;
4354
4356// is_c_string
4358
4359namespace impl
4360{
4361
4362template<typename T>
4363constexpr bool is_c_string()
4364{
4365 using TUnExt = typename std::remove_extent<T>::type;
4366 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4367 using TUnPtr = typename std::remove_pointer<T>::type;
4368 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4369 return
4370 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4371 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4372}
4373
4374} // namespace impl
4375
4376// checks whether T is a [cv] char */[cv] char[] C string
4377template<typename T>
4378struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4379
4380template<typename T>
4382
4384// is_transparent
4386
4387namespace impl
4388{
4389
4390template<typename T>
4391constexpr bool is_transparent()
4392{
4394}
4395
4396} // namespace impl
4397
4398// checks whether T has a member named is_transparent
4399template<typename T>
4400struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4401
4403
4404} // namespace detail
4406
4407// #include <nlohmann/detail/string_concat.hpp>
4408// __ _____ _____ _____
4409// __| | __| | | | JSON for Modern C++
4410// | | |__ | | | | | | version 3.12.0
4411// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4412//
4413// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
4414// SPDX-License-Identifier: MIT
4415
4416
4417
4418#include <cstring> // strlen
4419#include <string> // string
4420#include <utility> // forward
4421
4422// #include <nlohmann/detail/meta/cpp_future.hpp>
4423
4424// #include <nlohmann/detail/meta/detected.hpp>
4425
4426
4428namespace detail
4429{
4430
4431inline std::size_t concat_length()
4432{
4433 return 0;
4434}
4435
4436template<typename... Args>
4437inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4438
4439template<typename StringType, typename... Args>
4440inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4441
4442template<typename... Args>
4443inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4444{
4445 return 1 + concat_length(rest...);
4446}
4447
4448template<typename... Args>
4449inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4450{
4451 // cppcheck-suppress ignoredReturnValue
4452 return ::strlen(cstr) + concat_length(rest...);
4453}
4454
4455template<typename StringType, typename... Args>
4456inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4457{
4458 return str.size() + concat_length(rest...);
4459}
4460
4461template<typename OutStringType>
4462inline void concat_into(OutStringType& /*out*/)
4463{}
4464
4465template<typename StringType, typename Arg>
4466using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4467
4468template<typename StringType, typename Arg>
4470
4471template<typename StringType, typename Arg>
4472using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4473
4474template<typename StringType, typename Arg>
4476
4477template<typename StringType, typename Arg>
4478using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4479
4480template<typename StringType, typename Arg>
4482
4483template<typename StringType, typename Arg>
4484using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4485
4486template<typename StringType, typename Arg>
4488
4489template < typename OutStringType, typename Arg, typename... Args,
4490 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4492inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4493
4494template < typename OutStringType, typename Arg, typename... Args,
4495 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4498inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4499
4500template < typename OutStringType, typename Arg, typename... Args,
4501 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4505inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4506
4507template<typename OutStringType, typename Arg, typename... Args,
4509inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4510{
4511 out.append(std::forward<Arg>(arg));
4512 concat_into(out, std::forward<Args>(rest)...);
4513}
4514
4515template < typename OutStringType, typename Arg, typename... Args,
4516 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4517 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4518inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4519{
4520 out += std::forward<Arg>(arg);
4521 concat_into(out, std::forward<Args>(rest)...);
4522}
4523
4524template < typename OutStringType, typename Arg, typename... Args,
4525 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4526 && !detect_string_can_append_op<OutStringType, Arg>::value
4527 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4528inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4529{
4530 out.append(arg.begin(), arg.end());
4531 concat_into(out, std::forward<Args>(rest)...);
4532}
4533
4534template < typename OutStringType, typename Arg, typename... Args,
4535 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4536 && !detect_string_can_append_op<OutStringType, Arg>::value
4537 && !detect_string_can_append_iter<OutStringType, Arg>::value
4538 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4539inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4540{
4541 out.append(arg.data(), arg.size());
4542 concat_into(out, std::forward<Args>(rest)...);
4543}
4544
4545template<typename OutStringType = std::string, typename... Args>
4546inline OutStringType concat(Args && ... args)
4547{
4548 OutStringType str;
4549 str.reserve(concat_length(args...));
4550 concat_into(str, std::forward<Args>(args)...);
4551 return str;
4552}
4553
4554} // namespace detail
4556
4557
4558// With -Wweak-vtables, Clang will complain about the exception classes as they
4559// have no out-of-line virtual method definitions and their vtable will be
4560// emitted in every translation unit. This issue cannot be fixed with a
4561// header-only library as there is no implementation file to move these
4562// functions to. As a result, we suppress this warning here to avoid client
4563// code stumbling over this. See https://github.com/nlohmann/json/issues/4087
4564// for a discussion.
4565#if defined(__clang__)
4566 #pragma clang diagnostic push
4567 #pragma clang diagnostic ignored "-Wweak-vtables"
4568#endif
4569
4571namespace detail
4572{
4573
4575// exceptions //
4577
4580class exception : public std::exception
4581{
4582 public:
4584 const char* what() const noexcept override
4585 {
4586 return m.what();
4587 }
4588
4590 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4591
4592 protected:
4594 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4595
4596 static std::string name(const std::string& ename, int id_)
4597 {
4598 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4599 }
4600
4601 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4602 {
4603 return "";
4604 }
4605
4606 template<typename BasicJsonType>
4607 static std::string diagnostics(const BasicJsonType* leaf_element)
4608 {
4609#if JSON_DIAGNOSTICS
4610 std::vector<std::string> tokens;
4611 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4612 {
4613 switch (current->m_parent->type())
4614 {
4615 case value_t::array:
4616 {
4617 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4618 {
4619 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4620 {
4621 tokens.emplace_back(std::to_string(i));
4622 break;
4623 }
4624 }
4625 break;
4626 }
4627
4628 case value_t::object:
4629 {
4630 for (const auto& element : *current->m_parent->m_data.m_value.object)
4631 {
4632 if (&element.second == current)
4633 {
4634 tokens.emplace_back(element.first.c_str());
4635 break;
4636 }
4637 }
4638 break;
4639 }
4640
4641 case value_t::null: // LCOV_EXCL_LINE
4642 case value_t::string: // LCOV_EXCL_LINE
4643 case value_t::boolean: // LCOV_EXCL_LINE
4644 case value_t::number_integer: // LCOV_EXCL_LINE
4645 case value_t::number_unsigned: // LCOV_EXCL_LINE
4646 case value_t::number_float: // LCOV_EXCL_LINE
4647 case value_t::binary: // LCOV_EXCL_LINE
4648 case value_t::discarded: // LCOV_EXCL_LINE
4649 default: // LCOV_EXCL_LINE
4650 break; // LCOV_EXCL_LINE
4651 }
4652 }
4653
4654 if (tokens.empty())
4655 {
4656 return "";
4657 }
4658
4659 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4660 [](const std::string & a, const std::string & b)
4661 {
4662 return concat(a, '/', detail::escape(b));
4663 });
4664
4665 return concat('(', str, ") ", get_byte_positions(leaf_element));
4666#else
4667 return get_byte_positions(leaf_element);
4668#endif
4669 }
4670
4671 private:
4673 std::runtime_error m;
4674#if JSON_DIAGNOSTIC_POSITIONS
4675 template<typename BasicJsonType>
4676 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4677 {
4678 if ((leaf_element->start_pos() != std::string::npos) && (leaf_element->end_pos() != std::string::npos))
4679 {
4680 return concat("(bytes ", std::to_string(leaf_element->start_pos()), "-", std::to_string(leaf_element->end_pos()), ") ");
4681 }
4682 return "";
4683 }
4684#else
4685 template<typename BasicJsonType>
4686 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4687 {
4688 static_cast<void>(leaf_element);
4689 return "";
4690 }
4691#endif
4692};
4693
4697{
4698 public:
4708 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4709 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4710 {
4711 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4712 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4713 return {id_, pos.chars_read_total, w.c_str()};
4714 }
4715
4716 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4717 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4718 {
4719 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4720 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4721 ": ", exception::diagnostics(context), what_arg);
4722 return {id_, byte_, w.c_str()};
4723 }
4724
4734 const std::size_t byte;
4735
4736 private:
4737 parse_error(int id_, std::size_t byte_, const char* what_arg)
4738 : exception(id_, what_arg), byte(byte_) {}
4739
4740 static std::string position_string(const position_t& pos)
4741 {
4742 return concat(" at line ", std::to_string(pos.lines_read + 1),
4743 ", column ", std::to_string(pos.chars_read_current_line));
4744 }
4745};
4746
4750{
4751 public:
4752 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4753 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4754 {
4755 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4756 return {id_, w.c_str()};
4757 }
4758
4759 private:
4761 invalid_iterator(int id_, const char* what_arg)
4762 : exception(id_, what_arg) {}
4763};
4764
4767class type_error : public exception
4768{
4769 public:
4770 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4771 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4772 {
4773 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4774 return {id_, w.c_str()};
4775 }
4776
4777 private:
4779 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4780};
4781
4785{
4786 public:
4787 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4788 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4789 {
4790 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4791 return {id_, w.c_str()};
4792 }
4793
4794 private:
4796 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4797};
4798
4802{
4803 public:
4804 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4805 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4806 {
4807 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4808 return {id_, w.c_str()};
4809 }
4810
4811 private:
4813 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4814};
4815
4816} // namespace detail
4818
4819#if defined(__clang__)
4820 #pragma clang diagnostic pop
4821#endif
4822
4823// #include <nlohmann/detail/macro_scope.hpp>
4824
4825// #include <nlohmann/detail/meta/cpp_future.hpp>
4826
4827// #include <nlohmann/detail/meta/identity_tag.hpp>
4828// __ _____ _____ _____
4829// __| | __| | | | JSON for Modern C++
4830// | | |__ | | | | | | version 3.12.0
4831// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4832//
4833// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
4834// SPDX-License-Identifier: MIT
4835
4836
4837
4838// #include <nlohmann/detail/abi_macros.hpp>
4839
4840
4842namespace detail
4843{
4844
4845// dispatching helper struct
4846template <class T> struct identity_tag {};
4847
4848} // namespace detail
4850
4851// #include <nlohmann/detail/meta/std_fs.hpp>
4852// __ _____ _____ _____
4853// __| | __| | | | JSON for Modern C++
4854// | | |__ | | | | | | version 3.12.0
4855// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4856//
4857// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
4858// SPDX-License-Identifier: MIT
4859
4860
4861
4862// #include <nlohmann/detail/macro_scope.hpp>
4863
4864
4865#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4866#include <experimental/filesystem>
4868namespace detail
4869{
4870namespace std_fs = std::experimental::filesystem;
4871} // namespace detail
4873#elif JSON_HAS_FILESYSTEM
4874#include <filesystem> // NOLINT(build/c++17)
4876namespace detail
4877{
4878namespace std_fs = std::filesystem;
4879} // namespace detail
4881#endif
4882
4883// #include <nlohmann/detail/meta/type_traits.hpp>
4884
4885// #include <nlohmann/detail/meta/logic.hpp>
4886
4887
4888// #include <nlohmann/detail/macro_scope.hpp>
4889
4890
4892namespace detail
4893{
4894#ifdef JSON_HAS_CPP_17
4895
4896template<bool... Booleans>
4897struct cxpr_or_impl : std::integral_constant < bool, (Booleans || ...) > {};
4898
4899template<bool... Booleans>
4900struct cxpr_and_impl : std::integral_constant < bool, (Booleans &&...) > {};
4901
4902#else
4903
4904template<bool... Booleans>
4905struct cxpr_or_impl : std::false_type {};
4906
4907template<bool... Booleans>
4908struct cxpr_or_impl<true, Booleans...> : std::true_type {};
4909
4910template<bool... Booleans>
4911struct cxpr_or_impl<false, Booleans...> : cxpr_or_impl<Booleans...> {};
4912
4913template<bool... Booleans>
4914struct cxpr_and_impl : std::true_type {};
4915
4916template<bool... Booleans>
4917struct cxpr_and_impl<true, Booleans...> : cxpr_and_impl<Booleans...> {};
4918
4919template<bool... Booleans>
4920struct cxpr_and_impl<false, Booleans...> : std::false_type {};
4921
4922#endif
4923
4924template<class Boolean>
4925struct cxpr_not : std::integral_constant < bool, !Boolean::value > {};
4926
4927template<class... Booleans>
4928struct cxpr_or : cxpr_or_impl<Booleans::value...> {};
4929
4930template<bool... Booleans>
4931struct cxpr_or_c : cxpr_or_impl<Booleans...> {};
4932
4933template<class... Booleans>
4934struct cxpr_and : cxpr_and_impl<Booleans::value...> {};
4935
4936template<bool... Booleans>
4937struct cxpr_and_c : cxpr_and_impl<Booleans...> {};
4938
4939} // namespace detail
4941
4942// #include <nlohmann/detail/string_concat.hpp>
4943
4944// #include <nlohmann/detail/value_t.hpp>
4945
4946
4947// include after macro_scope.hpp
4948#ifdef JSON_HAS_CPP_17
4949 #include <optional> // optional
4950#endif
4951
4952#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4953 #include <string_view> // u8string_view
4954#endif
4955
4957namespace detail
4958{
4959
4960template<typename BasicJsonType>
4961inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4962{
4963 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4964 {
4965 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4966 }
4967 n = nullptr;
4968}
4969
4970#ifdef JSON_HAS_CPP_17
4971template < typename BasicJsonType, typename T,
4972 typename std::enable_if < !nlohmann::detail::is_basic_json<T>::value, int >::type = 0 >
4973void from_json(const BasicJsonType& j, std::optional<T>& opt)
4974{
4975 if (j.is_null())
4976 {
4977 opt = std::nullopt;
4978 }
4979 else
4980 {
4981 opt.emplace(j.template get<T>());
4982 }
4983}
4984#endif // JSON_HAS_CPP_17
4985
4986// overloads for basic_json template parameters
4987template < typename BasicJsonType, typename ArithmeticType,
4988 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4989 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4990 int > = 0 >
4991void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4992{
4993 switch (static_cast<value_t>(j))
4994 {
4996 {
4997 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4998 break;
4999 }
5001 {
5002 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5003 break;
5004 }
5006 {
5007 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5008 break;
5009 }
5010
5011 case value_t::null:
5012 case value_t::object:
5013 case value_t::array:
5014 case value_t::string:
5015 case value_t::boolean:
5016 case value_t::binary:
5017 case value_t::discarded:
5018 default:
5019 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5020 }
5021}
5022
5023template<typename BasicJsonType>
5024inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
5025{
5026 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
5027 {
5028 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
5029 }
5030 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
5031}
5032
5033template<typename BasicJsonType>
5034inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
5035{
5036 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5037 {
5038 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5039 }
5040 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5041}
5042
5043template <
5044 typename BasicJsonType, typename StringType,
5045 enable_if_t <
5046 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
5047 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
5048 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
5049 && !is_json_ref<StringType>::value, int > = 0 >
5050inline void from_json(const BasicJsonType& j, StringType& s)
5051{
5052 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5053 {
5054 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5055 }
5056
5057 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5058}
5059
5060template<typename BasicJsonType>
5061inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
5062{
5063 get_arithmetic_value(j, val);
5064}
5065
5066template<typename BasicJsonType>
5067inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
5068{
5069 get_arithmetic_value(j, val);
5070}
5071
5072template<typename BasicJsonType>
5073inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
5074{
5075 get_arithmetic_value(j, val);
5076}
5077
5078#if !JSON_DISABLE_ENUM_SERIALIZATION
5079template<typename BasicJsonType, typename EnumType,
5080 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5081inline void from_json(const BasicJsonType& j, EnumType& e)
5082{
5083 typename std::underlying_type<EnumType>::type val;
5084 get_arithmetic_value(j, val);
5085 e = static_cast<EnumType>(val);
5086}
5087#endif // JSON_DISABLE_ENUM_SERIALIZATION
5088
5089// forward_list doesn't have an insert method
5090template<typename BasicJsonType, typename T, typename Allocator,
5091 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
5092inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
5093{
5094 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5095 {
5096 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5097 }
5098 l.clear();
5099 std::transform(j.rbegin(), j.rend(),
5100 std::front_inserter(l), [](const BasicJsonType & i)
5101 {
5102 return i.template get<T>();
5103 });
5104}
5105
5106// valarray doesn't have an insert method
5107template<typename BasicJsonType, typename T,
5108 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
5109inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
5110{
5111 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5112 {
5113 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5114 }
5115 l.resize(j.size());
5116 std::transform(j.begin(), j.end(), std::begin(l),
5117 [](const BasicJsonType & elem)
5118 {
5119 return elem.template get<T>();
5120 });
5121}
5122
5123template<typename BasicJsonType, typename T, std::size_t N>
5124auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5125-> decltype(j.template get<T>(), void())
5126{
5127 for (std::size_t i = 0; i < N; ++i)
5128 {
5129 arr[i] = j.at(i).template get<T>();
5130 }
5131}
5132
5133template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2>
5134auto from_json(const BasicJsonType& j, T (&arr)[N1][N2]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5135-> decltype(j.template get<T>(), void())
5136{
5137 for (std::size_t i1 = 0; i1 < N1; ++i1)
5138 {
5139 for (std::size_t i2 = 0; i2 < N2; ++i2)
5140 {
5141 arr[i1][i2] = j.at(i1).at(i2).template get<T>();
5142 }
5143 }
5144}
5145
5146template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3>
5147auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5148-> decltype(j.template get<T>(), void())
5149{
5150 for (std::size_t i1 = 0; i1 < N1; ++i1)
5151 {
5152 for (std::size_t i2 = 0; i2 < N2; ++i2)
5153 {
5154 for (std::size_t i3 = 0; i3 < N3; ++i3)
5155 {
5156 arr[i1][i2][i3] = j.at(i1).at(i2).at(i3).template get<T>();
5157 }
5158 }
5159 }
5160}
5161
5162template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3, std::size_t N4>
5163auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3][N4]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5164-> decltype(j.template get<T>(), void())
5165{
5166 for (std::size_t i1 = 0; i1 < N1; ++i1)
5167 {
5168 for (std::size_t i2 = 0; i2 < N2; ++i2)
5169 {
5170 for (std::size_t i3 = 0; i3 < N3; ++i3)
5171 {
5172 for (std::size_t i4 = 0; i4 < N4; ++i4)
5173 {
5174 arr[i1][i2][i3][i4] = j.at(i1).at(i2).at(i3).at(i4).template get<T>();
5175 }
5176 }
5177 }
5178 }
5179}
5180
5181template<typename BasicJsonType>
5182inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
5183{
5184 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
5185}
5186
5187template<typename BasicJsonType, typename T, std::size_t N>
5188auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
5189 priority_tag<2> /*unused*/)
5190-> decltype(j.template get<T>(), void())
5191{
5192 for (std::size_t i = 0; i < N; ++i)
5193 {
5194 arr[i] = j.at(i).template get<T>();
5195 }
5196}
5197
5198template<typename BasicJsonType, typename ConstructibleArrayType,
5200 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5201 int> = 0>
5202auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
5203-> decltype(
5204 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
5205 j.template get<typename ConstructibleArrayType::value_type>(),
5206 void())
5207{
5208 using std::end;
5209
5210 ConstructibleArrayType ret;
5211 ret.reserve(j.size());
5212 std::transform(j.begin(), j.end(),
5213 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
5214 {
5215 // get<BasicJsonType>() returns *this, this won't call a from_json
5216 // method when value_type is BasicJsonType
5217 return i.template get<typename ConstructibleArrayType::value_type>();
5218 });
5219 arr = std::move(ret);
5220}
5221
5222template<typename BasicJsonType, typename ConstructibleArrayType,
5224 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5225 int> = 0>
5226inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
5227 priority_tag<0> /*unused*/)
5228{
5229 using std::end;
5230
5231 ConstructibleArrayType ret;
5232 std::transform(
5233 j.begin(), j.end(), std::inserter(ret, end(ret)),
5234 [](const BasicJsonType & i)
5235 {
5236 // get<BasicJsonType>() returns *this, this won't call a from_json
5237 // method when value_type is BasicJsonType
5238 return i.template get<typename ConstructibleArrayType::value_type>();
5239 });
5240 arr = std::move(ret);
5241}
5242
5243template < typename BasicJsonType, typename ConstructibleArrayType,
5244 enable_if_t <
5245 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
5246 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
5248 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
5249 !is_basic_json<ConstructibleArrayType>::value,
5250 int > = 0 >
5251auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
5252-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
5253j.template get<typename ConstructibleArrayType::value_type>(),
5254void())
5255{
5256 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5257 {
5258 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5259 }
5260
5261 from_json_array_impl(j, arr, priority_tag<3> {});
5262}
5263
5264template < typename BasicJsonType, typename T, std::size_t... Idx >
5265std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
5266 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
5267{
5268 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
5269}
5270
5271template < typename BasicJsonType, typename T, std::size_t N >
5272auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
5273-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
5274{
5275 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5276 {
5277 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5278 }
5279
5280 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
5281}
5282
5283template<typename BasicJsonType>
5284inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
5285{
5286 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
5287 {
5288 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
5289 }
5290
5291 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
5292}
5293
5294template<typename BasicJsonType, typename ConstructibleObjectType,
5295 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
5296inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
5297{
5298 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
5299 {
5300 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
5301 }
5302
5303 ConstructibleObjectType ret;
5304 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
5305 using value_type = typename ConstructibleObjectType::value_type;
5306 std::transform(
5307 inner_object->begin(), inner_object->end(),
5308 std::inserter(ret, ret.begin()),
5309 [](typename BasicJsonType::object_t::value_type const & p)
5310 {
5311 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
5312 });
5313 obj = std::move(ret);
5314}
5315
5316// overload for arithmetic types, not chosen for basic_json template arguments
5317// (BooleanType, etc.); note: Is it really necessary to provide explicit
5318// overloads for boolean_t etc. in case of a custom BooleanType which is not
5319// an arithmetic type?
5320template < typename BasicJsonType, typename ArithmeticType,
5321 enable_if_t <
5322 std::is_arithmetic<ArithmeticType>::value&&
5323 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
5324 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
5325 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
5326 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
5327 int > = 0 >
5328inline void from_json(const BasicJsonType& j, ArithmeticType& val)
5329{
5330 switch (static_cast<value_t>(j))
5331 {
5333 {
5334 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
5335 break;
5336 }
5338 {
5339 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5340 break;
5341 }
5343 {
5344 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5345 break;
5346 }
5347 case value_t::boolean:
5348 {
5349 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5350 break;
5351 }
5352
5353 case value_t::null:
5354 case value_t::object:
5355 case value_t::array:
5356 case value_t::string:
5357 case value_t::binary:
5358 case value_t::discarded:
5359 default:
5360 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5361 }
5362}
5363
5364template<typename BasicJsonType, typename Type>
5366{
5367 return std::forward<BasicJsonType>(j).template get<detail::uncvref_t<Type>>();
5368}
5369
5370template<typename BasicJsonType, typename Type,
5373{
5374 return std::forward<BasicJsonType>(j).template get_ref<Type>();
5375}
5376
5377template<typename BasicJsonType, typename Type,
5380{
5381 return std::forward<BasicJsonType>(j).template get<detail::uncvref_t<Type>>();
5382}
5383
5384template<std::size_t PTagValue, typename BasicJsonType, typename... Types>
5385using tuple_type = std::tuple < decltype(from_json_tuple_get_impl(std::declval<BasicJsonType>(), detail::identity_tag<Types> {}, detail::priority_tag<PTagValue> {}))... >;
5386
5387template<std::size_t PTagValue, typename... Args, typename BasicJsonType, std::size_t... Idx>
5388tuple_type<PTagValue, BasicJsonType, Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5389{
5390 return tuple_type<PTagValue, BasicJsonType, Args...>(from_json_tuple_get_impl(std::forward<BasicJsonType>(j).at(Idx), detail::identity_tag<Args> {}, detail::priority_tag<PTagValue> {})...);
5391}
5392
5393template<std::size_t PTagValue, typename BasicJsonType>
5394std::tuple<> from_json_tuple_impl_base(BasicJsonType& /*unused*/, index_sequence<> /*unused*/)
5395{
5396 return {};
5397}
5398
5399template < typename BasicJsonType, class A1, class A2 >
5400std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5401{
5402 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5403 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5404}
5405
5406template<typename BasicJsonType, typename A1, typename A2>
5407inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5408{
5409 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5410}
5411
5412template<typename BasicJsonType, typename... Args>
5413std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5414{
5416 "Can not return a tuple containing references to types not contained in a Json, try Json::get_to()");
5417 return from_json_tuple_impl_base<1, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5418}
5419
5420template<typename BasicJsonType, typename... Args>
5421inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5422{
5423 t = from_json_tuple_impl_base<2, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5424}
5425
5426template<typename BasicJsonType, typename TupleRelated>
5427auto from_json(BasicJsonType&& j, TupleRelated&& t)
5428-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5429{
5430 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5431 {
5432 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5433 }
5434
5435 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5436}
5437
5438template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5439 typename = enable_if_t < !std::is_constructible <
5440 typename BasicJsonType::string_t, Key >::value >>
5441inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5442{
5443 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5444 {
5445 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5446 }
5447 m.clear();
5448 for (const auto& p : j)
5449 {
5450 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5451 {
5452 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5453 }
5454 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5455 }
5456}
5457
5458template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5459 typename = enable_if_t < !std::is_constructible <
5460 typename BasicJsonType::string_t, Key >::value >>
5461inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5462{
5463 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5464 {
5465 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5466 }
5467 m.clear();
5468 for (const auto& p : j)
5469 {
5470 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5471 {
5472 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5473 }
5474 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5475 }
5476}
5477
5478#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5479template<typename BasicJsonType>
5480inline void from_json(const BasicJsonType& j, std_fs::path& p)
5481{
5482 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5483 {
5484 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5485 }
5486 const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5487 // Checking for C++20 standard or later can be insufficient in case the
5488 // library support for char8_t is either incomplete or was disabled
5489 // altogether. Use the __cpp_lib_char8_t feature test instead.
5490#if defined(__cpp_lib_char8_t) && (__cpp_lib_char8_t >= 201907L)
5491 p = std_fs::path(std::u8string_view(reinterpret_cast<const char8_t*>(s.data()), s.size()));
5492#else
5493 p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20
5494#endif
5495}
5496#endif
5497
5499{
5500 template<typename BasicJsonType, typename T>
5501 auto operator()(const BasicJsonType& j, T&& val) const
5502 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5503 -> decltype(from_json(j, std::forward<T>(val)))
5504 {
5505 return from_json(j, std::forward<T>(val));
5506 }
5507};
5508
5509} // namespace detail
5510
5511#ifndef JSON_HAS_CPP_17
5515namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5516{
5517#endif
5518JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5520#ifndef JSON_HAS_CPP_17
5521} // namespace
5522#endif
5523
5525
5526// #include <nlohmann/detail/conversions/to_json.hpp>
5527// __ _____ _____ _____
5528// __| | __| | | | JSON for Modern C++
5529// | | |__ | | | | | | version 3.12.0
5530// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5531//
5532// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
5533// SPDX-License-Identifier: MIT
5534
5535
5536
5537// #include <nlohmann/detail/macro_scope.hpp>
5538// JSON_HAS_CPP_17
5539#ifdef JSON_HAS_CPP_17
5540 #include <optional> // optional
5541#endif
5542
5543#include <algorithm> // copy
5544#include <iterator> // begin, end
5545#include <memory> // allocator_traits
5546#include <string> // basic_string, char_traits
5547#include <tuple> // tuple, get
5548#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5549#include <utility> // move, forward, declval, pair
5550#include <valarray> // valarray
5551#include <vector> // vector
5552
5553// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5554// __ _____ _____ _____
5555// __| | __| | | | JSON for Modern C++
5556// | | |__ | | | | | | version 3.12.0
5557// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5558//
5559// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
5560// SPDX-License-Identifier: MIT
5561
5562
5563
5564#include <cstddef> // size_t
5565#include <iterator> // forward_iterator_tag
5566#include <tuple> // tuple_size, get, tuple_element
5567#include <utility> // move
5568
5569#if JSON_HAS_RANGES
5570 #include <ranges> // enable_borrowed_range
5571#endif
5572
5573// #include <nlohmann/detail/abi_macros.hpp>
5574
5575// #include <nlohmann/detail/meta/type_traits.hpp>
5576
5577// #include <nlohmann/detail/string_utils.hpp>
5578// __ _____ _____ _____
5579// __| | __| | | | JSON for Modern C++
5580// | | |__ | | | | | | version 3.12.0
5581// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5582//
5583// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
5584// SPDX-License-Identifier: MIT
5585
5586
5587
5588#include <cstddef> // size_t
5589#include <string> // string, to_string
5590
5591// #include <nlohmann/detail/abi_macros.hpp>
5592
5593
5595namespace detail
5596{
5597
5598template<typename StringType>
5599void int_to_string(StringType& target, std::size_t value)
5600{
5601 // For ADL
5602 using std::to_string;
5603 target = to_string(value);
5604}
5605
5606template<typename StringType>
5607StringType to_string(std::size_t value)
5608{
5609 StringType result;
5610 int_to_string(result, value);
5611 return result;
5612}
5613
5614} // namespace detail
5616
5617// #include <nlohmann/detail/value_t.hpp>
5618
5619
5621namespace detail
5622{
5623
5624template<typename IteratorType> class iteration_proxy_value
5625{
5626 public:
5627 using difference_type = std::ptrdiff_t;
5631 using iterator_category = std::forward_iterator_tag;
5632 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5633
5634 private:
5636 IteratorType anchor{};
5638 std::size_t array_index = 0;
5640 mutable std::size_t array_index_last = 0;
5645
5646 public:
5647 explicit iteration_proxy_value() = default;
5648 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5649 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5650 && std::is_nothrow_default_constructible<string_type>::value)
5651 : anchor(std::move(it))
5652 , array_index(array_index_)
5653 {}
5654
5657 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5659 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5660 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5662 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5663 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5665
5667 const iteration_proxy_value& operator*() const
5668 {
5669 return *this;
5670 }
5671
5674 {
5675 ++anchor;
5676 ++array_index;
5677
5678 return *this;
5679 }
5680
5681 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5682 {
5684 ++anchor;
5685 ++array_index;
5686 return tmp;
5687 }
5688
5691 {
5692 return anchor == o.anchor;
5693 }
5694
5697 {
5698 return anchor != o.anchor;
5699 }
5700
5702 const string_type& key() const
5703 {
5704 JSON_ASSERT(anchor.m_object != nullptr);
5705
5706 switch (anchor.m_object->type())
5707 {
5708 // use integer array index as key
5709 case value_t::array:
5710 {
5712 {
5715 }
5716 return array_index_str;
5717 }
5718
5719 // use key from the object
5720 case value_t::object:
5721 return anchor.key();
5722
5723 // use an empty key for all primitive types
5724 case value_t::null:
5725 case value_t::string:
5726 case value_t::boolean:
5730 case value_t::binary:
5731 case value_t::discarded:
5732 default:
5733 return empty_str;
5734 }
5735 }
5736
5738 typename IteratorType::reference value() const
5739 {
5740 return anchor.value();
5741 }
5742};
5743
5745template<typename IteratorType> class iteration_proxy
5746{
5747 private:
5749 typename IteratorType::pointer container = nullptr;
5750
5751 public:
5752 explicit iteration_proxy() = default;
5753
5755 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5756 : container(&cont) {}
5757
5760 iteration_proxy(iteration_proxy&&) noexcept = default;
5761 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5762 ~iteration_proxy() = default;
5763
5765 iteration_proxy_value<IteratorType> begin() const noexcept
5766 {
5768 }
5769
5775};
5776
5777// Structured Bindings Support
5778// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5779// And see https://github.com/nlohmann/json/pull/1391
5780template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5781auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5782{
5783 return i.key();
5784}
5785// Structured Bindings Support
5786// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5787// And see https://github.com/nlohmann/json/pull/1391
5788template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5789auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5790{
5791 return i.value();
5792}
5793
5794} // namespace detail
5796
5797// The Addition to the STD Namespace is required to add
5798// Structured Bindings Support to the iteration_proxy_value class
5799// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5800// And see https://github.com/nlohmann/json/pull/1391
5801namespace std
5802{
5803
5804#if defined(__clang__)
5805 // Fix: https://github.com/nlohmann/json/issues/1401
5806 #pragma clang diagnostic push
5807 #pragma clang diagnostic ignored "-Wmismatched-tags"
5808#endif
5809template<typename IteratorType>
5810class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5811 : public std::integral_constant<std::size_t, 2> {};
5812
5813template<std::size_t N, typename IteratorType>
5814class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5815{
5816 public:
5817 using type = decltype(
5818 get<N>(std::declval <
5819 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5820};
5821#if defined(__clang__)
5822 #pragma clang diagnostic pop
5823#endif
5824
5825} // namespace std
5826
5827#if JSON_HAS_RANGES
5828 template <typename IteratorType>
5829 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5830#endif
5831
5832// #include <nlohmann/detail/meta/cpp_future.hpp>
5833
5834// #include <nlohmann/detail/meta/std_fs.hpp>
5835
5836// #include <nlohmann/detail/meta/type_traits.hpp>
5837
5838// #include <nlohmann/detail/value_t.hpp>
5839
5840
5842namespace detail
5843{
5844
5846// constructors //
5848
5849/*
5850 * Note all external_constructor<>::construct functions need to call
5851 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5852 * allocated value (e.g., a string). See bug issue
5853 * https://github.com/nlohmann/json/issues/2865 for more information.
5854 */
5855
5856template<value_t> struct external_constructor;
5857
5858template<>
5860{
5861 template<typename BasicJsonType>
5862 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5863 {
5864 j.m_data.m_value.destroy(j.m_data.m_type);
5865 j.m_data.m_type = value_t::boolean;
5866 j.m_data.m_value = b;
5867 j.assert_invariant();
5868 }
5869};
5870
5871template<>
5873{
5874 template<typename BasicJsonType>
5875 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5876 {
5877 j.m_data.m_value.destroy(j.m_data.m_type);
5878 j.m_data.m_type = value_t::string;
5879 j.m_data.m_value = s;
5880 j.assert_invariant();
5881 }
5882
5883 template<typename BasicJsonType>
5884 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5885 {
5886 j.m_data.m_value.destroy(j.m_data.m_type);
5887 j.m_data.m_type = value_t::string;
5888 j.m_data.m_value = std::move(s);
5889 j.assert_invariant();
5890 }
5891
5892 template < typename BasicJsonType, typename CompatibleStringType,
5893 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5894 int > = 0 >
5895 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5896 {
5897 j.m_data.m_value.destroy(j.m_data.m_type);
5898 j.m_data.m_type = value_t::string;
5899 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5900 j.assert_invariant();
5901 }
5902};
5903
5904template<>
5906{
5907 template<typename BasicJsonType>
5908 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5909 {
5910 j.m_data.m_value.destroy(j.m_data.m_type);
5911 j.m_data.m_type = value_t::binary;
5912 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5913 j.assert_invariant();
5914 }
5915
5916 template<typename BasicJsonType>
5917 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5918 {
5919 j.m_data.m_value.destroy(j.m_data.m_type);
5920 j.m_data.m_type = value_t::binary;
5921 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5922 j.assert_invariant();
5923 }
5924};
5925
5926template<>
5928{
5929 template<typename BasicJsonType>
5930 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5931 {
5932 j.m_data.m_value.destroy(j.m_data.m_type);
5933 j.m_data.m_type = value_t::number_float;
5934 j.m_data.m_value = val;
5935 j.assert_invariant();
5936 }
5937};
5938
5939template<>
5941{
5942 template<typename BasicJsonType>
5943 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5944 {
5945 j.m_data.m_value.destroy(j.m_data.m_type);
5946 j.m_data.m_type = value_t::number_unsigned;
5947 j.m_data.m_value = val;
5948 j.assert_invariant();
5949 }
5950};
5951
5952template<>
5954{
5955 template<typename BasicJsonType>
5956 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5957 {
5958 j.m_data.m_value.destroy(j.m_data.m_type);
5959 j.m_data.m_type = value_t::number_integer;
5960 j.m_data.m_value = val;
5961 j.assert_invariant();
5962 }
5963};
5964
5965template<>
5967{
5968 template<typename BasicJsonType>
5969 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5970 {
5971 j.m_data.m_value.destroy(j.m_data.m_type);
5972 j.m_data.m_type = value_t::array;
5973 j.m_data.m_value = arr;
5974 j.set_parents();
5975 j.assert_invariant();
5976 }
5977
5978 template<typename BasicJsonType>
5979 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5980 {
5981 j.m_data.m_value.destroy(j.m_data.m_type);
5982 j.m_data.m_type = value_t::array;
5983 j.m_data.m_value = std::move(arr);
5984 j.set_parents();
5985 j.assert_invariant();
5986 }
5987
5988 template < typename BasicJsonType, typename CompatibleArrayType,
5989 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5990 int > = 0 >
5991 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5992 {
5993 using std::begin;
5994 using std::end;
5995
5996 j.m_data.m_value.destroy(j.m_data.m_type);
5997 j.m_data.m_type = value_t::array;
5998 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5999 j.set_parents();
6000 j.assert_invariant();
6001 }
6002
6003 template<typename BasicJsonType>
6004 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
6005 {
6006 j.m_data.m_value.destroy(j.m_data.m_type);
6007 j.m_data.m_type = value_t::array;
6008 j.m_data.m_value = value_t::array;
6009 j.m_data.m_value.array->reserve(arr.size());
6010 for (const bool x : arr)
6011 {
6012 j.m_data.m_value.array->push_back(x);
6013 j.set_parent(j.m_data.m_value.array->back());
6014 }
6015 j.assert_invariant();
6016 }
6017
6018 template<typename BasicJsonType, typename T,
6020 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
6021 {
6022 j.m_data.m_value.destroy(j.m_data.m_type);
6023 j.m_data.m_type = value_t::array;
6024 j.m_data.m_value = value_t::array;
6025 j.m_data.m_value.array->resize(arr.size());
6026 if (arr.size() > 0)
6027 {
6028 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
6029 }
6030 j.set_parents();
6031 j.assert_invariant();
6032 }
6033};
6034
6035template<>
6037{
6038 template<typename BasicJsonType>
6039 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
6040 {
6041 j.m_data.m_value.destroy(j.m_data.m_type);
6042 j.m_data.m_type = value_t::object;
6043 j.m_data.m_value = obj;
6044 j.set_parents();
6045 j.assert_invariant();
6046 }
6047
6048 template<typename BasicJsonType>
6049 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
6050 {
6051 j.m_data.m_value.destroy(j.m_data.m_type);
6052 j.m_data.m_type = value_t::object;
6053 j.m_data.m_value = std::move(obj);
6054 j.set_parents();
6055 j.assert_invariant();
6056 }
6057
6058 template < typename BasicJsonType, typename CompatibleObjectType,
6059 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
6060 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
6061 {
6062 using std::begin;
6063 using std::end;
6064
6065 j.m_data.m_value.destroy(j.m_data.m_type);
6066 j.m_data.m_type = value_t::object;
6067 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
6068 j.set_parents();
6069 j.assert_invariant();
6070 }
6071};
6072
6074// to_json //
6076
6077#ifdef JSON_HAS_CPP_17
6078template<typename BasicJsonType, typename T,
6079 enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
6080void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept
6081{
6082 if (opt.has_value())
6083 {
6084 j = *opt;
6085 }
6086 else
6087 {
6088 j = nullptr;
6089 }
6090}
6091#endif
6092
6093template<typename BasicJsonType, typename T,
6094 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
6095inline void to_json(BasicJsonType& j, T b) noexcept
6096{
6098}
6099
6100template < typename BasicJsonType, typename BoolRef,
6101 enable_if_t <
6102 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
6103 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
6104 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
6105 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
6106 typename BasicJsonType::boolean_t >::value))
6107 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
6108inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
6109{
6110 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
6111}
6112
6113template<typename BasicJsonType, typename CompatibleString,
6114 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
6115inline void to_json(BasicJsonType& j, const CompatibleString& s)
6116{
6118}
6119
6120template<typename BasicJsonType>
6121inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
6122{
6124}
6125
6126template<typename BasicJsonType, typename FloatType,
6127 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
6128inline void to_json(BasicJsonType& j, FloatType val) noexcept
6129{
6130 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
6131}
6132
6133template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
6134 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
6135inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
6136{
6137 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
6138}
6139
6140template<typename BasicJsonType, typename CompatibleNumberIntegerType,
6141 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
6142inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
6143{
6144 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
6145}
6146
6147#if !JSON_DISABLE_ENUM_SERIALIZATION
6148template<typename BasicJsonType, typename EnumType,
6149 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
6150inline void to_json(BasicJsonType& j, EnumType e) noexcept
6151{
6152 using underlying_type = typename std::underlying_type<EnumType>::type;
6153 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
6154 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
6155}
6156#endif // JSON_DISABLE_ENUM_SERIALIZATION
6157
6158template<typename BasicJsonType>
6159inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
6160{
6162}
6163
6164template < typename BasicJsonType, typename CompatibleArrayType,
6165 enable_if_t < is_compatible_array_type<BasicJsonType,
6166 CompatibleArrayType>::value&&
6167 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
6169 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
6170 !is_basic_json<CompatibleArrayType>::value,
6171 int > = 0 >
6172inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
6173{
6175}
6176
6177template<typename BasicJsonType>
6178inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
6179{
6181}
6182
6183template<typename BasicJsonType, typename T,
6184 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
6185inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
6186{
6188}
6189
6190template<typename BasicJsonType>
6191inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
6192{
6194}
6195
6196template < typename BasicJsonType, typename CompatibleObjectType,
6197 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
6198inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
6199{
6201}
6202
6203template<typename BasicJsonType>
6204inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
6205{
6207}
6208
6209template <
6210 typename BasicJsonType, typename T, std::size_t N,
6211 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
6212 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6213 int > = 0 >
6214inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6215{
6217}
6218
6219template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
6220inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
6221{
6222 j = { p.first, p.second };
6223}
6224
6225// for https://github.com/nlohmann/json/pull/1134
6226template<typename BasicJsonType, typename T,
6227 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
6228inline void to_json(BasicJsonType& j, const T& b)
6229{
6230 j = { {b.key(), b.value()} };
6231}
6232
6233template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
6234inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
6235{
6236 j = { std::get<Idx>(t)... };
6237}
6238
6239template<typename BasicJsonType, typename Tuple>
6240inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& /*unused*/, index_sequence<> /*unused*/)
6241{
6242 using array_t = typename BasicJsonType::array_t;
6243 j = array_t();
6244}
6245
6246template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
6247inline void to_json(BasicJsonType& j, const T& t)
6248{
6249 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
6250}
6251
6252#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
6253#if defined(__cpp_lib_char8_t)
6254template<typename BasicJsonType, typename Tr, typename Allocator>
6255inline void to_json(BasicJsonType& j, const std::basic_string<char8_t, Tr, Allocator>& s)
6256{
6257 using OtherAllocator = typename std::allocator_traits<Allocator>::template rebind_alloc<char>;
6258 j = std::basic_string<char, std::char_traits<char>, OtherAllocator>(s.begin(), s.end(), s.get_allocator());
6259}
6260#endif
6261
6262template<typename BasicJsonType>
6263inline void to_json(BasicJsonType& j, const std_fs::path& p)
6264{
6265 // Returns either a std::string or a std::u8string depending whether library
6266 // support for char8_t is enabled.
6267 j = p.u8string();
6268}
6269#endif
6270
6272{
6273 template<typename BasicJsonType, typename T>
6274 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
6275 -> decltype(to_json(j, std::forward<T>(val)), void())
6276 {
6277 return to_json(j, std::forward<T>(val));
6278 }
6279};
6280} // namespace detail
6281
6282#ifndef JSON_HAS_CPP_17
6286namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
6287{
6288#endif
6289JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
6291#ifndef JSON_HAS_CPP_17
6292} // namespace
6293#endif
6294
6296
6297// #include <nlohmann/detail/meta/identity_tag.hpp>
6298
6299
6301
6303template<typename ValueType, typename>
6305{
6308 template<typename BasicJsonType, typename TargetType = ValueType>
6309 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
6310 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
6311 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
6312 {
6313 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
6314 }
6315
6318 template<typename BasicJsonType, typename TargetType = ValueType>
6319 static auto from_json(BasicJsonType && j) noexcept(
6320 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
6321 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
6322 {
6323 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
6324 }
6325
6328 template<typename BasicJsonType, typename TargetType = ValueType>
6329 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
6330 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
6331 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
6332 {
6333 ::nlohmann::to_json(j, std::forward<TargetType>(val));
6334 }
6335};
6336
6338
6339// #include <nlohmann/byte_container_with_subtype.hpp>
6340// __ _____ _____ _____
6341// __| | __| | | | JSON for Modern C++
6342// | | |__ | | | | | | version 3.12.0
6343// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6344//
6345// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
6346// SPDX-License-Identifier: MIT
6347
6348
6349
6350#include <cstdint> // uint8_t, uint64_t
6351#include <tuple> // tie
6352#include <utility> // move
6353
6354// #include <nlohmann/detail/abi_macros.hpp>
6355
6356
6358
6361template<typename BinaryType>
6362class byte_container_with_subtype : public BinaryType
6363{
6364 public:
6365 using container_type = BinaryType;
6366 using subtype_type = std::uint64_t;
6367
6370 : container_type()
6371 {}
6372
6375 : container_type(b)
6376 {}
6377
6379 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
6380 : container_type(std::move(b))
6381 {}
6382
6385 : container_type(b)
6386 , m_subtype(subtype_)
6387 , m_has_subtype(true)
6388 {}
6389
6391 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
6392 : container_type(std::move(b))
6393 , m_subtype(subtype_)
6394 , m_has_subtype(true)
6395 {}
6396
6398 {
6399 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
6400 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
6401 }
6402
6404 {
6405 return !(rhs == *this);
6406 }
6407
6410 void set_subtype(subtype_type subtype_) noexcept
6411 {
6412 m_subtype = subtype_;
6413 m_has_subtype = true;
6414 }
6415
6418 constexpr subtype_type subtype() const noexcept
6419 {
6420 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
6421 }
6422
6425 constexpr bool has_subtype() const noexcept
6426 {
6427 return m_has_subtype;
6428 }
6429
6432 void clear_subtype() noexcept
6433 {
6434 m_subtype = 0;
6435 m_has_subtype = false;
6436 }
6437
6438 private:
6440 bool m_has_subtype = false;
6441};
6442
6444
6445// #include <nlohmann/detail/conversions/from_json.hpp>
6446
6447// #include <nlohmann/detail/conversions/to_json.hpp>
6448
6449// #include <nlohmann/detail/exceptions.hpp>
6450
6451// #include <nlohmann/detail/hash.hpp>
6452// __ _____ _____ _____
6453// __| | __| | | | JSON for Modern C++
6454// | | |__ | | | | | | version 3.12.0
6455// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6456//
6457// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
6458// SPDX-License-Identifier: MIT
6459
6460
6461
6462#include <cstdint> // uint8_t
6463#include <cstddef> // size_t
6464#include <functional> // hash
6465
6466// #include <nlohmann/detail/abi_macros.hpp>
6467
6468// #include <nlohmann/detail/value_t.hpp>
6469
6470
6472namespace detail
6473{
6474
6475// boost::hash_combine
6476inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6477{
6478 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6479 return seed;
6480}
6481
6493template<typename BasicJsonType>
6494std::size_t hash(const BasicJsonType& j)
6495{
6496 using string_t = typename BasicJsonType::string_t;
6497 using number_integer_t = typename BasicJsonType::number_integer_t;
6498 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6499 using number_float_t = typename BasicJsonType::number_float_t;
6500
6501 const auto type = static_cast<std::size_t>(j.type());
6502 switch (j.type())
6503 {
6504 case BasicJsonType::value_t::null:
6505 case BasicJsonType::value_t::discarded:
6506 {
6507 return combine(type, 0);
6508 }
6509
6510 case BasicJsonType::value_t::object:
6511 {
6512 auto seed = combine(type, j.size());
6513 for (const auto& element : j.items())
6514 {
6515 const auto h = std::hash<string_t> {}(element.key());
6516 seed = combine(seed, h);
6517 seed = combine(seed, hash(element.value()));
6518 }
6519 return seed;
6520 }
6521
6522 case BasicJsonType::value_t::array:
6523 {
6524 auto seed = combine(type, j.size());
6525 for (const auto& element : j)
6526 {
6527 seed = combine(seed, hash(element));
6528 }
6529 return seed;
6530 }
6531
6532 case BasicJsonType::value_t::string:
6533 {
6534 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6535 return combine(type, h);
6536 }
6537
6538 case BasicJsonType::value_t::boolean:
6539 {
6540 const auto h = std::hash<bool> {}(j.template get<bool>());
6541 return combine(type, h);
6542 }
6543
6544 case BasicJsonType::value_t::number_integer:
6545 {
6546 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6547 return combine(type, h);
6548 }
6549
6550 case BasicJsonType::value_t::number_unsigned:
6551 {
6552 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6553 return combine(type, h);
6554 }
6555
6556 case BasicJsonType::value_t::number_float:
6557 {
6558 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6559 return combine(type, h);
6560 }
6561
6562 case BasicJsonType::value_t::binary:
6563 {
6564 auto seed = combine(type, j.get_binary().size());
6565 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6566 seed = combine(seed, h);
6567 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6568 for (const auto byte : j.get_binary())
6569 {
6570 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6571 }
6572 return seed;
6573 }
6574
6575 default: // LCOV_EXCL_LINE
6576 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6577 return 0; // LCOV_EXCL_LINE
6578 }
6579}
6580
6581} // namespace detail
6583
6584// #include <nlohmann/detail/input/binary_reader.hpp>
6585// __ _____ _____ _____
6586// __| | __| | | | JSON for Modern C++
6587// | | |__ | | | | | | version 3.12.0
6588// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6589//
6590// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
6591// SPDX-License-Identifier: MIT
6592
6593
6594
6595#include <algorithm> // generate_n
6596#include <array> // array
6597#include <cmath> // ldexp
6598#include <cstddef> // size_t
6599#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6600#include <cstdio> // snprintf
6601#include <cstring> // memcpy
6602#include <iterator> // back_inserter
6603#include <limits> // numeric_limits
6604#include <string> // char_traits, string
6605#include <utility> // make_pair, move
6606#include <vector> // vector
6607#ifdef __cpp_lib_byteswap
6608 #include <bit> //byteswap
6609#endif
6610
6611// #include <nlohmann/detail/exceptions.hpp>
6612
6613// #include <nlohmann/detail/input/input_adapters.hpp>
6614// __ _____ _____ _____
6615// __| | __| | | | JSON for Modern C++
6616// | | |__ | | | | | | version 3.12.0
6617// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6618//
6619// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
6620// SPDX-License-Identifier: MIT
6621
6622
6623
6624#include <array> // array
6625#include <cstddef> // size_t
6626#include <cstring> // strlen
6627#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6628#include <memory> // shared_ptr, make_shared, addressof
6629#include <numeric> // accumulate
6630#include <streambuf> // streambuf
6631#include <string> // string, char_traits
6632#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6633#include <utility> // pair, declval
6634
6635#ifndef JSON_NO_IO
6636 #include <cstdio> // FILE *
6637 #include <istream> // istream
6638#endif // JSON_NO_IO
6639
6640// #include <nlohmann/detail/exceptions.hpp>
6641
6642// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6643
6644// #include <nlohmann/detail/macro_scope.hpp>
6645
6646// #include <nlohmann/detail/meta/type_traits.hpp>
6647
6648
6650namespace detail
6651{
6652
6655
6657// input adapters //
6659
6660#ifndef JSON_NO_IO
6666{
6667 public:
6668 using char_type = char;
6669
6671 explicit file_input_adapter(std::FILE* f) noexcept
6672 : m_file(f)
6673 {
6674 JSON_ASSERT(m_file != nullptr);
6675 }
6676
6677 // make class move-only
6680 file_input_adapter& operator=(const file_input_adapter&) = delete;
6683
6684 std::char_traits<char>::int_type get_character() noexcept
6685 {
6686 return std::fgetc(m_file);
6687 }
6688
6689 // returns the number of characters successfully read
6690 template<class T>
6691 std::size_t get_elements(T* dest, std::size_t count = 1)
6692 {
6693 return fread(dest, 1, sizeof(T) * count, m_file);
6694 }
6695
6696 private:
6698 std::FILE* m_file;
6699};
6700
6711{
6712 public:
6713 using char_type = char;
6714
6716 {
6717 // clear stream flags; we use underlying streambuf I/O, do not
6718 // maintain ifstream flags, except eof
6719 if (is != nullptr)
6720 {
6721 is->clear(is->rdstate() & std::ios::eofbit);
6722 }
6723 }
6724
6725 explicit input_stream_adapter(std::istream& i)
6726 : is(&i), sb(i.rdbuf())
6727 {}
6728
6729 // deleted because of pointer members
6733
6735 : is(rhs.is), sb(rhs.sb)
6736 {
6737 rhs.is = nullptr;
6738 rhs.sb = nullptr;
6739 }
6740
6741 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6742 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6743 // end up as the same value, e.g., 0xFFFFFFFF.
6744 std::char_traits<char>::int_type get_character()
6745 {
6746 auto res = sb->sbumpc();
6747 // set eof manually, as we don't use the istream interface.
6748 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6749 {
6750 is->clear(is->rdstate() | std::ios::eofbit);
6751 }
6752 return res;
6753 }
6754
6755 template<class T>
6756 std::size_t get_elements(T* dest, std::size_t count = 1)
6757 {
6758 auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
6759 if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T)))
6760 {
6761 is->clear(is->rdstate() | std::ios::eofbit);
6762 }
6763 return res;
6764 }
6765
6766 private:
6768 std::istream* is = nullptr;
6769 std::streambuf* sb = nullptr;
6770};
6771#endif // JSON_NO_IO
6772
6773// General-purpose iterator-based adapter. It might not be as fast as
6774// theoretically possible for some containers, but it is extremely versatile.
6775template<typename IteratorType>
6777{
6778 public:
6779 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6780
6781 iterator_input_adapter(IteratorType first, IteratorType last)
6782 : current(std::move(first)), end(std::move(last))
6783 {}
6784
6786 {
6788 {
6790 std::advance(current, 1);
6791 return result;
6792 }
6793
6795 }
6796
6797 // for general iterators, we cannot really do something better than falling back to processing the range one-by-one
6798 template<class T>
6799 std::size_t get_elements(T* dest, std::size_t count = 1)
6800 {
6801 auto* ptr = reinterpret_cast<char*>(dest);
6802 for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index)
6803 {
6805 {
6806 ptr[read_index] = static_cast<char>(*current);
6807 std::advance(current, 1);
6808 }
6809 else
6810 {
6811 return read_index;
6812 }
6813 }
6814 return count * sizeof(T);
6815 }
6816
6817 private:
6818 IteratorType current;
6819 IteratorType end;
6820
6821 template<typename BaseInputAdapter, size_t T>
6823
6824 bool empty() const
6825 {
6826 return current == end;
6827 }
6828};
6829
6830template<typename BaseInputAdapter, size_t T>
6832
6833template<typename BaseInputAdapter>
6834struct wide_string_input_helper<BaseInputAdapter, 4>
6835{
6836 // UTF-32
6837 static void fill_buffer(BaseInputAdapter& input,
6838 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6839 size_t& utf8_bytes_index,
6840 size_t& utf8_bytes_filled)
6841 {
6842 utf8_bytes_index = 0;
6843
6844 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6845 {
6846 utf8_bytes[0] = std::char_traits<char>::eof();
6847 utf8_bytes_filled = 1;
6848 }
6849 else
6850 {
6851 // get the current character
6852 const auto wc = input.get_character();
6853
6854 // UTF-32 to UTF-8 encoding
6855 if (wc < 0x80)
6856 {
6857 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6858 utf8_bytes_filled = 1;
6859 }
6860 else if (wc <= 0x7FF)
6861 {
6862 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6863 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6864 utf8_bytes_filled = 2;
6865 }
6866 else if (wc <= 0xFFFF)
6867 {
6868 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6869 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6870 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6871 utf8_bytes_filled = 3;
6872 }
6873 else if (wc <= 0x10FFFF)
6874 {
6875 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6876 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6877 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6878 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6879 utf8_bytes_filled = 4;
6880 }
6881 else
6882 {
6883 // unknown character
6884 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6885 utf8_bytes_filled = 1;
6886 }
6887 }
6888 }
6889};
6890
6891template<typename BaseInputAdapter>
6892struct wide_string_input_helper<BaseInputAdapter, 2>
6893{
6894 // UTF-16
6895 static void fill_buffer(BaseInputAdapter& input,
6896 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6897 size_t& utf8_bytes_index,
6898 size_t& utf8_bytes_filled)
6899 {
6900 utf8_bytes_index = 0;
6901
6902 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6903 {
6904 utf8_bytes[0] = std::char_traits<char>::eof();
6905 utf8_bytes_filled = 1;
6906 }
6907 else
6908 {
6909 // get the current character
6910 const auto wc = input.get_character();
6911
6912 // UTF-16 to UTF-8 encoding
6913 if (wc < 0x80)
6914 {
6915 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6916 utf8_bytes_filled = 1;
6917 }
6918 else if (wc <= 0x7FF)
6919 {
6920 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6921 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6922 utf8_bytes_filled = 2;
6923 }
6924 else if (0xD800 > wc || wc >= 0xE000)
6925 {
6926 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6927 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6928 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6929 utf8_bytes_filled = 3;
6930 }
6931 else
6932 {
6933 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6934 {
6935 const auto wc2 = static_cast<unsigned int>(input.get_character());
6936 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6937 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6938 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6939 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6940 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6941 utf8_bytes_filled = 4;
6942 }
6943 else
6944 {
6945 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6946 utf8_bytes_filled = 1;
6947 }
6948 }
6949 }
6950 }
6951};
6952
6953// Wraps another input adapter to convert wide character types into individual bytes.
6954template<typename BaseInputAdapter, typename WideCharType>
6956{
6957 public:
6958 using char_type = char;
6959
6960 wide_string_input_adapter(BaseInputAdapter base)
6961 : base_adapter(base) {}
6962
6963 typename std::char_traits<char>::int_type get_character() noexcept
6964 {
6965 // check if the buffer needs to be filled
6967 {
6968 fill_buffer<sizeof(WideCharType)>();
6969
6972 }
6973
6974 // use buffer
6977 return utf8_bytes[utf8_bytes_index++];
6978 }
6979
6980 // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
6981 template<class T>
6982 std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
6983 {
6984 JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
6985 }
6986
6987 private:
6988 BaseInputAdapter base_adapter;
6989
6990 template<size_t T>
6995
6997 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6998
7000 std::size_t utf8_bytes_index = 0;
7002 std::size_t utf8_bytes_filled = 0;
7003};
7004
7005template<typename IteratorType, typename Enable = void>
7007{
7008 using iterator_type = IteratorType;
7009 using char_type = typename std::iterator_traits<iterator_type>::value_type;
7011
7012 static adapter_type create(IteratorType first, IteratorType last)
7013 {
7014 return adapter_type(std::move(first), std::move(last));
7015 }
7016};
7017
7018template<typename T>
7020{
7021 using value_type = typename std::iterator_traits<T>::value_type;
7022 enum // NOLINT(cppcoreguidelines-use-enum-class)
7023 {
7024 value = sizeof(value_type) > 1
7025 };
7026};
7027
7028template<typename IteratorType>
7030{
7031 using iterator_type = IteratorType;
7032 using char_type = typename std::iterator_traits<iterator_type>::value_type;
7035
7036 static adapter_type create(IteratorType first, IteratorType last)
7037 {
7038 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
7039 }
7040};
7041
7042// General purpose iterator-based input
7043template<typename IteratorType>
7045{
7047 return factory_type::create(first, last);
7048}
7049
7050// Convenience shorthand from container to iterator
7051// Enables ADL on begin(container) and end(container)
7052// Encloses the using declarations in namespace for not to leak them to outside scope
7053
7054namespace container_input_adapter_factory_impl
7055{
7056
7057using std::begin;
7058using std::end;
7059
7060template<typename ContainerType, typename Enable = void>
7062
7063template<typename ContainerType>
7065 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
7066 {
7067 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
7068
7069 static adapter_type create(const ContainerType& container)
7070{
7071 return input_adapter(begin(container), end(container));
7072}
7073 };
7074
7075} // namespace container_input_adapter_factory_impl
7076
7077template<typename ContainerType>
7082
7083// specialization for std::string
7084using string_input_adapter_type = decltype(input_adapter(std::declval<std::string>()));
7085
7086#ifndef JSON_NO_IO
7087// Special cases with fast paths
7088inline file_input_adapter input_adapter(std::FILE* file)
7089{
7090 if (file == nullptr)
7091 {
7092 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));
7093 }
7094 return file_input_adapter(file);
7095}
7096
7097inline input_stream_adapter input_adapter(std::istream& stream)
7098{
7099 return input_stream_adapter(stream);
7100}
7101
7102inline input_stream_adapter input_adapter(std::istream&& stream)
7103{
7104 return input_stream_adapter(stream);
7105}
7106#endif // JSON_NO_IO
7107
7108using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
7109
7110// Null-delimited strings, and the like.
7111template < typename CharT,
7112 typename std::enable_if <
7113 std::is_pointer<CharT>::value&&
7114 !std::is_array<CharT>::value&&
7115 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
7116 sizeof(typename std::remove_pointer<CharT>::type) == 1,
7117 int >::type = 0 >
7119{
7120 if (b == nullptr)
7121 {
7122 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));
7123 }
7124 auto length = std::strlen(reinterpret_cast<const char*>(b));
7125 const auto* ptr = reinterpret_cast<const char*>(b);
7126 return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck]
7127}
7128
7129template<typename T, std::size_t N>
7130auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
7131{
7132 return input_adapter(array, array + N);
7133}
7134
7135// This class only handles inputs of input_buffer_adapter type.
7136// It's required so that expressions like {ptr, len} can be implicitly cast
7137// to the correct adapter.
7139{
7140 public:
7141 template < typename CharT,
7142 typename std::enable_if <
7143 std::is_pointer<CharT>::value&&
7144 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
7145 sizeof(typename std::remove_pointer<CharT>::type) == 1,
7146 int >::type = 0 >
7147 span_input_adapter(CharT b, std::size_t l)
7148 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
7149
7150 template<class IteratorType,
7151 typename std::enable_if<
7152 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
7153 int>::type = 0>
7154 span_input_adapter(IteratorType first, IteratorType last)
7155 : ia(input_adapter(first, last)) {}
7156
7158 {
7159 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
7160 }
7161
7162 private:
7164};
7165
7166} // namespace detail
7168
7169// #include <nlohmann/detail/input/json_sax.hpp>
7170// __ _____ _____ _____
7171// __| | __| | | | JSON for Modern C++
7172// | | |__ | | | | | | version 3.12.0
7173// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7174//
7175// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
7176// SPDX-License-Identifier: MIT
7177
7178
7179
7180#include <cstddef>
7181#include <string> // string
7182#include <type_traits> // enable_if_t
7183#include <utility> // move
7184#include <vector> // vector
7185
7186// #include <nlohmann/detail/exceptions.hpp>
7187
7188// #include <nlohmann/detail/input/lexer.hpp>
7189// __ _____ _____ _____
7190// __| | __| | | | JSON for Modern C++
7191// | | |__ | | | | | | version 3.12.0
7192// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7193//
7194// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
7195// SPDX-License-Identifier: MIT
7196
7197
7198
7199#include <array> // array
7200#include <clocale> // localeconv
7201#include <cstddef> // size_t
7202#include <cstdio> // snprintf
7203#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7204#include <initializer_list> // initializer_list
7205#include <string> // char_traits, string
7206#include <utility> // move
7207#include <vector> // vector
7208
7209// #include <nlohmann/detail/input/input_adapters.hpp>
7210
7211// #include <nlohmann/detail/input/position_t.hpp>
7212
7213// #include <nlohmann/detail/macro_scope.hpp>
7214
7215// #include <nlohmann/detail/meta/type_traits.hpp>
7216
7217
7219namespace detail
7220{
7221
7223// lexer //
7225
7226template<typename BasicJsonType>
7228{
7229 public:
7251
7255 static const char* token_type_name(const token_type t) noexcept
7256 {
7257 switch (t)
7258 {
7260 return "<uninitialized>";
7262 return "true literal";
7264 return "false literal";
7266 return "null literal";
7268 return "string literal";
7272 return "number literal";
7274 return "'['";
7276 return "'{'";
7278 return "']'";
7280 return "'}'";
7282 return "':'";
7284 return "','";
7286 return "<parse error>";
7288 return "end of input";
7290 return "'[', '{', or a literal";
7291 // LCOV_EXCL_START
7292 default: // catch non-enum values
7293 return "unknown token";
7294 // LCOV_EXCL_STOP
7295 }
7296 }
7297};
7303template<typename BasicJsonType, typename InputAdapterType>
7304class lexer : public lexer_base<BasicJsonType>
7305{
7306 using number_integer_t = typename BasicJsonType::number_integer_t;
7307 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7308 using number_float_t = typename BasicJsonType::number_float_t;
7309 using string_t = typename BasicJsonType::string_t;
7310 using char_type = typename InputAdapterType::char_type;
7312
7313 public:
7315
7316 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7317 : ia(std::move(adapter))
7318 , ignore_comments(ignore_comments_)
7320 {}
7321
7322 // deleted because of pointer members
7323 lexer(const lexer&) = delete;
7324 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7325 lexer& operator=(lexer&) = delete;
7326 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7327 ~lexer() = default;
7328
7329 private:
7331 // locales
7333
7336 static char get_decimal_point() noexcept
7337 {
7338 const auto* loc = localeconv();
7339 JSON_ASSERT(loc != nullptr);
7340 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7341 }
7342
7344 // scan functions
7346
7363 {
7364 // this function only makes sense after reading `\u`
7365 JSON_ASSERT(current == 'u');
7366 int codepoint = 0;
7367
7368 const auto factors = { 12u, 8u, 4u, 0u };
7369 for (const auto factor : factors)
7370 {
7371 get();
7372
7373 if (current >= '0' && current <= '9')
7374 {
7375 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7376 }
7377 else if (current >= 'A' && current <= 'F')
7378 {
7379 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7380 }
7381 else if (current >= 'a' && current <= 'f')
7382 {
7383 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7384 }
7385 else
7386 {
7387 return -1;
7388 }
7389 }
7390
7391 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7392 return codepoint;
7393 }
7394
7410 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7411 {
7412 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7413 add(current);
7414
7415 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7416 {
7417 get();
7418 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7419 {
7420 add(current);
7421 }
7422 else
7423 {
7424 error_message = "invalid string: ill-formed UTF-8 byte";
7425 return false;
7426 }
7427 }
7428
7429 return true;
7430 }
7431
7448 {
7449 // reset token_buffer (ignore opening quote)
7450 reset();
7451
7452 // we entered the function by reading an open quote
7453 JSON_ASSERT(current == '\"');
7454
7455 while (true)
7456 {
7457 // get the next character
7458 switch (get())
7459 {
7460 // end of file while parsing the string
7462 {
7463 error_message = "invalid string: missing closing quote";
7464 return token_type::parse_error;
7465 }
7466
7467 // closing quote
7468 case '\"':
7469 {
7470 return token_type::value_string;
7471 }
7472
7473 // escapes
7474 case '\\':
7475 {
7476 switch (get())
7477 {
7478 // quotation mark
7479 case '\"':
7480 add('\"');
7481 break;
7482 // reverse solidus
7483 case '\\':
7484 add('\\');
7485 break;
7486 // solidus
7487 case '/':
7488 add('/');
7489 break;
7490 // backspace
7491 case 'b':
7492 add('\b');
7493 break;
7494 // form feed
7495 case 'f':
7496 add('\f');
7497 break;
7498 // line feed
7499 case 'n':
7500 add('\n');
7501 break;
7502 // carriage return
7503 case 'r':
7504 add('\r');
7505 break;
7506 // tab
7507 case 't':
7508 add('\t');
7509 break;
7510
7511 // unicode escapes
7512 case 'u':
7513 {
7514 const int codepoint1 = get_codepoint();
7515 int codepoint = codepoint1; // start with codepoint1
7516
7517 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7518 {
7519 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7520 return token_type::parse_error;
7521 }
7522
7523 // check if code point is a high surrogate
7524 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7525 {
7526 // expect next \uxxxx entry
7527 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7528 {
7529 const int codepoint2 = get_codepoint();
7530
7531 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7532 {
7533 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7534 return token_type::parse_error;
7535 }
7536
7537 // check if codepoint2 is a low surrogate
7538 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7539 {
7540 // overwrite codepoint
7541 codepoint = static_cast<int>(
7542 // high surrogate occupies the most significant 22 bits
7543 (static_cast<unsigned int>(codepoint1) << 10u)
7544 // low surrogate occupies the least significant 15 bits
7545 + static_cast<unsigned int>(codepoint2)
7546 // there is still the 0xD800, 0xDC00, and 0x10000 noise
7547 // in the result, so we have to subtract with:
7548 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7549 - 0x35FDC00u);
7550 }
7551 else
7552 {
7553 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7554 return token_type::parse_error;
7555 }
7556 }
7557 else
7558 {
7559 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7560 return token_type::parse_error;
7561 }
7562 }
7563 else
7564 {
7565 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7566 {
7567 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7568 return token_type::parse_error;
7569 }
7570 }
7571
7572 // the result of the above calculation yields a proper codepoint
7573 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7574
7575 // translate codepoint into bytes
7576 if (codepoint < 0x80)
7577 {
7578 // 1-byte characters: 0xxxxxxx (ASCII)
7579 add(static_cast<char_int_type>(codepoint));
7580 }
7581 else if (codepoint <= 0x7FF)
7582 {
7583 // 2-byte characters: 110xxxxx 10xxxxxx
7584 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7585 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7586 }
7587 else if (codepoint <= 0xFFFF)
7588 {
7589 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7590 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7591 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7592 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7593 }
7594 else
7595 {
7596 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7597 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7598 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7599 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7600 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7601 }
7602
7603 break;
7604 }
7605
7606 // other characters after escape
7607 default:
7608 error_message = "invalid string: forbidden character after backslash";
7609 return token_type::parse_error;
7610 }
7611
7612 break;
7613 }
7614
7615 // invalid control characters
7616 case 0x00:
7617 {
7618 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7619 return token_type::parse_error;
7620 }
7621
7622 case 0x01:
7623 {
7624 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7625 return token_type::parse_error;
7626 }
7627
7628 case 0x02:
7629 {
7630 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7631 return token_type::parse_error;
7632 }
7633
7634 case 0x03:
7635 {
7636 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7637 return token_type::parse_error;
7638 }
7639
7640 case 0x04:
7641 {
7642 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7643 return token_type::parse_error;
7644 }
7645
7646 case 0x05:
7647 {
7648 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7649 return token_type::parse_error;
7650 }
7651
7652 case 0x06:
7653 {
7654 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7655 return token_type::parse_error;
7656 }
7657
7658 case 0x07:
7659 {
7660 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7661 return token_type::parse_error;
7662 }
7663
7664 case 0x08:
7665 {
7666 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7667 return token_type::parse_error;
7668 }
7669
7670 case 0x09:
7671 {
7672 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7673 return token_type::parse_error;
7674 }
7675
7676 case 0x0A:
7677 {
7678 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7679 return token_type::parse_error;
7680 }
7681
7682 case 0x0B:
7683 {
7684 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7685 return token_type::parse_error;
7686 }
7687
7688 case 0x0C:
7689 {
7690 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7691 return token_type::parse_error;
7692 }
7693
7694 case 0x0D:
7695 {
7696 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7697 return token_type::parse_error;
7698 }
7699
7700 case 0x0E:
7701 {
7702 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7703 return token_type::parse_error;
7704 }
7705
7706 case 0x0F:
7707 {
7708 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7709 return token_type::parse_error;
7710 }
7711
7712 case 0x10:
7713 {
7714 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7715 return token_type::parse_error;
7716 }
7717
7718 case 0x11:
7719 {
7720 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7721 return token_type::parse_error;
7722 }
7723
7724 case 0x12:
7725 {
7726 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7727 return token_type::parse_error;
7728 }
7729
7730 case 0x13:
7731 {
7732 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7733 return token_type::parse_error;
7734 }
7735
7736 case 0x14:
7737 {
7738 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7739 return token_type::parse_error;
7740 }
7741
7742 case 0x15:
7743 {
7744 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7745 return token_type::parse_error;
7746 }
7747
7748 case 0x16:
7749 {
7750 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7751 return token_type::parse_error;
7752 }
7753
7754 case 0x17:
7755 {
7756 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7757 return token_type::parse_error;
7758 }
7759
7760 case 0x18:
7761 {
7762 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7763 return token_type::parse_error;
7764 }
7765
7766 case 0x19:
7767 {
7768 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7769 return token_type::parse_error;
7770 }
7771
7772 case 0x1A:
7773 {
7774 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7775 return token_type::parse_error;
7776 }
7777
7778 case 0x1B:
7779 {
7780 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7781 return token_type::parse_error;
7782 }
7783
7784 case 0x1C:
7785 {
7786 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7787 return token_type::parse_error;
7788 }
7789
7790 case 0x1D:
7791 {
7792 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7793 return token_type::parse_error;
7794 }
7795
7796 case 0x1E:
7797 {
7798 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7799 return token_type::parse_error;
7800 }
7801
7802 case 0x1F:
7803 {
7804 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7805 return token_type::parse_error;
7806 }
7807
7808 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7809 case 0x20:
7810 case 0x21:
7811 case 0x23:
7812 case 0x24:
7813 case 0x25:
7814 case 0x26:
7815 case 0x27:
7816 case 0x28:
7817 case 0x29:
7818 case 0x2A:
7819 case 0x2B:
7820 case 0x2C:
7821 case 0x2D:
7822 case 0x2E:
7823 case 0x2F:
7824 case 0x30:
7825 case 0x31:
7826 case 0x32:
7827 case 0x33:
7828 case 0x34:
7829 case 0x35:
7830 case 0x36:
7831 case 0x37:
7832 case 0x38:
7833 case 0x39:
7834 case 0x3A:
7835 case 0x3B:
7836 case 0x3C:
7837 case 0x3D:
7838 case 0x3E:
7839 case 0x3F:
7840 case 0x40:
7841 case 0x41:
7842 case 0x42:
7843 case 0x43:
7844 case 0x44:
7845 case 0x45:
7846 case 0x46:
7847 case 0x47:
7848 case 0x48:
7849 case 0x49:
7850 case 0x4A:
7851 case 0x4B:
7852 case 0x4C:
7853 case 0x4D:
7854 case 0x4E:
7855 case 0x4F:
7856 case 0x50:
7857 case 0x51:
7858 case 0x52:
7859 case 0x53:
7860 case 0x54:
7861 case 0x55:
7862 case 0x56:
7863 case 0x57:
7864 case 0x58:
7865 case 0x59:
7866 case 0x5A:
7867 case 0x5B:
7868 case 0x5D:
7869 case 0x5E:
7870 case 0x5F:
7871 case 0x60:
7872 case 0x61:
7873 case 0x62:
7874 case 0x63:
7875 case 0x64:
7876 case 0x65:
7877 case 0x66:
7878 case 0x67:
7879 case 0x68:
7880 case 0x69:
7881 case 0x6A:
7882 case 0x6B:
7883 case 0x6C:
7884 case 0x6D:
7885 case 0x6E:
7886 case 0x6F:
7887 case 0x70:
7888 case 0x71:
7889 case 0x72:
7890 case 0x73:
7891 case 0x74:
7892 case 0x75:
7893 case 0x76:
7894 case 0x77:
7895 case 0x78:
7896 case 0x79:
7897 case 0x7A:
7898 case 0x7B:
7899 case 0x7C:
7900 case 0x7D:
7901 case 0x7E:
7902 case 0x7F:
7903 {
7904 add(current);
7905 break;
7906 }
7907
7908 // U+0080..U+07FF: bytes C2..DF 80..BF
7909 case 0xC2:
7910 case 0xC3:
7911 case 0xC4:
7912 case 0xC5:
7913 case 0xC6:
7914 case 0xC7:
7915 case 0xC8:
7916 case 0xC9:
7917 case 0xCA:
7918 case 0xCB:
7919 case 0xCC:
7920 case 0xCD:
7921 case 0xCE:
7922 case 0xCF:
7923 case 0xD0:
7924 case 0xD1:
7925 case 0xD2:
7926 case 0xD3:
7927 case 0xD4:
7928 case 0xD5:
7929 case 0xD6:
7930 case 0xD7:
7931 case 0xD8:
7932 case 0xD9:
7933 case 0xDA:
7934 case 0xDB:
7935 case 0xDC:
7936 case 0xDD:
7937 case 0xDE:
7938 case 0xDF:
7939 {
7940 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7941 {
7942 return token_type::parse_error;
7943 }
7944 break;
7945 }
7946
7947 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7948 case 0xE0:
7949 {
7950 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7951 {
7952 return token_type::parse_error;
7953 }
7954 break;
7955 }
7956
7957 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7958 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7959 case 0xE1:
7960 case 0xE2:
7961 case 0xE3:
7962 case 0xE4:
7963 case 0xE5:
7964 case 0xE6:
7965 case 0xE7:
7966 case 0xE8:
7967 case 0xE9:
7968 case 0xEA:
7969 case 0xEB:
7970 case 0xEC:
7971 case 0xEE:
7972 case 0xEF:
7973 {
7974 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7975 {
7976 return token_type::parse_error;
7977 }
7978 break;
7979 }
7980
7981 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7982 case 0xED:
7983 {
7984 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7985 {
7986 return token_type::parse_error;
7987 }
7988 break;
7989 }
7990
7991 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7992 case 0xF0:
7993 {
7994 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7995 {
7996 return token_type::parse_error;
7997 }
7998 break;
7999 }
8000
8001 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
8002 case 0xF1:
8003 case 0xF2:
8004 case 0xF3:
8005 {
8006 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8007 {
8008 return token_type::parse_error;
8009 }
8010 break;
8011 }
8012
8013 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
8014 case 0xF4:
8015 {
8016 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
8017 {
8018 return token_type::parse_error;
8019 }
8020 break;
8021 }
8022
8023 // the remaining bytes (80..C1 and F5..FF) are ill-formed
8024 default:
8025 {
8026 error_message = "invalid string: ill-formed UTF-8 byte";
8027 return token_type::parse_error;
8028 }
8029 }
8030 }
8031 }
8032
8038 {
8039 switch (get())
8040 {
8041 // single-line comments skip input until a newline or EOF is read
8042 case '/':
8043 {
8044 while (true)
8045 {
8046 switch (get())
8047 {
8048 case '\n':
8049 case '\r':
8051 case '\0':
8052 return true;
8053
8054 default:
8055 break;
8056 }
8057 }
8058
8060 }
8061
8062 // multi-line comments skip input until */ is read
8063 case '*':
8064 {
8065 while (true)
8066 {
8067 switch (get())
8068 {
8070 case '\0':
8071 {
8072 error_message = "invalid comment; missing closing '*/'";
8073 return false;
8074 }
8075
8076 case '*':
8077 {
8078 switch (get())
8079 {
8080 case '/':
8081 return true;
8082
8083 default:
8084 {
8085 unget();
8086 continue;
8087 }
8088 }
8089 }
8090
8091 default:
8092 continue;
8093 }
8094 }
8095
8097 }
8098
8099 // unexpected character after reading '/'
8100 default:
8101 {
8102 error_message = "invalid comment; expecting '/' or '*' after '/'";
8103 return false;
8104 }
8105 }
8106 }
8107
8109 static void strtof(float& f, const char* str, char** endptr) noexcept
8110 {
8111 f = std::strtof(str, endptr);
8112 }
8113
8115 static void strtof(double& f, const char* str, char** endptr) noexcept
8116 {
8117 f = std::strtod(str, endptr);
8118 }
8119
8121 static void strtof(long double& f, const char* str, char** endptr) noexcept
8122 {
8123 f = std::strtold(str, endptr);
8124 }
8125
8166 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.
8167 {
8168 // reset token_buffer to store the number's bytes
8169 reset();
8170
8171 // the type of the parsed number; initially set to unsigned; will be
8172 // changed if minus sign, decimal point, or exponent is read
8173 token_type number_type = token_type::value_unsigned;
8174
8175 // state (init): we just found out we need to scan a number
8176 switch (current)
8177 {
8178 case '-':
8179 {
8180 add(current);
8181 goto scan_number_minus;
8182 }
8183
8184 case '0':
8185 {
8186 add(current);
8187 goto scan_number_zero;
8188 }
8189
8190 case '1':
8191 case '2':
8192 case '3':
8193 case '4':
8194 case '5':
8195 case '6':
8196 case '7':
8197 case '8':
8198 case '9':
8199 {
8200 add(current);
8201 goto scan_number_any1;
8202 }
8203
8204 // all other characters are rejected outside scan_number()
8205 default: // LCOV_EXCL_LINE
8206 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8207 }
8208
8209scan_number_minus:
8210 // state: we just parsed a leading minus sign
8211 number_type = token_type::value_integer;
8212 switch (get())
8213 {
8214 case '0':
8215 {
8216 add(current);
8217 goto scan_number_zero;
8218 }
8219
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_any1;
8232 }
8233
8234 default:
8235 {
8236 error_message = "invalid number; expected digit after '-'";
8237 return token_type::parse_error;
8238 }
8239 }
8240
8241scan_number_zero:
8242 // state: we just parse a zero (maybe with a leading minus sign)
8243 switch (get())
8244 {
8245 case '.':
8246 {
8249 goto scan_number_decimal1;
8250 }
8251
8252 case 'e':
8253 case 'E':
8254 {
8255 add(current);
8256 goto scan_number_exponent;
8257 }
8258
8259 default:
8260 goto scan_number_done;
8261 }
8262
8263scan_number_any1:
8264 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8265 switch (get())
8266 {
8267 case '0':
8268 case '1':
8269 case '2':
8270 case '3':
8271 case '4':
8272 case '5':
8273 case '6':
8274 case '7':
8275 case '8':
8276 case '9':
8277 {
8278 add(current);
8279 goto scan_number_any1;
8280 }
8281
8282 case '.':
8283 {
8286 goto scan_number_decimal1;
8287 }
8288
8289 case 'e':
8290 case 'E':
8291 {
8292 add(current);
8293 goto scan_number_exponent;
8294 }
8295
8296 default:
8297 goto scan_number_done;
8298 }
8299
8300scan_number_decimal1:
8301 // state: we just parsed a decimal point
8302 number_type = token_type::value_float;
8303 switch (get())
8304 {
8305 case '0':
8306 case '1':
8307 case '2':
8308 case '3':
8309 case '4':
8310 case '5':
8311 case '6':
8312 case '7':
8313 case '8':
8314 case '9':
8315 {
8316 add(current);
8317 goto scan_number_decimal2;
8318 }
8319
8320 default:
8321 {
8322 error_message = "invalid number; expected digit after '.'";
8323 return token_type::parse_error;
8324 }
8325 }
8326
8327scan_number_decimal2:
8328 // we just parsed at least one number after a decimal point
8329 switch (get())
8330 {
8331 case '0':
8332 case '1':
8333 case '2':
8334 case '3':
8335 case '4':
8336 case '5':
8337 case '6':
8338 case '7':
8339 case '8':
8340 case '9':
8341 {
8342 add(current);
8343 goto scan_number_decimal2;
8344 }
8345
8346 case 'e':
8347 case 'E':
8348 {
8349 add(current);
8350 goto scan_number_exponent;
8351 }
8352
8353 default:
8354 goto scan_number_done;
8355 }
8356
8357scan_number_exponent:
8358 // we just parsed an exponent
8359 number_type = token_type::value_float;
8360 switch (get())
8361 {
8362 case '+':
8363 case '-':
8364 {
8365 add(current);
8366 goto scan_number_sign;
8367 }
8368
8369 case '0':
8370 case '1':
8371 case '2':
8372 case '3':
8373 case '4':
8374 case '5':
8375 case '6':
8376 case '7':
8377 case '8':
8378 case '9':
8379 {
8380 add(current);
8381 goto scan_number_any2;
8382 }
8383
8384 default:
8385 {
8387 "invalid number; expected '+', '-', or digit after exponent";
8388 return token_type::parse_error;
8389 }
8390 }
8391
8392scan_number_sign:
8393 // we just parsed an exponent sign
8394 switch (get())
8395 {
8396 case '0':
8397 case '1':
8398 case '2':
8399 case '3':
8400 case '4':
8401 case '5':
8402 case '6':
8403 case '7':
8404 case '8':
8405 case '9':
8406 {
8407 add(current);
8408 goto scan_number_any2;
8409 }
8410
8411 default:
8412 {
8413 error_message = "invalid number; expected digit after exponent sign";
8414 return token_type::parse_error;
8415 }
8416 }
8417
8418scan_number_any2:
8419 // we just parsed a number after the exponent or exponent sign
8420 switch (get())
8421 {
8422 case '0':
8423 case '1':
8424 case '2':
8425 case '3':
8426 case '4':
8427 case '5':
8428 case '6':
8429 case '7':
8430 case '8':
8431 case '9':
8432 {
8433 add(current);
8434 goto scan_number_any2;
8435 }
8436
8437 default:
8438 goto scan_number_done;
8439 }
8440
8441scan_number_done:
8442 // unget the character after the number (we only read it to know that
8443 // we are done scanning a number)
8444 unget();
8445
8446 char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8447 errno = 0;
8448
8449 // try to parse integers first and fall back to floats
8450 if (number_type == token_type::value_unsigned)
8451 {
8452 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8453
8454 // we checked the number format before
8455 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8456
8457 if (errno != ERANGE)
8458 {
8459 value_unsigned = static_cast<number_unsigned_t>(x);
8460 if (value_unsigned == x)
8461 {
8462 return token_type::value_unsigned;
8463 }
8464 }
8465 }
8466 else if (number_type == token_type::value_integer)
8467 {
8468 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8469
8470 // we checked the number format before
8471 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8472
8473 if (errno != ERANGE)
8474 {
8475 value_integer = static_cast<number_integer_t>(x);
8476 if (value_integer == x)
8477 {
8478 return token_type::value_integer;
8479 }
8480 }
8481 }
8482
8483 // this code is reached if we parse a floating-point number or if an
8484 // integer conversion above failed
8485 strtof(value_float, token_buffer.data(), &endptr);
8486
8487 // we checked the number format before
8488 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8489
8490 return token_type::value_float;
8491 }
8492
8499 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8500 token_type return_type)
8501 {
8503 for (std::size_t i = 1; i < length; ++i)
8504 {
8506 {
8507 error_message = "invalid literal";
8508 return token_type::parse_error;
8509 }
8510 }
8511 return return_type;
8512 }
8513
8515 // input management
8517
8519 void reset() noexcept
8520 {
8521 token_buffer.clear();
8522 token_string.clear();
8523 decimal_point_position = std::string::npos;
8525 }
8526
8527 /*
8528 @brief get next character from the input
8529
8530 This function provides the interface to the used input adapter. It does
8531 not throw in case the input reached EOF, but returns a
8532 `char_traits<char>::eof()` in that case. Stores the scanned characters
8533 for use in error messages.
8534
8535 @return character read from the input
8536 */
8538 {
8541
8542 if (next_unget)
8543 {
8544 // only reset the next_unget variable and work with current
8545 next_unget = false;
8546 }
8547 else
8548 {
8549 current = ia.get_character();
8550 }
8551
8553 {
8555 }
8556
8557 if (current == '\n')
8558 {
8561 }
8562
8563 return current;
8564 }
8565
8574 void unget()
8575 {
8576 next_unget = true;
8577
8579
8580 // in case we "unget" a newline, we have to also decrement the lines_read
8582 {
8583 if (position.lines_read > 0)
8584 {
8586 }
8587 }
8588 else
8589 {
8591 }
8592
8594 {
8595 JSON_ASSERT(!token_string.empty());
8596 token_string.pop_back();
8597 }
8598 }
8599
8602 {
8603 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8604 }
8605
8606 public:
8608 // value getters
8610
8612 constexpr number_integer_t get_number_integer() const noexcept
8613 {
8614 return value_integer;
8615 }
8616
8618 constexpr number_unsigned_t get_number_unsigned() const noexcept
8619 {
8620 return value_unsigned;
8621 }
8622
8624 constexpr number_float_t get_number_float() const noexcept
8625 {
8626 return value_float;
8627 }
8628
8631 {
8632 // translate decimal points from locale back to '.' (#4084)
8633 if (decimal_point_char != '.' && decimal_point_position != std::string::npos)
8634 {
8636 }
8637 return token_buffer;
8638 }
8639
8641 // diagnostics
8643
8645 constexpr position_t get_position() const noexcept
8646 {
8647 return position;
8648 }
8649
8653 std::string get_token_string() const
8654 {
8655 // escape control characters
8656 std::string result;
8657 for (const auto c : token_string)
8658 {
8659 if (static_cast<unsigned char>(c) <= '\x1F')
8660 {
8661 // escape control characters
8662 std::array<char, 9> cs{{}};
8663 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8664 result += cs.data();
8665 }
8666 else
8667 {
8668 // add character as is
8669 result.push_back(static_cast<std::string::value_type>(c));
8670 }
8671 }
8672
8673 return result;
8674 }
8675
8678 constexpr const char* get_error_message() const noexcept
8679 {
8680 return error_message;
8681 }
8682
8684 // actual scanner
8686
8692 {
8693 if (get() == 0xEF)
8694 {
8695 // check if we completely parse the BOM
8696 return get() == 0xBB && get() == 0xBF;
8697 }
8698
8699 // the first character is not the beginning of the BOM; unget it to
8700 // process is later
8701 unget();
8702 return true;
8703 }
8704
8706 {
8707 do
8708 {
8709 get();
8710 }
8711 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8712 }
8713
8715 {
8716 // initially, skip the BOM
8717 if (position.chars_read_total == 0 && !skip_bom())
8718 {
8719 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8720 return token_type::parse_error;
8721 }
8722
8723 // read the next character and ignore whitespace
8725
8726 // ignore comments
8727 while (ignore_comments && current == '/')
8728 {
8729 if (!scan_comment())
8730 {
8731 return token_type::parse_error;
8732 }
8733
8734 // skip following whitespace
8736 }
8737
8738 switch (current)
8739 {
8740 // structural characters
8741 case '[':
8742 return token_type::begin_array;
8743 case ']':
8744 return token_type::end_array;
8745 case '{':
8746 return token_type::begin_object;
8747 case '}':
8748 return token_type::end_object;
8749 case ':':
8750 return token_type::name_separator;
8751 case ',':
8752 return token_type::value_separator;
8753
8754 // literals
8755 case 't':
8756 {
8757 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')}};
8758 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8759 }
8760 case 'f':
8761 {
8762 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')}};
8763 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8764 }
8765 case 'n':
8766 {
8767 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')}};
8768 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8769 }
8770
8771 // string
8772 case '\"':
8773 return scan_string();
8774
8775 // number
8776 case '-':
8777 case '0':
8778 case '1':
8779 case '2':
8780 case '3':
8781 case '4':
8782 case '5':
8783 case '6':
8784 case '7':
8785 case '8':
8786 case '9':
8787 return scan_number();
8788
8789 // end of input (the null byte is needed when parsing from
8790 // string literals)
8791 case '\0':
8793 return token_type::end_of_input;
8794
8795 // error
8796 default:
8797 error_message = "invalid literal";
8798 return token_type::parse_error;
8799 }
8800 }
8801
8802 private:
8804 InputAdapterType ia;
8805
8807 const bool ignore_comments = false;
8808
8811
8813 bool next_unget = false;
8814
8817
8819 std::vector<char_type> token_string {};
8820
8823
8825 const char* error_message = "";
8826
8827 // number values
8831
8835 std::size_t decimal_point_position = std::string::npos;
8836};
8837
8838} // namespace detail
8840
8841// #include <nlohmann/detail/macro_scope.hpp>
8842
8843// #include <nlohmann/detail/string_concat.hpp>
8844
8846
8855template<typename BasicJsonType>
8857{
8858 using number_integer_t = typename BasicJsonType::number_integer_t;
8859 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8860 using number_float_t = typename BasicJsonType::number_float_t;
8861 using string_t = typename BasicJsonType::string_t;
8862 using binary_t = typename BasicJsonType::binary_t;
8863
8868 virtual bool null() = 0;
8869
8875 virtual bool boolean(bool val) = 0;
8876
8882 virtual bool number_integer(number_integer_t val) = 0;
8883
8889 virtual bool number_unsigned(number_unsigned_t val) = 0;
8890
8897 virtual bool number_float(number_float_t val, const string_t& s) = 0;
8898
8905 virtual bool string(string_t& val) = 0;
8906
8913 virtual bool binary(binary_t& val) = 0;
8914
8921 virtual bool start_object(std::size_t elements) = 0;
8922
8929 virtual bool key(string_t& val) = 0;
8930
8935 virtual bool end_object() = 0;
8936
8943 virtual bool start_array(std::size_t elements) = 0;
8944
8949 virtual bool end_array() = 0;
8950
8958 virtual bool parse_error(std::size_t position,
8959 const std::string& last_token,
8960 const detail::exception& ex) = 0;
8961
8962 json_sax() = default;
8963 json_sax(const json_sax&) = default;
8964 json_sax(json_sax&&) noexcept = default;
8965 json_sax& operator=(const json_sax&) = default;
8966 json_sax& operator=(json_sax&&) noexcept = default;
8967 virtual ~json_sax() = default;
8968};
8969
8970namespace detail
8971{
8972constexpr std::size_t unknown_size()
8973{
8974 return (std::numeric_limits<std::size_t>::max)();
8975}
8976
8990template<typename BasicJsonType, typename InputAdapterType>
8992{
8993 public:
8994 using number_integer_t = typename BasicJsonType::number_integer_t;
8995 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8996 using number_float_t = typename BasicJsonType::number_float_t;
8997 using string_t = typename BasicJsonType::string_t;
8998 using binary_t = typename BasicJsonType::binary_t;
9000
9006 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr)
9007 : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
9008 {}
9009
9010 // make class move-only
9012 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9014 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9016
9017 bool null()
9018 {
9019 handle_value(nullptr);
9020 return true;
9021 }
9022
9023 bool boolean(bool val)
9024 {
9025 handle_value(val);
9026 return true;
9027 }
9028
9030 {
9031 handle_value(val);
9032 return true;
9033 }
9034
9036 {
9037 handle_value(val);
9038 return true;
9039 }
9040
9041 bool number_float(number_float_t val, const string_t& /*unused*/)
9042 {
9043 handle_value(val);
9044 return true;
9045 }
9046
9047 bool string(string_t& val)
9048 {
9049 handle_value(val);
9050 return true;
9051 }
9052
9053 bool binary(binary_t& val)
9054 {
9055 handle_value(std::move(val));
9056 return true;
9057 }
9058
9059 bool start_object(std::size_t len)
9060 {
9061 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
9062
9063#if JSON_DIAGNOSTIC_POSITIONS
9064 // Manually set the start position of the object here.
9065 // Ensure this is after the call to handle_value to ensure correct start position.
9066 if (m_lexer_ref)
9067 {
9068 // Lexer has read the first character of the object, so
9069 // subtract 1 from the position to get the correct start position.
9070 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9071 }
9072#endif
9073
9074 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9075 {
9076 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
9077 }
9078
9079 return true;
9080 }
9081
9082 bool key(string_t& val)
9083 {
9084 JSON_ASSERT(!ref_stack.empty());
9085 JSON_ASSERT(ref_stack.back()->is_object());
9086
9087 // add null at the given key and store the reference for later
9088 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
9089 return true;
9090 }
9091
9093 {
9094 JSON_ASSERT(!ref_stack.empty());
9095 JSON_ASSERT(ref_stack.back()->is_object());
9096
9097#if JSON_DIAGNOSTIC_POSITIONS
9098 if (m_lexer_ref)
9099 {
9100 // Lexer's position is past the closing brace, so set that as the end position.
9101 ref_stack.back()->end_position = m_lexer_ref->get_position();
9102 }
9103#endif
9104
9105 ref_stack.back()->set_parents();
9106 ref_stack.pop_back();
9107 return true;
9108 }
9109
9110 bool start_array(std::size_t len)
9111 {
9112 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
9113
9114#if JSON_DIAGNOSTIC_POSITIONS
9115 // Manually set the start position of the array here.
9116 // Ensure this is after the call to handle_value to ensure correct start position.
9117 if (m_lexer_ref)
9118 {
9119 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9120 }
9121#endif
9122
9123 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9124 {
9125 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
9126 }
9127
9128 return true;
9129 }
9130
9132 {
9133 JSON_ASSERT(!ref_stack.empty());
9134 JSON_ASSERT(ref_stack.back()->is_array());
9135
9136#if JSON_DIAGNOSTIC_POSITIONS
9137 if (m_lexer_ref)
9138 {
9139 // Lexer's position is past the closing bracket, so set that as the end position.
9140 ref_stack.back()->end_position = m_lexer_ref->get_position();
9141 }
9142#endif
9143
9144 ref_stack.back()->set_parents();
9145 ref_stack.pop_back();
9146 return true;
9147 }
9148
9149 template<class Exception>
9150 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9151 const Exception& ex)
9152 {
9153 errored = true;
9154 static_cast<void>(ex);
9155 if (allow_exceptions)
9156 {
9157 JSON_THROW(ex);
9158 }
9159 return false;
9160 }
9161
9162 constexpr bool is_errored() const
9163 {
9164 return errored;
9165 }
9166
9167 private:
9168
9169#if JSON_DIAGNOSTIC_POSITIONS
9170 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9171 {
9172 if (m_lexer_ref)
9173 {
9174 // Lexer has read past the current field value, so set the end position to the current position.
9175 // The start position will be set below based on the length of the string representation
9176 // of the value.
9177 v.end_position = m_lexer_ref->get_position();
9178
9179 switch (v.type())
9180 {
9181 case value_t::boolean:
9182 {
9183 // 4 and 5 are the string length of "true" and "false"
9184 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9185 break;
9186 }
9187
9188 case value_t::null:
9189 {
9190 // 4 is the string length of "null"
9191 v.start_position = v.end_position - 4;
9192 break;
9193 }
9194
9195 case value_t::string:
9196 {
9197 // include the length of the quotes, which is 2
9198 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9199 break;
9200 }
9201
9202 // As we handle the start and end positions for values created during parsing,
9203 // we do not expect the following value type to be called. Regardless, set the positions
9204 // in case this is created manually or through a different constructor. Exclude from lcov
9205 // since the exact condition of this switch is esoteric.
9206 // LCOV_EXCL_START
9207 case value_t::discarded:
9208 {
9209 v.end_position = std::string::npos;
9210 v.start_position = v.end_position;
9211 break;
9212 }
9213 // LCOV_EXCL_STOP
9214 case value_t::binary:
9215 case value_t::number_integer:
9216 case value_t::number_unsigned:
9217 case value_t::number_float:
9218 {
9219 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9220 break;
9221 }
9222 case value_t::object:
9223 case value_t::array:
9224 {
9225 // object and array are handled in start_object() and start_array() handlers
9226 // skip setting the values here.
9227 break;
9228 }
9229 default: // LCOV_EXCL_LINE
9230 // Handle all possible types discretely, default handler should never be reached.
9231 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9232 }
9233 }
9234 }
9235#endif
9236
9243 template<typename Value>
9245 BasicJsonType* handle_value(Value&& v)
9246 {
9247 if (ref_stack.empty())
9248 {
9249 root = BasicJsonType(std::forward<Value>(v));
9250
9251#if JSON_DIAGNOSTIC_POSITIONS
9252 handle_diagnostic_positions_for_json_value(root);
9253#endif
9254
9255 return &root;
9256 }
9257
9258 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9259
9260 if (ref_stack.back()->is_array())
9261 {
9262 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
9263
9264#if JSON_DIAGNOSTIC_POSITIONS
9265 handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back());
9266#endif
9267
9268 return &(ref_stack.back()->m_data.m_value.array->back());
9269 }
9270
9271 JSON_ASSERT(ref_stack.back()->is_object());
9272 JSON_ASSERT(object_element);
9273 *object_element = BasicJsonType(std::forward<Value>(v));
9274
9275#if JSON_DIAGNOSTIC_POSITIONS
9276 handle_diagnostic_positions_for_json_value(*object_element);
9277#endif
9278
9279 return object_element;
9280 }
9281
9283 BasicJsonType& root;
9285 std::vector<BasicJsonType*> ref_stack {};
9287 BasicJsonType* object_element = nullptr;
9289 bool errored = false;
9291 const bool allow_exceptions = true;
9293 lexer_t* m_lexer_ref = nullptr;
9294};
9295
9296template<typename BasicJsonType, typename InputAdapterType>
9298{
9299 public:
9300 using number_integer_t = typename BasicJsonType::number_integer_t;
9301 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9302 using number_float_t = typename BasicJsonType::number_float_t;
9303 using string_t = typename BasicJsonType::string_t;
9304 using binary_t = typename BasicJsonType::binary_t;
9305 using parser_callback_t = typename BasicJsonType::parser_callback_t;
9306 using parse_event_t = typename BasicJsonType::parse_event_t;
9308
9311 const bool allow_exceptions_ = true,
9312 lexer_t* lexer_ = nullptr)
9313 : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
9314 {
9315 keep_stack.push_back(true);
9316 }
9317
9318 // make class move-only
9320 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9322 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9324
9325 bool null()
9326 {
9327 handle_value(nullptr);
9328 return true;
9329 }
9330
9331 bool boolean(bool val)
9332 {
9333 handle_value(val);
9334 return true;
9335 }
9336
9338 {
9339 handle_value(val);
9340 return true;
9341 }
9342
9344 {
9345 handle_value(val);
9346 return true;
9347 }
9348
9349 bool number_float(number_float_t val, const string_t& /*unused*/)
9350 {
9351 handle_value(val);
9352 return true;
9353 }
9354
9355 bool string(string_t& val)
9356 {
9357 handle_value(val);
9358 return true;
9359 }
9360
9361 bool binary(binary_t& val)
9362 {
9363 handle_value(std::move(val));
9364 return true;
9365 }
9366
9367 bool start_object(std::size_t len)
9368 {
9369 // check callback for object start
9370 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
9371 keep_stack.push_back(keep);
9372
9373 auto val = handle_value(BasicJsonType::value_t::object, true);
9374 ref_stack.push_back(val.second);
9375
9376 if (ref_stack.back())
9377 {
9378
9379#if JSON_DIAGNOSTIC_POSITIONS
9380 // Manually set the start position of the object here.
9381 // Ensure this is after the call to handle_value to ensure correct start position.
9382 if (m_lexer_ref)
9383 {
9384 // Lexer has read the first character of the object, so
9385 // subtract 1 from the position to get the correct start position.
9386 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9387 }
9388#endif
9389
9390 // check object limit
9391 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9392 {
9393 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
9394 }
9395 }
9396 return true;
9397 }
9398
9399 bool key(string_t& val)
9400 {
9401 BasicJsonType k = BasicJsonType(val);
9402
9403 // check callback for the key
9404 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
9405 key_keep_stack.push_back(keep);
9406
9407 // add discarded value at the given key and store the reference for later
9408 if (keep && ref_stack.back())
9409 {
9410 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
9411 }
9412
9413 return true;
9414 }
9415
9417 {
9418 if (ref_stack.back())
9419 {
9420 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
9421 {
9422 // discard object
9423 *ref_stack.back() = discarded;
9424
9425#if JSON_DIAGNOSTIC_POSITIONS
9426 // Set start/end positions for discarded object.
9427 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9428#endif
9429 }
9430 else
9431 {
9432
9433#if JSON_DIAGNOSTIC_POSITIONS
9434 if (m_lexer_ref)
9435 {
9436 // Lexer's position is past the closing brace, so set that as the end position.
9437 ref_stack.back()->end_position = m_lexer_ref->get_position();
9438 }
9439#endif
9440
9441 ref_stack.back()->set_parents();
9442 }
9443 }
9444
9445 JSON_ASSERT(!ref_stack.empty());
9446 JSON_ASSERT(!keep_stack.empty());
9447 ref_stack.pop_back();
9448 keep_stack.pop_back();
9449
9450 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
9451 {
9452 // remove discarded value
9453 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
9454 {
9455 if (it->is_discarded())
9456 {
9457 ref_stack.back()->erase(it);
9458 break;
9459 }
9460 }
9461 }
9462
9463 return true;
9464 }
9465
9466 bool start_array(std::size_t len)
9467 {
9468 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
9469 keep_stack.push_back(keep);
9470
9471 auto val = handle_value(BasicJsonType::value_t::array, true);
9472 ref_stack.push_back(val.second);
9473
9474 if (ref_stack.back())
9475 {
9476
9477#if JSON_DIAGNOSTIC_POSITIONS
9478 // Manually set the start position of the array here.
9479 // Ensure this is after the call to handle_value to ensure correct start position.
9480 if (m_lexer_ref)
9481 {
9482 // Lexer has read the first character of the array, so
9483 // subtract 1 from the position to get the correct start position.
9484 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9485 }
9486#endif
9487
9488 // check array limit
9489 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9490 {
9491 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
9492 }
9493 }
9494
9495 return true;
9496 }
9497
9499 {
9500 bool keep = true;
9501
9502 if (ref_stack.back())
9503 {
9504 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
9505 if (keep)
9506 {
9507
9508#if JSON_DIAGNOSTIC_POSITIONS
9509 if (m_lexer_ref)
9510 {
9511 // Lexer's position is past the closing bracket, so set that as the end position.
9512 ref_stack.back()->end_position = m_lexer_ref->get_position();
9513 }
9514#endif
9515
9516 ref_stack.back()->set_parents();
9517 }
9518 else
9519 {
9520 // discard array
9521 *ref_stack.back() = discarded;
9522
9523#if JSON_DIAGNOSTIC_POSITIONS
9524 // Set start/end positions for discarded array.
9525 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9526#endif
9527 }
9528 }
9529
9530 JSON_ASSERT(!ref_stack.empty());
9531 JSON_ASSERT(!keep_stack.empty());
9532 ref_stack.pop_back();
9533 keep_stack.pop_back();
9534
9535 // remove discarded value
9536 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
9537 {
9538 ref_stack.back()->m_data.m_value.array->pop_back();
9539 }
9540
9541 return true;
9542 }
9543
9544 template<class Exception>
9545 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9546 const Exception& ex)
9547 {
9548 errored = true;
9549 static_cast<void>(ex);
9550 if (allow_exceptions)
9551 {
9552 JSON_THROW(ex);
9553 }
9554 return false;
9555 }
9556
9557 constexpr bool is_errored() const
9558 {
9559 return errored;
9560 }
9561
9562 private:
9563
9564#if JSON_DIAGNOSTIC_POSITIONS
9565 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9566 {
9567 if (m_lexer_ref)
9568 {
9569 // Lexer has read past the current field value, so set the end position to the current position.
9570 // The start position will be set below based on the length of the string representation
9571 // of the value.
9572 v.end_position = m_lexer_ref->get_position();
9573
9574 switch (v.type())
9575 {
9576 case value_t::boolean:
9577 {
9578 // 4 and 5 are the string length of "true" and "false"
9579 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9580 break;
9581 }
9582
9583 case value_t::null:
9584 {
9585 // 4 is the string length of "null"
9586 v.start_position = v.end_position - 4;
9587 break;
9588 }
9589
9590 case value_t::string:
9591 {
9592 // include the length of the quotes, which is 2
9593 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9594 break;
9595 }
9596
9597 case value_t::discarded:
9598 {
9599 v.end_position = std::string::npos;
9600 v.start_position = v.end_position;
9601 break;
9602 }
9603
9604 case value_t::binary:
9605 case value_t::number_integer:
9606 case value_t::number_unsigned:
9607 case value_t::number_float:
9608 {
9609 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9610 break;
9611 }
9612
9613 case value_t::object:
9614 case value_t::array:
9615 {
9616 // object and array are handled in start_object() and start_array() handlers
9617 // skip setting the values here.
9618 break;
9619 }
9620 default: // LCOV_EXCL_LINE
9621 // Handle all possible types discretely, default handler should never be reached.
9622 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9623 }
9624 }
9625 }
9626#endif
9627
9643 template<typename Value>
9644 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
9645 {
9646 JSON_ASSERT(!keep_stack.empty());
9647
9648 // do not handle this value if we know it would be added to a discarded
9649 // container
9650 if (!keep_stack.back())
9651 {
9652 return {false, nullptr};
9653 }
9654
9655 // create value
9656 auto value = BasicJsonType(std::forward<Value>(v));
9657
9658#if JSON_DIAGNOSTIC_POSITIONS
9659 handle_diagnostic_positions_for_json_value(value);
9660#endif
9661
9662 // check callback
9663 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
9664
9665 // do not handle this value if we just learnt it shall be discarded
9666 if (!keep)
9667 {
9668 return {false, nullptr};
9669 }
9670
9671 if (ref_stack.empty())
9672 {
9673 root = std::move(value);
9674 return {true, & root};
9675 }
9676
9677 // skip this value if we already decided to skip the parent
9678 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
9679 if (!ref_stack.back())
9680 {
9681 return {false, nullptr};
9682 }
9683
9684 // we now only expect arrays and objects
9685 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9686
9687 // array
9688 if (ref_stack.back()->is_array())
9689 {
9690 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
9691 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
9692 }
9693
9694 // object
9695 JSON_ASSERT(ref_stack.back()->is_object());
9696 // check if we should store an element for the current key
9697 JSON_ASSERT(!key_keep_stack.empty());
9698 const bool store_element = key_keep_stack.back();
9699 key_keep_stack.pop_back();
9700
9701 if (!store_element)
9702 {
9703 return {false, nullptr};
9704 }
9705
9706 JSON_ASSERT(object_element);
9707 *object_element = std::move(value);
9708 return {true, object_element};
9709 }
9710
9712 BasicJsonType& root;
9714 std::vector<BasicJsonType*> ref_stack {};
9716 std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
9718 std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
9720 BasicJsonType* object_element = nullptr;
9722 bool errored = false;
9724 const parser_callback_t callback = nullptr;
9726 const bool allow_exceptions = true;
9728 BasicJsonType discarded = BasicJsonType::value_t::discarded;
9730 lexer_t* m_lexer_ref = nullptr;
9731};
9732
9733template<typename BasicJsonType>
9735{
9736 public:
9737 using number_integer_t = typename BasicJsonType::number_integer_t;
9738 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9739 using number_float_t = typename BasicJsonType::number_float_t;
9740 using string_t = typename BasicJsonType::string_t;
9741 using binary_t = typename BasicJsonType::binary_t;
9742
9743 bool null()
9744 {
9745 return true;
9746 }
9747
9748 bool boolean(bool /*unused*/)
9749 {
9750 return true;
9751 }
9752
9754 {
9755 return true;
9756 }
9757
9759 {
9760 return true;
9761 }
9762
9763 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
9764 {
9765 return true;
9766 }
9767
9768 bool string(string_t& /*unused*/)
9769 {
9770 return true;
9771 }
9772
9773 bool binary(binary_t& /*unused*/)
9774 {
9775 return true;
9776 }
9777
9778 bool start_object(std::size_t /*unused*/ = detail::unknown_size())
9779 {
9780 return true;
9781 }
9782
9783 bool key(string_t& /*unused*/)
9784 {
9785 return true;
9786 }
9787
9789 {
9790 return true;
9791 }
9792
9793 bool start_array(std::size_t /*unused*/ = detail::unknown_size())
9794 {
9795 return true;
9796 }
9797
9799 {
9800 return true;
9801 }
9802
9803 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
9804 {
9805 return false;
9806 }
9807};
9808
9809} // namespace detail
9811
9812// #include <nlohmann/detail/input/lexer.hpp>
9813
9814// #include <nlohmann/detail/macro_scope.hpp>
9815
9816// #include <nlohmann/detail/meta/is_sax.hpp>
9817// __ _____ _____ _____
9818// __| | __| | | | JSON for Modern C++
9819// | | |__ | | | | | | version 3.12.0
9820// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9821//
9822// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
9823// SPDX-License-Identifier: MIT
9824
9825
9826
9827#include <cstdint> // size_t
9828#include <utility> // declval
9829#include <string> // string
9830
9831// #include <nlohmann/detail/abi_macros.hpp>
9832
9833// #include <nlohmann/detail/meta/detected.hpp>
9834
9835// #include <nlohmann/detail/meta/type_traits.hpp>
9836
9837
9839namespace detail
9840{
9841
9842template<typename T>
9843using null_function_t = decltype(std::declval<T&>().null());
9844
9845template<typename T>
9847 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9848
9849template<typename T, typename Integer>
9851 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9852
9853template<typename T, typename Unsigned>
9855 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9856
9857template<typename T, typename Float, typename String>
9858using number_float_function_t = decltype(std::declval<T&>().number_float(
9859 std::declval<Float>(), std::declval<const String&>()));
9860
9861template<typename T, typename String>
9863 decltype(std::declval<T&>().string(std::declval<String&>()));
9864
9865template<typename T, typename Binary>
9867 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9868
9869template<typename T>
9871 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9872
9873template<typename T, typename String>
9875 decltype(std::declval<T&>().key(std::declval<String&>()));
9876
9877template<typename T>
9878using end_object_function_t = decltype(std::declval<T&>().end_object());
9879
9880template<typename T>
9882 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9883
9884template<typename T>
9885using end_array_function_t = decltype(std::declval<T&>().end_array());
9886
9887template<typename T, typename Exception>
9888using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9889 std::declval<std::size_t>(), std::declval<const std::string&>(),
9890 std::declval<const Exception&>()));
9891
9892template<typename SAX, typename BasicJsonType>
9894{
9895 private:
9897 "BasicJsonType must be of type basic_json<...>");
9898
9899 using number_integer_t = typename BasicJsonType::number_integer_t;
9900 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9901 using number_float_t = typename BasicJsonType::number_float_t;
9902 using string_t = typename BasicJsonType::string_t;
9903 using binary_t = typename BasicJsonType::binary_t;
9904 using exception_t = typename BasicJsonType::exception;
9905
9906 public:
9907 static constexpr bool value =
9921};
9922
9923template<typename SAX, typename BasicJsonType>
9925{
9926 private:
9928 "BasicJsonType must be of type basic_json<...>");
9929
9930 using number_integer_t = typename BasicJsonType::number_integer_t;
9931 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9932 using number_float_t = typename BasicJsonType::number_float_t;
9933 using string_t = typename BasicJsonType::string_t;
9934 using binary_t = typename BasicJsonType::binary_t;
9935 using exception_t = typename BasicJsonType::exception;
9936
9937 public:
9939 "Missing/invalid function: bool null()");
9941 "Missing/invalid function: bool boolean(bool)");
9943 "Missing/invalid function: bool boolean(bool)");
9944 static_assert(
9946 number_integer_t>::value,
9947 "Missing/invalid function: bool number_integer(number_integer_t)");
9948 static_assert(
9950 number_unsigned_t>::value,
9951 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9952 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9953 number_float_t, string_t>::value,
9954 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9955 static_assert(
9957 "Missing/invalid function: bool string(string_t&)");
9958 static_assert(
9960 "Missing/invalid function: bool binary(binary_t&)");
9962 "Missing/invalid function: bool start_object(std::size_t)");
9964 "Missing/invalid function: bool key(string_t&)");
9966 "Missing/invalid function: bool end_object()");
9968 "Missing/invalid function: bool start_array(std::size_t)");
9970 "Missing/invalid function: bool end_array()");
9971 static_assert(
9973 "Missing/invalid function: bool parse_error(std::size_t, const "
9974 "std::string&, const exception&)");
9975};
9976
9977} // namespace detail
9979
9980// #include <nlohmann/detail/meta/type_traits.hpp>
9981
9982// #include <nlohmann/detail/string_concat.hpp>
9983
9984// #include <nlohmann/detail/value_t.hpp>
9985
9986
9988namespace detail
9989{
9990
9993{
9994 error,
9995 ignore,
9996 store
9997};
9998
10006inline bool little_endianness(int num = 1) noexcept
10007{
10008 return *reinterpret_cast<char*>(&num) == 1;
10009}
10010
10012// binary reader //
10014
10018template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType, InputAdapterType>>
10020{
10021 using number_integer_t = typename BasicJsonType::number_integer_t;
10022 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
10023 using number_float_t = typename BasicJsonType::number_float_t;
10024 using string_t = typename BasicJsonType::string_t;
10025 using binary_t = typename BasicJsonType::binary_t;
10026 using json_sax_t = SAX;
10027 using char_type = typename InputAdapterType::char_type;
10029
10030 public:
10036 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
10037 {
10039 }
10040
10041 // make class move-only
10043 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
10045 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
10046 ~binary_reader() = default;
10047
10057 bool sax_parse(const input_format_t format,
10058 json_sax_t* sax_,
10059 const bool strict = true,
10060 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
10061 {
10062 sax = sax_;
10063 bool result = false;
10064
10065 switch (format)
10066 {
10067 case input_format_t::bson:
10068 result = parse_bson_internal();
10069 break;
10070
10071 case input_format_t::cbor:
10072 result = parse_cbor_internal(true, tag_handler);
10073 break;
10074
10075 case input_format_t::msgpack:
10076 result = parse_msgpack_internal();
10077 break;
10078
10079 case input_format_t::ubjson:
10080 case input_format_t::bjdata:
10081 result = parse_ubjson_internal();
10082 break;
10083
10084 case input_format_t::json: // LCOV_EXCL_LINE
10085 default: // LCOV_EXCL_LINE
10086 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10087 }
10088
10089 // strict mode: next byte must be EOF
10090 if (result && strict)
10091 {
10092 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
10093 {
10094 get_ignore_noop();
10095 }
10096 else
10097 {
10098 get();
10099 }
10100
10102 {
10103 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
10104 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
10105 }
10106 }
10107
10108 return result;
10109 }
10110
10111 private:
10113 // BSON //
10115
10121 {
10122 std::int32_t document_size{};
10123 get_number<std::int32_t, true>(input_format_t::bson, document_size);
10124
10125 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
10126 {
10127 return false;
10128 }
10129
10130 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
10131 {
10132 return false;
10133 }
10134
10135 return sax->end_object();
10136 }
10137
10146 {
10147 auto out = std::back_inserter(result);
10148 while (true)
10149 {
10150 get();
10151 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
10152 {
10153 return false;
10154 }
10155 if (current == 0x00)
10156 {
10157 return true;
10158 }
10159 *out++ = static_cast<typename string_t::value_type>(current);
10160 }
10161 }
10162
10174 template<typename NumberType>
10175 bool get_bson_string(const NumberType len, string_t& result)
10176 {
10177 if (JSON_HEDLEY_UNLIKELY(len < 1))
10178 {
10179 auto last_token = get_token_string();
10180 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10181 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
10182 }
10183
10184 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
10185 }
10186
10196 template<typename NumberType>
10197 bool get_bson_binary(const NumberType len, binary_t& result)
10198 {
10199 if (JSON_HEDLEY_UNLIKELY(len < 0))
10200 {
10201 auto last_token = get_token_string();
10202 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10203 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
10204 }
10205
10206 // All BSON binary values have a subtype
10207 std::uint8_t subtype{};
10208 get_number<std::uint8_t>(input_format_t::bson, subtype);
10209 result.set_subtype(subtype);
10210
10211 return get_binary(input_format_t::bson, len, result);
10212 }
10213
10225 const std::size_t element_type_parse_position)
10226 {
10227 switch (element_type)
10228 {
10229 case 0x01: // double
10230 {
10231 double number{};
10232 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10233 }
10234
10235 case 0x02: // string
10236 {
10237 std::int32_t len{};
10239 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
10240 }
10241
10242 case 0x03: // object
10243 {
10244 return parse_bson_internal();
10245 }
10246
10247 case 0x04: // array
10248 {
10249 return parse_bson_array();
10250 }
10251
10252 case 0x05: // binary
10253 {
10254 std::int32_t len{};
10256 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
10257 }
10258
10259 case 0x08: // boolean
10260 {
10261 return sax->boolean(get() != 0);
10262 }
10263
10264 case 0x0A: // null
10265 {
10266 return sax->null();
10267 }
10268
10269 case 0x10: // int32
10270 {
10271 std::int32_t value{};
10272 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10273 }
10274
10275 case 0x12: // int64
10276 {
10277 std::int64_t value{};
10278 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10279 }
10280
10281 case 0x11: // uint64
10282 {
10283 std::uint64_t value{};
10284 return get_number<std::uint64_t, true>(input_format_t::bson, value) && sax->number_unsigned(value);
10285 }
10286
10287 default: // anything else is not supported (yet)
10288 {
10289 std::array<char, 3> cr{{}};
10290 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10291 const std::string cr_str{cr.data()};
10292 return sax->parse_error(element_type_parse_position, cr_str,
10293 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
10294 }
10295 }
10296 }
10297
10310 bool parse_bson_element_list(const bool is_array)
10311 {
10312 string_t key;
10313
10314 while (auto element_type = get())
10315 {
10316 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
10317 {
10318 return false;
10319 }
10320
10321 const std::size_t element_type_parse_position = chars_read;
10322 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
10323 {
10324 return false;
10325 }
10326
10327 if (!is_array && !sax->key(key))
10328 {
10329 return false;
10330 }
10331
10332 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
10333 {
10334 return false;
10335 }
10336
10337 // get_bson_cstr only appends
10338 key.clear();
10339 }
10340
10341 return true;
10342 }
10343
10349 {
10350 std::int32_t document_size{};
10351 get_number<std::int32_t, true>(input_format_t::bson, document_size);
10352
10353 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
10354 {
10355 return false;
10356 }
10357
10358 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
10359 {
10360 return false;
10361 }
10362
10363 return sax->end_array();
10364 }
10365
10367 // CBOR //
10369
10379 template<typename NumberType>
10381 {
10382 NumberType number{};
10383 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, number)))
10384 {
10385 return false;
10386 }
10387 const auto max_val = static_cast<NumberType>((std::numeric_limits<number_integer_t>::max)());
10388 if (number > max_val)
10389 {
10390 return sax->parse_error(chars_read, get_token_string(),
10391 parse_error::create(112, chars_read,
10392 exception_message(input_format_t::cbor, "negative integer overflow", "value"), nullptr));
10393 }
10394 return sax->number_integer(static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(number));
10395 }
10396
10397 bool parse_cbor_internal(const bool get_char,
10398 const cbor_tag_handler_t tag_handler)
10399 {
10400 switch (get_char ? get() : current)
10401 {
10402 // EOF
10404 return unexpect_eof(input_format_t::cbor, "value");
10405
10406 // Integer 0x00..0x17 (0..23)
10407 case 0x00:
10408 case 0x01:
10409 case 0x02:
10410 case 0x03:
10411 case 0x04:
10412 case 0x05:
10413 case 0x06:
10414 case 0x07:
10415 case 0x08:
10416 case 0x09:
10417 case 0x0A:
10418 case 0x0B:
10419 case 0x0C:
10420 case 0x0D:
10421 case 0x0E:
10422 case 0x0F:
10423 case 0x10:
10424 case 0x11:
10425 case 0x12:
10426 case 0x13:
10427 case 0x14:
10428 case 0x15:
10429 case 0x16:
10430 case 0x17:
10431 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10432
10433 case 0x18: // Unsigned integer (one-byte uint8_t follows)
10434 {
10435 std::uint8_t number{};
10436 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10437 }
10438
10439 case 0x19: // Unsigned integer (two-byte uint16_t follows)
10440 {
10441 std::uint16_t number{};
10442 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10443 }
10444
10445 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
10446 {
10447 std::uint32_t number{};
10448 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10449 }
10450
10451 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
10452 {
10453 std::uint64_t number{};
10454 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10455 }
10456
10457 // Negative integer -1-0x00..-1-0x17 (-1..-24)
10458 case 0x20:
10459 case 0x21:
10460 case 0x22:
10461 case 0x23:
10462 case 0x24:
10463 case 0x25:
10464 case 0x26:
10465 case 0x27:
10466 case 0x28:
10467 case 0x29:
10468 case 0x2A:
10469 case 0x2B:
10470 case 0x2C:
10471 case 0x2D:
10472 case 0x2E:
10473 case 0x2F:
10474 case 0x30:
10475 case 0x31:
10476 case 0x32:
10477 case 0x33:
10478 case 0x34:
10479 case 0x35:
10480 case 0x36:
10481 case 0x37:
10482 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
10483
10484 case 0x38: // Negative integer (one-byte uint8_t follows)
10485 return get_cbor_negative_integer<std::uint8_t>();
10486
10487 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
10488 return get_cbor_negative_integer<std::uint16_t>();
10489
10490 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
10491 return get_cbor_negative_integer<std::uint32_t>();
10492
10493 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
10494 return get_cbor_negative_integer<std::uint64_t>();
10495
10496 // Binary data (0x00..0x17 bytes follow)
10497 case 0x40:
10498 case 0x41:
10499 case 0x42:
10500 case 0x43:
10501 case 0x44:
10502 case 0x45:
10503 case 0x46:
10504 case 0x47:
10505 case 0x48:
10506 case 0x49:
10507 case 0x4A:
10508 case 0x4B:
10509 case 0x4C:
10510 case 0x4D:
10511 case 0x4E:
10512 case 0x4F:
10513 case 0x50:
10514 case 0x51:
10515 case 0x52:
10516 case 0x53:
10517 case 0x54:
10518 case 0x55:
10519 case 0x56:
10520 case 0x57:
10521 case 0x58: // Binary data (one-byte uint8_t for n follows)
10522 case 0x59: // Binary data (two-byte uint16_t for n follow)
10523 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10524 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10525 case 0x5F: // Binary data (indefinite length)
10526 {
10527 binary_t b;
10528 return get_cbor_binary(b) && sax->binary(b);
10529 }
10530
10531 // UTF-8 string (0x00..0x17 bytes follow)
10532 case 0x60:
10533 case 0x61:
10534 case 0x62:
10535 case 0x63:
10536 case 0x64:
10537 case 0x65:
10538 case 0x66:
10539 case 0x67:
10540 case 0x68:
10541 case 0x69:
10542 case 0x6A:
10543 case 0x6B:
10544 case 0x6C:
10545 case 0x6D:
10546 case 0x6E:
10547 case 0x6F:
10548 case 0x70:
10549 case 0x71:
10550 case 0x72:
10551 case 0x73:
10552 case 0x74:
10553 case 0x75:
10554 case 0x76:
10555 case 0x77:
10556 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10557 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10558 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10559 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10560 case 0x7F: // UTF-8 string (indefinite length)
10561 {
10562 string_t s;
10563 return get_cbor_string(s) && sax->string(s);
10564 }
10565
10566 // array (0x00..0x17 data items follow)
10567 case 0x80:
10568 case 0x81:
10569 case 0x82:
10570 case 0x83:
10571 case 0x84:
10572 case 0x85:
10573 case 0x86:
10574 case 0x87:
10575 case 0x88:
10576 case 0x89:
10577 case 0x8A:
10578 case 0x8B:
10579 case 0x8C:
10580 case 0x8D:
10581 case 0x8E:
10582 case 0x8F:
10583 case 0x90:
10584 case 0x91:
10585 case 0x92:
10586 case 0x93:
10587 case 0x94:
10588 case 0x95:
10589 case 0x96:
10590 case 0x97:
10591 return get_cbor_array(
10592 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10593
10594 case 0x98: // array (one-byte uint8_t for n follows)
10595 {
10596 std::uint8_t len{};
10597 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10598 }
10599
10600 case 0x99: // array (two-byte uint16_t for n follow)
10601 {
10602 std::uint16_t len{};
10603 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10604 }
10605
10606 case 0x9A: // array (four-byte uint32_t for n follow)
10607 {
10608 std::uint32_t len{};
10609 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10610 }
10611
10612 case 0x9B: // array (eight-byte uint64_t for n follow)
10613 {
10614 std::uint64_t len{};
10615 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10616 }
10617
10618 case 0x9F: // array (indefinite length)
10619 return get_cbor_array(detail::unknown_size(), tag_handler);
10620
10621 // map (0x00..0x17 pairs of data items follow)
10622 case 0xA0:
10623 case 0xA1:
10624 case 0xA2:
10625 case 0xA3:
10626 case 0xA4:
10627 case 0xA5:
10628 case 0xA6:
10629 case 0xA7:
10630 case 0xA8:
10631 case 0xA9:
10632 case 0xAA:
10633 case 0xAB:
10634 case 0xAC:
10635 case 0xAD:
10636 case 0xAE:
10637 case 0xAF:
10638 case 0xB0:
10639 case 0xB1:
10640 case 0xB2:
10641 case 0xB3:
10642 case 0xB4:
10643 case 0xB5:
10644 case 0xB6:
10645 case 0xB7:
10646 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10647
10648 case 0xB8: // map (one-byte uint8_t for n follows)
10649 {
10650 std::uint8_t len{};
10651 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10652 }
10653
10654 case 0xB9: // map (two-byte uint16_t for n follow)
10655 {
10656 std::uint16_t len{};
10657 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10658 }
10659
10660 case 0xBA: // map (four-byte uint32_t for n follow)
10661 {
10662 std::uint32_t len{};
10663 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10664 }
10665
10666 case 0xBB: // map (eight-byte uint64_t for n follow)
10667 {
10668 std::uint64_t len{};
10669 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10670 }
10671
10672 case 0xBF: // map (indefinite length)
10673 return get_cbor_object(detail::unknown_size(), tag_handler);
10674
10675 case 0xC6: // tagged item
10676 case 0xC7:
10677 case 0xC8:
10678 case 0xC9:
10679 case 0xCA:
10680 case 0xCB:
10681 case 0xCC:
10682 case 0xCD:
10683 case 0xCE:
10684 case 0xCF:
10685 case 0xD0:
10686 case 0xD1:
10687 case 0xD2:
10688 case 0xD3:
10689 case 0xD4:
10690 case 0xD8: // tagged item (1 byte follows)
10691 case 0xD9: // tagged item (2 bytes follow)
10692 case 0xDA: // tagged item (4 bytes follow)
10693 case 0xDB: // tagged item (8 bytes follow)
10694 {
10695 switch (tag_handler)
10696 {
10697 case cbor_tag_handler_t::error:
10698 {
10699 auto last_token = get_token_string();
10700 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10701 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10702 }
10703
10704 case cbor_tag_handler_t::ignore:
10705 {
10706 // ignore binary subtype
10707 switch (current)
10708 {
10709 case 0xD8:
10710 {
10711 std::uint8_t subtype_to_ignore{};
10712 get_number(input_format_t::cbor, subtype_to_ignore);
10713 break;
10714 }
10715 case 0xD9:
10716 {
10717 std::uint16_t subtype_to_ignore{};
10718 get_number(input_format_t::cbor, subtype_to_ignore);
10719 break;
10720 }
10721 case 0xDA:
10722 {
10723 std::uint32_t subtype_to_ignore{};
10724 get_number(input_format_t::cbor, subtype_to_ignore);
10725 break;
10726 }
10727 case 0xDB:
10728 {
10729 std::uint64_t subtype_to_ignore{};
10730 get_number(input_format_t::cbor, subtype_to_ignore);
10731 break;
10732 }
10733 default:
10734 break;
10735 }
10736 return parse_cbor_internal(true, tag_handler);
10737 }
10738
10739 case cbor_tag_handler_t::store:
10740 {
10741 binary_t b;
10742 // use binary subtype and store in a binary container
10743 switch (current)
10744 {
10745 case 0xD8:
10746 {
10747 std::uint8_t subtype{};
10748 get_number(input_format_t::cbor, subtype);
10749 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10750 break;
10751 }
10752 case 0xD9:
10753 {
10754 std::uint16_t subtype{};
10755 get_number(input_format_t::cbor, subtype);
10756 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10757 break;
10758 }
10759 case 0xDA:
10760 {
10761 std::uint32_t subtype{};
10762 get_number(input_format_t::cbor, subtype);
10763 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10764 break;
10765 }
10766 case 0xDB:
10767 {
10768 std::uint64_t subtype{};
10769 get_number(input_format_t::cbor, subtype);
10770 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10771 break;
10772 }
10773 default:
10774 return parse_cbor_internal(true, tag_handler);
10775 }
10776 get();
10777 return get_cbor_binary(b) && sax->binary(b);
10778 }
10779
10780 default: // LCOV_EXCL_LINE
10781 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10782 return false; // LCOV_EXCL_LINE
10783 }
10784 }
10785
10786 case 0xF4: // false
10787 return sax->boolean(false);
10788
10789 case 0xF5: // true
10790 return sax->boolean(true);
10791
10792 case 0xF6: // null
10793 return sax->null();
10794
10795 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10796 {
10797 const auto byte1_raw = get();
10798 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10799 {
10800 return false;
10801 }
10802 const auto byte2_raw = get();
10803 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10804 {
10805 return false;
10806 }
10807
10808 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10809 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10810
10811 // Code from RFC 7049, Appendix D, Figure 3:
10812 // As half-precision floating-point numbers were only added
10813 // to IEEE 754 in 2008, today's programming platforms often
10814 // still only have limited support for them. It is very
10815 // easy to include at least decoding support for them even
10816 // without such support. An example of a small decoder for
10817 // half-precision floating-point numbers in the C language
10818 // is shown in Fig. 3.
10819 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10820 const double val = [&half]
10821 {
10822 const int exp = (half >> 10u) & 0x1Fu;
10823 const unsigned int mant = half & 0x3FFu;
10824 JSON_ASSERT(0 <= exp&& exp <= 32);
10825 JSON_ASSERT(mant <= 1024);
10826 switch (exp)
10827 {
10828 case 0:
10829 return std::ldexp(mant, -24);
10830 case 31:
10831 return (mant == 0)
10832 ? std::numeric_limits<double>::infinity()
10833 : std::numeric_limits<double>::quiet_NaN();
10834 default:
10835 return std::ldexp(mant + 1024, exp - 25);
10836 }
10837 }();
10838 return sax->number_float((half & 0x8000u) != 0
10839 ? static_cast<number_float_t>(-val)
10840 : static_cast<number_float_t>(val), "");
10841 }
10842
10843 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10844 {
10845 float number{};
10846 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10847 }
10848
10849 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10850 {
10851 double number{};
10852 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10853 }
10854
10855 default: // anything else (0xFF is handled inside the other types)
10856 {
10857 auto last_token = get_token_string();
10858 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10859 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10860 }
10861 }
10862 }
10863
10876 {
10877 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10878 {
10879 return false;
10880 }
10881
10882 switch (current)
10883 {
10884 // UTF-8 string (0x00..0x17 bytes follow)
10885 case 0x60:
10886 case 0x61:
10887 case 0x62:
10888 case 0x63:
10889 case 0x64:
10890 case 0x65:
10891 case 0x66:
10892 case 0x67:
10893 case 0x68:
10894 case 0x69:
10895 case 0x6A:
10896 case 0x6B:
10897 case 0x6C:
10898 case 0x6D:
10899 case 0x6E:
10900 case 0x6F:
10901 case 0x70:
10902 case 0x71:
10903 case 0x72:
10904 case 0x73:
10905 case 0x74:
10906 case 0x75:
10907 case 0x76:
10908 case 0x77:
10909 {
10910 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10911 }
10912
10913 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10914 {
10915 std::uint8_t len{};
10916 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10917 }
10918
10919 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10920 {
10921 std::uint16_t len{};
10922 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10923 }
10924
10925 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10926 {
10927 std::uint32_t len{};
10928 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10929 }
10930
10931 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10932 {
10933 std::uint64_t len{};
10934 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10935 }
10936
10937 case 0x7F: // UTF-8 string (indefinite length)
10938 {
10939 while (get() != 0xFF)
10940 {
10941 string_t chunk;
10942 if (!get_cbor_string(chunk))
10943 {
10944 return false;
10945 }
10946 result.append(chunk);
10947 }
10948 return true;
10949 }
10950
10951 default:
10952 {
10953 auto last_token = get_token_string();
10954 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10955 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10956 }
10957 }
10958 }
10959
10972 {
10973 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10974 {
10975 return false;
10976 }
10977
10978 switch (current)
10979 {
10980 // Binary data (0x00..0x17 bytes follow)
10981 case 0x40:
10982 case 0x41:
10983 case 0x42:
10984 case 0x43:
10985 case 0x44:
10986 case 0x45:
10987 case 0x46:
10988 case 0x47:
10989 case 0x48:
10990 case 0x49:
10991 case 0x4A:
10992 case 0x4B:
10993 case 0x4C:
10994 case 0x4D:
10995 case 0x4E:
10996 case 0x4F:
10997 case 0x50:
10998 case 0x51:
10999 case 0x52:
11000 case 0x53:
11001 case 0x54:
11002 case 0x55:
11003 case 0x56:
11004 case 0x57:
11005 {
11006 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
11007 }
11008
11009 case 0x58: // Binary data (one-byte uint8_t for n follows)
11010 {
11011 std::uint8_t len{};
11012 return get_number(input_format_t::cbor, len) &&
11013 get_binary(input_format_t::cbor, len, result);
11014 }
11015
11016 case 0x59: // Binary data (two-byte uint16_t for n follow)
11017 {
11018 std::uint16_t len{};
11019 return get_number(input_format_t::cbor, len) &&
11020 get_binary(input_format_t::cbor, len, result);
11021 }
11022
11023 case 0x5A: // Binary data (four-byte uint32_t for n follow)
11024 {
11025 std::uint32_t len{};
11026 return get_number(input_format_t::cbor, len) &&
11027 get_binary(input_format_t::cbor, len, result);
11028 }
11029
11030 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
11031 {
11032 std::uint64_t len{};
11033 return get_number(input_format_t::cbor, len) &&
11034 get_binary(input_format_t::cbor, len, result);
11035 }
11036
11037 case 0x5F: // Binary data (indefinite length)
11038 {
11039 while (get() != 0xFF)
11040 {
11041 binary_t chunk;
11042 if (!get_cbor_binary(chunk))
11043 {
11044 return false;
11045 }
11046 result.insert(result.end(), chunk.begin(), chunk.end());
11047 }
11048 return true;
11049 }
11050
11051 default:
11052 {
11053 auto last_token = get_token_string();
11054 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11055 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));
11056 }
11057 }
11058 }
11059
11066 bool get_cbor_array(const std::size_t len,
11067 const cbor_tag_handler_t tag_handler)
11068 {
11069 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
11070 {
11071 return false;
11072 }
11073
11074 if (len != detail::unknown_size())
11075 {
11076 for (std::size_t i = 0; i < len; ++i)
11077 {
11078 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
11079 {
11080 return false;
11081 }
11082 }
11083 }
11084 else
11085 {
11086 while (get() != 0xFF)
11087 {
11088 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
11089 {
11090 return false;
11091 }
11092 }
11093 }
11094
11095 return sax->end_array();
11096 }
11097
11104 bool get_cbor_object(const std::size_t len,
11105 const cbor_tag_handler_t tag_handler)
11106 {
11107 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
11108 {
11109 return false;
11110 }
11111
11112 if (len != 0)
11113 {
11114 string_t key;
11115 if (len != detail::unknown_size())
11116 {
11117 for (std::size_t i = 0; i < len; ++i)
11118 {
11119 get();
11120 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
11121 {
11122 return false;
11123 }
11124
11125 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
11126 {
11127 return false;
11128 }
11129 key.clear();
11130 }
11131 }
11132 else
11133 {
11134 while (get() != 0xFF)
11135 {
11136 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
11137 {
11138 return false;
11139 }
11140
11141 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
11142 {
11143 return false;
11144 }
11145 key.clear();
11146 }
11147 }
11148 }
11149
11150 return sax->end_object();
11151 }
11152
11154 // MsgPack //
11156
11161 {
11162 switch (get())
11163 {
11164 // EOF
11166 return unexpect_eof(input_format_t::msgpack, "value");
11167
11168 // positive fixint
11169 case 0x00:
11170 case 0x01:
11171 case 0x02:
11172 case 0x03:
11173 case 0x04:
11174 case 0x05:
11175 case 0x06:
11176 case 0x07:
11177 case 0x08:
11178 case 0x09:
11179 case 0x0A:
11180 case 0x0B:
11181 case 0x0C:
11182 case 0x0D:
11183 case 0x0E:
11184 case 0x0F:
11185 case 0x10:
11186 case 0x11:
11187 case 0x12:
11188 case 0x13:
11189 case 0x14:
11190 case 0x15:
11191 case 0x16:
11192 case 0x17:
11193 case 0x18:
11194 case 0x19:
11195 case 0x1A:
11196 case 0x1B:
11197 case 0x1C:
11198 case 0x1D:
11199 case 0x1E:
11200 case 0x1F:
11201 case 0x20:
11202 case 0x21:
11203 case 0x22:
11204 case 0x23:
11205 case 0x24:
11206 case 0x25:
11207 case 0x26:
11208 case 0x27:
11209 case 0x28:
11210 case 0x29:
11211 case 0x2A:
11212 case 0x2B:
11213 case 0x2C:
11214 case 0x2D:
11215 case 0x2E:
11216 case 0x2F:
11217 case 0x30:
11218 case 0x31:
11219 case 0x32:
11220 case 0x33:
11221 case 0x34:
11222 case 0x35:
11223 case 0x36:
11224 case 0x37:
11225 case 0x38:
11226 case 0x39:
11227 case 0x3A:
11228 case 0x3B:
11229 case 0x3C:
11230 case 0x3D:
11231 case 0x3E:
11232 case 0x3F:
11233 case 0x40:
11234 case 0x41:
11235 case 0x42:
11236 case 0x43:
11237 case 0x44:
11238 case 0x45:
11239 case 0x46:
11240 case 0x47:
11241 case 0x48:
11242 case 0x49:
11243 case 0x4A:
11244 case 0x4B:
11245 case 0x4C:
11246 case 0x4D:
11247 case 0x4E:
11248 case 0x4F:
11249 case 0x50:
11250 case 0x51:
11251 case 0x52:
11252 case 0x53:
11253 case 0x54:
11254 case 0x55:
11255 case 0x56:
11256 case 0x57:
11257 case 0x58:
11258 case 0x59:
11259 case 0x5A:
11260 case 0x5B:
11261 case 0x5C:
11262 case 0x5D:
11263 case 0x5E:
11264 case 0x5F:
11265 case 0x60:
11266 case 0x61:
11267 case 0x62:
11268 case 0x63:
11269 case 0x64:
11270 case 0x65:
11271 case 0x66:
11272 case 0x67:
11273 case 0x68:
11274 case 0x69:
11275 case 0x6A:
11276 case 0x6B:
11277 case 0x6C:
11278 case 0x6D:
11279 case 0x6E:
11280 case 0x6F:
11281 case 0x70:
11282 case 0x71:
11283 case 0x72:
11284 case 0x73:
11285 case 0x74:
11286 case 0x75:
11287 case 0x76:
11288 case 0x77:
11289 case 0x78:
11290 case 0x79:
11291 case 0x7A:
11292 case 0x7B:
11293 case 0x7C:
11294 case 0x7D:
11295 case 0x7E:
11296 case 0x7F:
11297 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
11298
11299 // fixmap
11300 case 0x80:
11301 case 0x81:
11302 case 0x82:
11303 case 0x83:
11304 case 0x84:
11305 case 0x85:
11306 case 0x86:
11307 case 0x87:
11308 case 0x88:
11309 case 0x89:
11310 case 0x8A:
11311 case 0x8B:
11312 case 0x8C:
11313 case 0x8D:
11314 case 0x8E:
11315 case 0x8F:
11316 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11317
11318 // fixarray
11319 case 0x90:
11320 case 0x91:
11321 case 0x92:
11322 case 0x93:
11323 case 0x94:
11324 case 0x95:
11325 case 0x96:
11326 case 0x97:
11327 case 0x98:
11328 case 0x99:
11329 case 0x9A:
11330 case 0x9B:
11331 case 0x9C:
11332 case 0x9D:
11333 case 0x9E:
11334 case 0x9F:
11335 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11336
11337 // fixstr
11338 case 0xA0:
11339 case 0xA1:
11340 case 0xA2:
11341 case 0xA3:
11342 case 0xA4:
11343 case 0xA5:
11344 case 0xA6:
11345 case 0xA7:
11346 case 0xA8:
11347 case 0xA9:
11348 case 0xAA:
11349 case 0xAB:
11350 case 0xAC:
11351 case 0xAD:
11352 case 0xAE:
11353 case 0xAF:
11354 case 0xB0:
11355 case 0xB1:
11356 case 0xB2:
11357 case 0xB3:
11358 case 0xB4:
11359 case 0xB5:
11360 case 0xB6:
11361 case 0xB7:
11362 case 0xB8:
11363 case 0xB9:
11364 case 0xBA:
11365 case 0xBB:
11366 case 0xBC:
11367 case 0xBD:
11368 case 0xBE:
11369 case 0xBF:
11370 case 0xD9: // str 8
11371 case 0xDA: // str 16
11372 case 0xDB: // str 32
11373 {
11374 string_t s;
11375 return get_msgpack_string(s) && sax->string(s);
11376 }
11377
11378 case 0xC0: // nil
11379 return sax->null();
11380
11381 case 0xC2: // false
11382 return sax->boolean(false);
11383
11384 case 0xC3: // true
11385 return sax->boolean(true);
11386
11387 case 0xC4: // bin 8
11388 case 0xC5: // bin 16
11389 case 0xC6: // bin 32
11390 case 0xC7: // ext 8
11391 case 0xC8: // ext 16
11392 case 0xC9: // ext 32
11393 case 0xD4: // fixext 1
11394 case 0xD5: // fixext 2
11395 case 0xD6: // fixext 4
11396 case 0xD7: // fixext 8
11397 case 0xD8: // fixext 16
11398 {
11399 binary_t b;
11400 return get_msgpack_binary(b) && sax->binary(b);
11401 }
11402
11403 case 0xCA: // float 32
11404 {
11405 float number{};
11406 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11407 }
11408
11409 case 0xCB: // float 64
11410 {
11411 double number{};
11412 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11413 }
11414
11415 case 0xCC: // uint 8
11416 {
11417 std::uint8_t number{};
11418 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11419 }
11420
11421 case 0xCD: // uint 16
11422 {
11423 std::uint16_t number{};
11424 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11425 }
11426
11427 case 0xCE: // uint 32
11428 {
11429 std::uint32_t number{};
11430 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11431 }
11432
11433 case 0xCF: // uint 64
11434 {
11435 std::uint64_t number{};
11436 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11437 }
11438
11439 case 0xD0: // int 8
11440 {
11441 std::int8_t number{};
11442 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11443 }
11444
11445 case 0xD1: // int 16
11446 {
11447 std::int16_t number{};
11448 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11449 }
11450
11451 case 0xD2: // int 32
11452 {
11453 std::int32_t number{};
11454 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11455 }
11456
11457 case 0xD3: // int 64
11458 {
11459 std::int64_t number{};
11460 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11461 }
11462
11463 case 0xDC: // array 16
11464 {
11465 std::uint16_t len{};
11466 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
11467 }
11468
11469 case 0xDD: // array 32
11470 {
11471 std::uint32_t len{};
11472 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
11473 }
11474
11475 case 0xDE: // map 16
11476 {
11477 std::uint16_t len{};
11478 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
11479 }
11480
11481 case 0xDF: // map 32
11482 {
11483 std::uint32_t len{};
11484 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
11485 }
11486
11487 // negative fixint
11488 case 0xE0:
11489 case 0xE1:
11490 case 0xE2:
11491 case 0xE3:
11492 case 0xE4:
11493 case 0xE5:
11494 case 0xE6:
11495 case 0xE7:
11496 case 0xE8:
11497 case 0xE9:
11498 case 0xEA:
11499 case 0xEB:
11500 case 0xEC:
11501 case 0xED:
11502 case 0xEE:
11503 case 0xEF:
11504 case 0xF0:
11505 case 0xF1:
11506 case 0xF2:
11507 case 0xF3:
11508 case 0xF4:
11509 case 0xF5:
11510 case 0xF6:
11511 case 0xF7:
11512 case 0xF8:
11513 case 0xF9:
11514 case 0xFA:
11515 case 0xFB:
11516 case 0xFC:
11517 case 0xFD:
11518 case 0xFE:
11519 case 0xFF:
11520 return sax->number_integer(static_cast<std::int8_t>(current));
11521
11522 default: // anything else
11523 {
11524 auto last_token = get_token_string();
11525 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11526 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
11527 }
11528 }
11529 }
11530
11542 {
11543 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
11544 {
11545 return false;
11546 }
11547
11548 switch (current)
11549 {
11550 // fixstr
11551 case 0xA0:
11552 case 0xA1:
11553 case 0xA2:
11554 case 0xA3:
11555 case 0xA4:
11556 case 0xA5:
11557 case 0xA6:
11558 case 0xA7:
11559 case 0xA8:
11560 case 0xA9:
11561 case 0xAA:
11562 case 0xAB:
11563 case 0xAC:
11564 case 0xAD:
11565 case 0xAE:
11566 case 0xAF:
11567 case 0xB0:
11568 case 0xB1:
11569 case 0xB2:
11570 case 0xB3:
11571 case 0xB4:
11572 case 0xB5:
11573 case 0xB6:
11574 case 0xB7:
11575 case 0xB8:
11576 case 0xB9:
11577 case 0xBA:
11578 case 0xBB:
11579 case 0xBC:
11580 case 0xBD:
11581 case 0xBE:
11582 case 0xBF:
11583 {
11584 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
11585 }
11586
11587 case 0xD9: // str 8
11588 {
11589 std::uint8_t len{};
11590 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11591 }
11592
11593 case 0xDA: // str 16
11594 {
11595 std::uint16_t len{};
11596 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11597 }
11598
11599 case 0xDB: // str 32
11600 {
11601 std::uint32_t len{};
11602 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11603 }
11604
11605 default:
11606 {
11607 auto last_token = get_token_string();
11608 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11609 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
11610 }
11611 }
11612 }
11613
11625 {
11626 // helper function to set the subtype
11627 auto assign_and_return_true = [&result](std::int8_t subtype)
11628 {
11629 result.set_subtype(static_cast<std::uint8_t>(subtype));
11630 return true;
11631 };
11632
11633 switch (current)
11634 {
11635 case 0xC4: // bin 8
11636 {
11637 std::uint8_t len{};
11638 return get_number(input_format_t::msgpack, len) &&
11639 get_binary(input_format_t::msgpack, len, result);
11640 }
11641
11642 case 0xC5: // bin 16
11643 {
11644 std::uint16_t len{};
11645 return get_number(input_format_t::msgpack, len) &&
11646 get_binary(input_format_t::msgpack, len, result);
11647 }
11648
11649 case 0xC6: // bin 32
11650 {
11651 std::uint32_t len{};
11652 return get_number(input_format_t::msgpack, len) &&
11653 get_binary(input_format_t::msgpack, len, result);
11654 }
11655
11656 case 0xC7: // ext 8
11657 {
11658 std::uint8_t len{};
11659 std::int8_t subtype{};
11660 return get_number(input_format_t::msgpack, len) &&
11661 get_number(input_format_t::msgpack, subtype) &&
11662 get_binary(input_format_t::msgpack, len, result) &&
11663 assign_and_return_true(subtype);
11664 }
11665
11666 case 0xC8: // ext 16
11667 {
11668 std::uint16_t len{};
11669 std::int8_t subtype{};
11670 return get_number(input_format_t::msgpack, len) &&
11671 get_number(input_format_t::msgpack, subtype) &&
11672 get_binary(input_format_t::msgpack, len, result) &&
11673 assign_and_return_true(subtype);
11674 }
11675
11676 case 0xC9: // ext 32
11677 {
11678 std::uint32_t len{};
11679 std::int8_t subtype{};
11680 return get_number(input_format_t::msgpack, len) &&
11681 get_number(input_format_t::msgpack, subtype) &&
11682 get_binary(input_format_t::msgpack, len, result) &&
11683 assign_and_return_true(subtype);
11684 }
11685
11686 case 0xD4: // fixext 1
11687 {
11688 std::int8_t subtype{};
11689 return get_number(input_format_t::msgpack, subtype) &&
11690 get_binary(input_format_t::msgpack, 1, result) &&
11691 assign_and_return_true(subtype);
11692 }
11693
11694 case 0xD5: // fixext 2
11695 {
11696 std::int8_t subtype{};
11697 return get_number(input_format_t::msgpack, subtype) &&
11698 get_binary(input_format_t::msgpack, 2, result) &&
11699 assign_and_return_true(subtype);
11700 }
11701
11702 case 0xD6: // fixext 4
11703 {
11704 std::int8_t subtype{};
11705 return get_number(input_format_t::msgpack, subtype) &&
11706 get_binary(input_format_t::msgpack, 4, result) &&
11707 assign_and_return_true(subtype);
11708 }
11709
11710 case 0xD7: // fixext 8
11711 {
11712 std::int8_t subtype{};
11713 return get_number(input_format_t::msgpack, subtype) &&
11714 get_binary(input_format_t::msgpack, 8, result) &&
11715 assign_and_return_true(subtype);
11716 }
11717
11718 case 0xD8: // fixext 16
11719 {
11720 std::int8_t subtype{};
11721 return get_number(input_format_t::msgpack, subtype) &&
11722 get_binary(input_format_t::msgpack, 16, result) &&
11723 assign_and_return_true(subtype);
11724 }
11725
11726 default: // LCOV_EXCL_LINE
11727 return false; // LCOV_EXCL_LINE
11728 }
11729 }
11730
11735 bool get_msgpack_array(const std::size_t len)
11736 {
11737 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
11738 {
11739 return false;
11740 }
11741
11742 for (std::size_t i = 0; i < len; ++i)
11743 {
11744 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11745 {
11746 return false;
11747 }
11748 }
11749
11750 return sax->end_array();
11751 }
11752
11757 bool get_msgpack_object(const std::size_t len)
11758 {
11759 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
11760 {
11761 return false;
11762 }
11763
11764 string_t key;
11765 for (std::size_t i = 0; i < len; ++i)
11766 {
11767 get();
11768 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
11769 {
11770 return false;
11771 }
11772
11773 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11774 {
11775 return false;
11776 }
11777 key.clear();
11778 }
11779
11780 return sax->end_object();
11781 }
11782
11784 // UBJSON //
11786
11794 bool parse_ubjson_internal(const bool get_char = true)
11795 {
11796 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11797 }
11798
11813 bool get_ubjson_string(string_t& result, const bool get_char = true)
11814 {
11815 if (get_char)
11816 {
11817 get(); // TODO(niels): may we ignore N here?
11818 }
11819
11820 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11821 {
11822 return false;
11823 }
11824
11825 switch (current)
11826 {
11827 case 'U':
11828 {
11829 std::uint8_t len{};
11830 return get_number(input_format, len) && get_string(input_format, len, result);
11831 }
11832
11833 case 'i':
11834 {
11835 std::int8_t len{};
11836 return get_number(input_format, len) && get_string(input_format, len, result);
11837 }
11838
11839 case 'I':
11840 {
11841 std::int16_t len{};
11842 return get_number(input_format, len) && get_string(input_format, len, result);
11843 }
11844
11845 case 'l':
11846 {
11847 std::int32_t len{};
11848 return get_number(input_format, len) && get_string(input_format, len, result);
11849 }
11850
11851 case 'L':
11852 {
11853 std::int64_t len{};
11854 return get_number(input_format, len) && get_string(input_format, len, result);
11855 }
11856
11857 case 'u':
11858 {
11859 if (input_format != input_format_t::bjdata)
11860 {
11861 break;
11862 }
11863 std::uint16_t len{};
11864 return get_number(input_format, len) && get_string(input_format, len, result);
11865 }
11866
11867 case 'm':
11868 {
11869 if (input_format != input_format_t::bjdata)
11870 {
11871 break;
11872 }
11873 std::uint32_t len{};
11874 return get_number(input_format, len) && get_string(input_format, len, result);
11875 }
11876
11877 case 'M':
11878 {
11879 if (input_format != input_format_t::bjdata)
11880 {
11881 break;
11882 }
11883 std::uint64_t len{};
11884 return get_number(input_format, len) && get_string(input_format, len, result);
11885 }
11886
11887 default:
11888 break;
11889 }
11890 auto last_token = get_token_string();
11891 std::string message;
11892
11893 if (input_format != input_format_t::bjdata)
11894 {
11895 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11896 }
11897 else
11898 {
11899 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11900 }
11901 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11902 }
11903
11908 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11909 {
11910 std::pair<std::size_t, char_int_type> size_and_type;
11911 size_t dimlen = 0;
11912 bool no_ndarray = true;
11913
11914 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11915 {
11916 return false;
11917 }
11918
11919 if (size_and_type.first != npos)
11920 {
11921 if (size_and_type.second != 0)
11922 {
11923 if (size_and_type.second != 'N')
11924 {
11925 for (std::size_t i = 0; i < size_and_type.first; ++i)
11926 {
11927 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11928 {
11929 return false;
11930 }
11931 dim.push_back(dimlen);
11932 }
11933 }
11934 }
11935 else
11936 {
11937 for (std::size_t i = 0; i < size_and_type.first; ++i)
11938 {
11939 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11940 {
11941 return false;
11942 }
11943 dim.push_back(dimlen);
11944 }
11945 }
11946 }
11947 else
11948 {
11949 while (current != ']')
11950 {
11951 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11952 {
11953 return false;
11954 }
11955 dim.push_back(dimlen);
11956 get_ignore_noop();
11957 }
11958 }
11959 return true;
11960 }
11961
11973 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11974 {
11975 if (prefix == 0)
11976 {
11977 prefix = get_ignore_noop();
11978 }
11979
11980 switch (prefix)
11981 {
11982 case 'U':
11983 {
11984 std::uint8_t number{};
11985 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11986 {
11987 return false;
11988 }
11989 result = static_cast<std::size_t>(number);
11990 return true;
11991 }
11992
11993 case 'i':
11994 {
11995 std::int8_t number{};
11996 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11997 {
11998 return false;
11999 }
12000 if (number < 0)
12001 {
12002 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
12003 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
12004 }
12005 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
12006 return true;
12007 }
12008
12009 case 'I':
12010 {
12011 std::int16_t number{};
12012 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
12013 {
12014 return false;
12015 }
12016 if (number < 0)
12017 {
12018 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
12019 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
12020 }
12021 result = static_cast<std::size_t>(number);
12022 return true;
12023 }
12024
12025 case 'l':
12026 {
12027 std::int32_t number{};
12028 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
12029 {
12030 return false;
12031 }
12032 if (number < 0)
12033 {
12034 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
12035 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
12036 }
12037 result = static_cast<std::size_t>(number);
12038 return true;
12039 }
12040
12041 case 'L':
12042 {
12043 std::int64_t number{};
12044 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
12045 {
12046 return false;
12047 }
12048 if (number < 0)
12049 {
12050 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
12051 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
12052 }
12053 if (!value_in_range_of<std::size_t>(number))
12054 {
12055 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
12056 exception_message(input_format, "integer value overflow", "size"), nullptr));
12057 }
12058 result = static_cast<std::size_t>(number);
12059 return true;
12060 }
12061
12062 case 'u':
12063 {
12064 if (input_format != input_format_t::bjdata)
12065 {
12066 break;
12067 }
12068 std::uint16_t number{};
12069 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
12070 {
12071 return false;
12072 }
12073 result = static_cast<std::size_t>(number);
12074 return true;
12075 }
12076
12077 case 'm':
12078 {
12079 if (input_format != input_format_t::bjdata)
12080 {
12081 break;
12082 }
12083 std::uint32_t number{};
12084 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
12085 {
12086 return false;
12087 }
12088 result = conditional_static_cast<std::size_t>(number);
12089 return true;
12090 }
12091
12092 case 'M':
12093 {
12094 if (input_format != input_format_t::bjdata)
12095 {
12096 break;
12097 }
12098 std::uint64_t number{};
12099 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
12100 {
12101 return false;
12102 }
12103 if (!value_in_range_of<std::size_t>(number))
12104 {
12105 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
12106 exception_message(input_format, "integer value overflow", "size"), nullptr));
12107 }
12108 result = detail::conditional_static_cast<std::size_t>(number);
12109 return true;
12110 }
12111
12112 case '[':
12113 {
12114 if (input_format != input_format_t::bjdata)
12115 {
12116 break;
12117 }
12118 if (is_ndarray) // ndarray dimensional vector can only contain integers and cannot embed another array
12119 {
12120 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));
12121 }
12122 std::vector<size_t> dim;
12123 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
12124 {
12125 return false;
12126 }
12127 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
12128 {
12129 result = dim.at(dim.size() - 1);
12130 return true;
12131 }
12132 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
12133 {
12134 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
12135 {
12136 if ( i == 0 )
12137 {
12138 result = 0;
12139 return true;
12140 }
12141 }
12142
12143 string_t key = "_ArraySize_";
12144 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
12145 {
12146 return false;
12147 }
12148 result = 1;
12149 for (auto i : dim)
12150 {
12151 // Pre-multiplication overflow check: if i > 0 and result > SIZE_MAX/i, then result*i would overflow.
12152 // This check must happen before multiplication since overflow detection after the fact is unreliable
12153 // as modular arithmetic can produce any value, not just 0 or SIZE_MAX.
12154 if (JSON_HEDLEY_UNLIKELY(i > 0 && result > (std::numeric_limits<std::size_t>::max)() / i))
12155 {
12156 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));
12157 }
12158 result *= i;
12159 // Additional post-multiplication check to catch any edge cases the pre-check might miss
12160 if (result == 0 || result == npos)
12161 {
12162 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));
12163 }
12164 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
12165 {
12166 return false;
12167 }
12168 }
12169 is_ndarray = true;
12170 return sax->end_array();
12171 }
12172 result = 0;
12173 return true;
12174 }
12175
12176 default:
12177 break;
12178 }
12179 auto last_token = get_token_string();
12180 std::string message;
12181
12182 if (input_format != input_format_t::bjdata)
12183 {
12184 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
12185 }
12186 else
12187 {
12188 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
12189 }
12190 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
12191 }
12192
12204 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
12205 {
12206 result.first = npos; // size
12207 result.second = 0; // type
12208 bool is_ndarray = false;
12209
12210 get_ignore_noop();
12211
12212 if (current == '$')
12213 {
12214 result.second = get(); // must not ignore 'N', because 'N' maybe the type
12215 if (input_format == input_format_t::bjdata
12216 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
12217 {
12218 auto last_token = get_token_string();
12219 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12220 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
12221 }
12222
12223 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
12224 {
12225 return false;
12226 }
12227
12228 get_ignore_noop();
12229 if (JSON_HEDLEY_UNLIKELY(current != '#'))
12230 {
12231 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
12232 {
12233 return false;
12234 }
12235 auto last_token = get_token_string();
12236 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12237 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
12238 }
12239
12240 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12241 if (input_format == input_format_t::bjdata && is_ndarray)
12242 {
12243 if (inside_ndarray)
12244 {
12245 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12246 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
12247 }
12248 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
12249 }
12250 return is_error;
12251 }
12252
12253 if (current == '#')
12254 {
12255 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12256 if (input_format == input_format_t::bjdata && is_ndarray)
12257 {
12258 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12259 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
12260 }
12261 return is_error;
12262 }
12263
12264 return true;
12265 }
12266
12272 {
12273 switch (prefix)
12274 {
12275 case char_traits<char_type>::eof(): // EOF
12276 return unexpect_eof(input_format, "value");
12277
12278 case 'T': // true
12279 return sax->boolean(true);
12280 case 'F': // false
12281 return sax->boolean(false);
12282
12283 case 'Z': // null
12284 return sax->null();
12285
12286 case 'B': // byte
12287 {
12288 if (input_format != input_format_t::bjdata)
12289 {
12290 break;
12291 }
12292 std::uint8_t number{};
12293 return get_number(input_format, number) && sax->number_unsigned(number);
12294 }
12295
12296 case 'U':
12297 {
12298 std::uint8_t number{};
12299 return get_number(input_format, number) && sax->number_unsigned(number);
12300 }
12301
12302 case 'i':
12303 {
12304 std::int8_t number{};
12305 return get_number(input_format, number) && sax->number_integer(number);
12306 }
12307
12308 case 'I':
12309 {
12310 std::int16_t number{};
12311 return get_number(input_format, number) && sax->number_integer(number);
12312 }
12313
12314 case 'l':
12315 {
12316 std::int32_t number{};
12317 return get_number(input_format, number) && sax->number_integer(number);
12318 }
12319
12320 case 'L':
12321 {
12322 std::int64_t number{};
12323 return get_number(input_format, number) && sax->number_integer(number);
12324 }
12325
12326 case 'u':
12327 {
12328 if (input_format != input_format_t::bjdata)
12329 {
12330 break;
12331 }
12332 std::uint16_t number{};
12333 return get_number(input_format, number) && sax->number_unsigned(number);
12334 }
12335
12336 case 'm':
12337 {
12338 if (input_format != input_format_t::bjdata)
12339 {
12340 break;
12341 }
12342 std::uint32_t number{};
12343 return get_number(input_format, number) && sax->number_unsigned(number);
12344 }
12345
12346 case 'M':
12347 {
12348 if (input_format != input_format_t::bjdata)
12349 {
12350 break;
12351 }
12352 std::uint64_t number{};
12353 return get_number(input_format, number) && sax->number_unsigned(number);
12354 }
12355
12356 case 'h':
12357 {
12358 if (input_format != input_format_t::bjdata)
12359 {
12360 break;
12361 }
12362 const auto byte1_raw = get();
12363 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12364 {
12365 return false;
12366 }
12367 const auto byte2_raw = get();
12368 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12369 {
12370 return false;
12371 }
12372
12373 const auto byte1 = static_cast<unsigned char>(byte1_raw);
12374 const auto byte2 = static_cast<unsigned char>(byte2_raw);
12375
12376 // Code from RFC 7049, Appendix D, Figure 3:
12377 // As half-precision floating-point numbers were only added
12378 // to IEEE 754 in 2008, today's programming platforms often
12379 // still only have limited support for them. It is very
12380 // easy to include at least decoding support for them even
12381 // without such support. An example of a small decoder for
12382 // half-precision floating-point numbers in the C language
12383 // is shown in Fig. 3.
12384 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
12385 const double val = [&half]
12386 {
12387 const int exp = (half >> 10u) & 0x1Fu;
12388 const unsigned int mant = half & 0x3FFu;
12389 JSON_ASSERT(0 <= exp&& exp <= 32);
12390 JSON_ASSERT(mant <= 1024);
12391 switch (exp)
12392 {
12393 case 0:
12394 return std::ldexp(mant, -24);
12395 case 31:
12396 return (mant == 0)
12397 ? std::numeric_limits<double>::infinity()
12398 : std::numeric_limits<double>::quiet_NaN();
12399 default:
12400 return std::ldexp(mant + 1024, exp - 25);
12401 }
12402 }();
12403 return sax->number_float((half & 0x8000u) != 0
12404 ? static_cast<number_float_t>(-val)
12405 : static_cast<number_float_t>(val), "");
12406 }
12407
12408 case 'd':
12409 {
12410 float number{};
12411 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12412 }
12413
12414 case 'D':
12415 {
12416 double number{};
12417 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12418 }
12419
12420 case 'H':
12421 {
12422 return get_ubjson_high_precision_number();
12423 }
12424
12425 case 'C': // char
12426 {
12427 get();
12428 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
12429 {
12430 return false;
12431 }
12432 if (JSON_HEDLEY_UNLIKELY(current > 127))
12433 {
12434 auto last_token = get_token_string();
12435 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
12436 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
12437 }
12438 string_t s(1, static_cast<typename string_t::value_type>(current));
12439 return sax->string(s);
12440 }
12441
12442 case 'S': // string
12443 {
12444 string_t s;
12445 return get_ubjson_string(s) && sax->string(s);
12446 }
12447
12448 case '[': // array
12449 return get_ubjson_array();
12450
12451 case '{': // object
12452 return get_ubjson_object();
12453
12454 default: // anything else
12455 break;
12456 }
12457 auto last_token = get_token_string();
12458 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));
12459 }
12460
12465 {
12466 std::pair<std::size_t, char_int_type> size_and_type;
12467 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12468 {
12469 return false;
12470 }
12471
12472 // 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):
12473 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
12474
12475 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12476 {
12477 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
12478 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)
12479 {
12480 return p.first < t;
12481 });
12482 string_t key = "_ArrayType_";
12483 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
12484 {
12485 auto last_token = get_token_string();
12486 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12487 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
12488 }
12489
12490 string_t type = it->second; // sax->string() takes a reference
12491 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
12492 {
12493 return false;
12494 }
12495
12496 if (size_and_type.second == 'C' || size_and_type.second == 'B')
12497 {
12498 size_and_type.second = 'U';
12499 }
12500
12501 key = "_ArrayData_";
12502 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
12503 {
12504 return false;
12505 }
12506
12507 for (std::size_t i = 0; i < size_and_type.first; ++i)
12508 {
12509 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12510 {
12511 return false;
12512 }
12513 }
12514
12515 return (sax->end_array() && sax->end_object());
12516 }
12517
12518 // If BJData type marker is 'B' decode as binary
12519 if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second == 'B')
12520 {
12521 binary_t result;
12522 return get_binary(input_format, size_and_type.first, result) && sax->binary(result);
12523 }
12524
12525 if (size_and_type.first != npos)
12526 {
12527 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
12528 {
12529 return false;
12530 }
12531
12532 if (size_and_type.second != 0)
12533 {
12534 if (size_and_type.second != 'N')
12535 {
12536 for (std::size_t i = 0; i < size_and_type.first; ++i)
12537 {
12538 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12539 {
12540 return false;
12541 }
12542 }
12543 }
12544 }
12545 else
12546 {
12547 for (std::size_t i = 0; i < size_and_type.first; ++i)
12548 {
12549 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12550 {
12551 return false;
12552 }
12553 }
12554 }
12555 }
12556 else
12557 {
12558 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
12559 {
12560 return false;
12561 }
12562
12563 while (current != ']')
12564 {
12565 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
12566 {
12567 return false;
12568 }
12569 get_ignore_noop();
12570 }
12571 }
12572
12573 return sax->end_array();
12574 }
12575
12580 {
12581 std::pair<std::size_t, char_int_type> size_and_type;
12582 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12583 {
12584 return false;
12585 }
12586
12587 // do not accept ND-array size in objects in BJData
12588 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12589 {
12590 auto last_token = get_token_string();
12591 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12592 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
12593 }
12594
12595 string_t key;
12596 if (size_and_type.first != npos)
12597 {
12598 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
12599 {
12600 return false;
12601 }
12602
12603 if (size_and_type.second != 0)
12604 {
12605 for (std::size_t i = 0; i < size_and_type.first; ++i)
12606 {
12607 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12608 {
12609 return false;
12610 }
12611 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12612 {
12613 return false;
12614 }
12615 key.clear();
12616 }
12617 }
12618 else
12619 {
12620 for (std::size_t i = 0; i < size_and_type.first; ++i)
12621 {
12622 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12623 {
12624 return false;
12625 }
12626 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12627 {
12628 return false;
12629 }
12630 key.clear();
12631 }
12632 }
12633 }
12634 else
12635 {
12636 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
12637 {
12638 return false;
12639 }
12640
12641 while (current != '}')
12642 {
12643 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
12644 {
12645 return false;
12646 }
12647 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12648 {
12649 return false;
12650 }
12651 get_ignore_noop();
12652 key.clear();
12653 }
12654 }
12655
12656 return sax->end_object();
12657 }
12658
12659 // Note, no reader for UBJSON binary types is implemented because they do
12660 // not exist
12661
12663 {
12664 // get the size of the following number string
12665 std::size_t size{};
12666 bool no_ndarray = true;
12667 auto res = get_ubjson_size_value(size, no_ndarray);
12668 if (JSON_HEDLEY_UNLIKELY(!res))
12669 {
12670 return res;
12671 }
12672
12673 // get number string
12674 std::vector<char> number_vector;
12675 for (std::size_t i = 0; i < size; ++i)
12676 {
12677 get();
12678 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12679 {
12680 return false;
12681 }
12682 number_vector.push_back(static_cast<char>(current));
12683 }
12684
12685 // parse number string
12686 using ia_type = decltype(detail::input_adapter(number_vector));
12687 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
12688 const auto result_number = number_lexer.scan();
12689 const auto number_string = number_lexer.get_token_string();
12690 const auto result_remainder = number_lexer.scan();
12691
12692 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
12693
12694 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
12695 {
12696 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12697 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12698 }
12699
12700 switch (result_number)
12701 {
12702 case token_type::value_integer:
12703 return sax->number_integer(number_lexer.get_number_integer());
12704 case token_type::value_unsigned:
12705 return sax->number_unsigned(number_lexer.get_number_unsigned());
12706 case token_type::value_float:
12707 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
12708 case token_type::uninitialized:
12709 case token_type::literal_true:
12710 case token_type::literal_false:
12711 case token_type::literal_null:
12712 case token_type::value_string:
12713 case token_type::begin_array:
12714 case token_type::begin_object:
12715 case token_type::end_array:
12716 case token_type::end_object:
12717 case token_type::name_separator:
12718 case token_type::value_separator:
12719 case token_type::parse_error:
12720 case token_type::end_of_input:
12721 case token_type::literal_or_value:
12722 default:
12723 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12724 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12725 }
12726 }
12727
12729 // Utility functions //
12731
12742 {
12743 ++chars_read;
12744 return current = ia.get_character();
12745 }
12746
12755 template<class T>
12756 bool get_to(T& dest, const input_format_t format, const char* context)
12757 {
12758 auto new_chars_read = ia.get_elements(&dest);
12759 chars_read += new_chars_read;
12760 if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T)))
12761 {
12762 // in case of failure, advance position by 1 to report the failing location
12763 ++chars_read;
12764 sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12765 return false;
12766 }
12767 return true;
12768 }
12769
12774 {
12775 do
12776 {
12777 get();
12778 }
12779 while (current == 'N');
12780
12781 return current;
12782 }
12783
12784 template<class NumberType>
12785 static void byte_swap(NumberType& number)
12786 {
12787 constexpr std::size_t sz = sizeof(number);
12788#ifdef __cpp_lib_byteswap
12789 if constexpr (sz == 1)
12790 {
12791 return;
12792 }
12793 else if constexpr(std::is_integral_v<NumberType>)
12794 {
12795 number = std::byteswap(number);
12796 return;
12797 }
12798 else
12799 {
12800#endif
12801 auto* ptr = reinterpret_cast<std::uint8_t*>(&number);
12802 for (std::size_t i = 0; i < sz / 2; ++i)
12803 {
12804 std::swap(ptr[i], ptr[sz - i - 1]);
12805 }
12806#ifdef __cpp_lib_byteswap
12807 }
12808#endif
12809 }
12810
12811 /*
12812 @brief read a number from the input
12813
12814 @tparam NumberType the type of the number
12815 @param[in] format the current format (for diagnostics)
12816 @param[out] result number of type @a NumberType
12817
12818 @return whether conversion completed
12819
12820 @note This function needs to respect the system's endianness, because
12821 bytes in CBOR, MessagePack, and UBJSON are stored in network order
12822 (big endian) and therefore need reordering on little endian systems.
12823 On the other hand, BSON and BJData use little endian and should reorder
12824 on big endian systems.
12825 */
12826 template<typename NumberType, bool InputIsLittleEndian = false>
12827 bool get_number(const input_format_t format, NumberType& result)
12828 {
12829 // read in the original format
12830
12831 if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number")))
12832 {
12833 return false;
12834 }
12835 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
12836 {
12837 byte_swap(result);
12838 }
12839 return true;
12840 }
12841
12856 template<typename NumberType>
12857 bool get_string(const input_format_t format,
12858 const NumberType len,
12859 string_t& result)
12860 {
12861 bool success = true;
12862 for (NumberType i = 0; i < len; i++)
12863 {
12864 get();
12865 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
12866 {
12867 success = false;
12868 break;
12869 }
12870 result.push_back(static_cast<typename string_t::value_type>(current));
12871 }
12872 return success;
12873 }
12874
12889 template<typename NumberType>
12890 bool get_binary(const input_format_t format,
12891 const NumberType len,
12892 binary_t& result)
12893 {
12894 bool success = true;
12895 for (NumberType i = 0; i < len; i++)
12896 {
12897 get();
12898 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12899 {
12900 success = false;
12901 break;
12902 }
12903 result.push_back(static_cast<typename binary_t::value_type>(current));
12904 }
12905 return success;
12906 }
12907
12914 bool unexpect_eof(const input_format_t format, const char* context) const
12915 {
12917 {
12918 return sax->parse_error(chars_read, "<end of file>",
12919 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12920 }
12921 return true;
12922 }
12923
12927 std::string get_token_string() const
12928 {
12929 std::array<char, 3> cr{{}};
12930 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12931 return std::string{cr.data()};
12932 }
12933
12940 std::string exception_message(const input_format_t format,
12941 const std::string& detail,
12942 const std::string& context) const
12943 {
12944 std::string error_msg = "syntax error while parsing ";
12945
12946 switch (format)
12947 {
12948 case input_format_t::cbor:
12949 error_msg += "CBOR";
12950 break;
12951
12952 case input_format_t::msgpack:
12953 error_msg += "MessagePack";
12954 break;
12955
12956 case input_format_t::ubjson:
12957 error_msg += "UBJSON";
12958 break;
12959
12960 case input_format_t::bson:
12961 error_msg += "BSON";
12962 break;
12963
12964 case input_format_t::bjdata:
12965 error_msg += "BJData";
12966 break;
12967
12968 case input_format_t::json: // LCOV_EXCL_LINE
12969 default: // LCOV_EXCL_LINE
12970 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12971 }
12972
12973 return concat(error_msg, ' ', context, ": ", detail);
12974 }
12975
12976 private:
12977 static JSON_INLINE_VARIABLE constexpr std::size_t npos = detail::unknown_size();
12978
12980 InputAdapterType ia;
12981
12984
12986 std::size_t chars_read = 0;
12987
12989 const bool is_little_endian = little_endianness();
12990
12992 const input_format_t input_format = input_format_t::json;
12993
12995 json_sax_t* sax = nullptr;
12996
12997 // excluded markers in bjdata optimized type
12998#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12999 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
13000
13001#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
13002 make_array<bjd_type>( \
13003 bjd_type{'B', "byte"}, \
13004 bjd_type{'C', "char"}, \
13005 bjd_type{'D', "double"}, \
13006 bjd_type{'I', "int16"}, \
13007 bjd_type{'L', "int64"}, \
13008 bjd_type{'M', "uint64"}, \
13009 bjd_type{'U', "uint8"}, \
13010 bjd_type{'d', "single"}, \
13011 bjd_type{'i', "int8"}, \
13012 bjd_type{'l', "int32"}, \
13013 bjd_type{'m', "uint32"}, \
13014 bjd_type{'u', "uint16"})
13015
13017 // lookup tables
13018 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
13019 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
13021
13022 using bjd_type = std::pair<char_int_type, string_t>;
13023 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
13024 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
13026
13027#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
13028#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
13029};
13030
13031#ifndef JSON_HAS_CPP_17
13032 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
13034#endif
13035
13036} // namespace detail
13038
13039// #include <nlohmann/detail/input/input_adapters.hpp>
13040
13041// #include <nlohmann/detail/input/lexer.hpp>
13042
13043// #include <nlohmann/detail/input/parser.hpp>
13044// __ _____ _____ _____
13045// __| | __| | | | JSON for Modern C++
13046// | | |__ | | | | | | version 3.12.0
13047// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13048//
13049// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
13050// SPDX-License-Identifier: MIT
13051
13052
13053
13054#include <cmath> // isfinite
13055#include <cstdint> // uint8_t
13056#include <functional> // function
13057#include <string> // string
13058#include <utility> // move
13059#include <vector> // vector
13060
13061// #include <nlohmann/detail/exceptions.hpp>
13062
13063// #include <nlohmann/detail/input/input_adapters.hpp>
13064
13065// #include <nlohmann/detail/input/json_sax.hpp>
13066
13067// #include <nlohmann/detail/input/lexer.hpp>
13068
13069// #include <nlohmann/detail/macro_scope.hpp>
13070
13071// #include <nlohmann/detail/meta/is_sax.hpp>
13072
13073// #include <nlohmann/detail/string_concat.hpp>
13074
13075// #include <nlohmann/detail/value_t.hpp>
13076
13077
13079namespace detail
13080{
13082// parser //
13084
13085enum class parse_event_t : std::uint8_t
13086{
13090 object_end,
13094 array_end,
13096 key,
13098 value
13099};
13100
13101template<typename BasicJsonType>
13103 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
13104
13110template<typename BasicJsonType, typename InputAdapterType>
13112{
13113 using number_integer_t = typename BasicJsonType::number_integer_t;
13114 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
13115 using number_float_t = typename BasicJsonType::number_float_t;
13116 using string_t = typename BasicJsonType::string_t;
13119
13120 public:
13122 explicit parser(InputAdapterType&& adapter,
13124 const bool allow_exceptions_ = true,
13125 const bool ignore_comments = false,
13126 const bool ignore_trailing_commas_ = false)
13127 : callback(std::move(cb))
13128 , m_lexer(std::move(adapter), ignore_comments)
13129 , allow_exceptions(allow_exceptions_)
13130 , ignore_trailing_commas(ignore_trailing_commas_)
13131 {
13132 // read first token
13133 get_token();
13134 }
13135
13146 void parse(const bool strict, BasicJsonType& result)
13147 {
13148 if (callback)
13149 {
13150 json_sax_dom_callback_parser<BasicJsonType, InputAdapterType> sdp(result, callback, allow_exceptions, &m_lexer);
13151 sax_parse_internal(&sdp);
13152
13153 // in strict mode, input must be completely read
13154 if (strict && (get_token() != token_type::end_of_input))
13155 {
13156 sdp.parse_error(m_lexer.get_position(),
13157 m_lexer.get_token_string(),
13158 parse_error::create(101, m_lexer.get_position(),
13159 exception_message(token_type::end_of_input, "value"), nullptr));
13160 }
13161
13162 // in case of an error, return a discarded value
13163 if (sdp.is_errored())
13164 {
13165 result = value_t::discarded;
13166 return;
13167 }
13168
13169 // set top-level value to null if it was discarded by the callback
13170 // function
13171 if (result.is_discarded())
13172 {
13173 result = nullptr;
13174 }
13175 }
13176 else
13177 {
13178 json_sax_dom_parser<BasicJsonType, InputAdapterType> sdp(result, allow_exceptions, &m_lexer);
13179 sax_parse_internal(&sdp);
13180
13181 // in strict mode, input must be completely read
13182 if (strict && (get_token() != token_type::end_of_input))
13183 {
13184 sdp.parse_error(m_lexer.get_position(),
13185 m_lexer.get_token_string(),
13186 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13187 }
13188
13189 // in case of an error, return a discarded value
13190 if (sdp.is_errored())
13191 {
13192 result = value_t::discarded;
13193 return;
13194 }
13195 }
13196
13197 result.assert_invariant();
13198 }
13199
13206 bool accept(const bool strict = true)
13207 {
13209 return sax_parse(&sax_acceptor, strict);
13210 }
13211
13212 template<typename SAX>
13214 bool sax_parse(SAX* sax, const bool strict = true)
13215 {
13217 const bool result = sax_parse_internal(sax);
13218
13219 // strict mode: next byte must be EOF
13220 if (result && strict && (get_token() != token_type::end_of_input))
13221 {
13222 return sax->parse_error(m_lexer.get_position(),
13223 m_lexer.get_token_string(),
13224 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13225 }
13226
13227 return result;
13228 }
13229
13230 private:
13231 template<typename SAX>
13233 bool sax_parse_internal(SAX* sax)
13234 {
13235 // stack to remember the hierarchy of structured values we are parsing
13236 // true = array; false = object
13237 std::vector<bool> states;
13238 // value to avoid a goto (see comment where set to true)
13239 bool skip_to_state_evaluation = false;
13240
13241 while (true)
13242 {
13243 if (!skip_to_state_evaluation)
13244 {
13245 // invariant: get_token() was called before each iteration
13246 switch (last_token)
13247 {
13248 case token_type::begin_object:
13249 {
13250 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
13251 {
13252 return false;
13253 }
13254
13255 // closing } -> we are done
13256 if (get_token() == token_type::end_object)
13257 {
13258 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13259 {
13260 return false;
13261 }
13262 break;
13263 }
13264
13265 // parse key
13266 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13267 {
13268 return sax->parse_error(m_lexer.get_position(),
13269 m_lexer.get_token_string(),
13270 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13271 }
13272 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13273 {
13274 return false;
13275 }
13276
13277 // parse separator (:)
13278 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13279 {
13280 return sax->parse_error(m_lexer.get_position(),
13281 m_lexer.get_token_string(),
13282 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13283 }
13284
13285 // remember we are now inside an object
13286 states.push_back(false);
13287
13288 // parse values
13289 get_token();
13290 continue;
13291 }
13292
13293 case token_type::begin_array:
13294 {
13295 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
13296 {
13297 return false;
13298 }
13299
13300 // closing ] -> we are done
13301 if (get_token() == token_type::end_array)
13302 {
13303 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13304 {
13305 return false;
13306 }
13307 break;
13308 }
13309
13310 // remember we are now inside an array
13311 states.push_back(true);
13312
13313 // parse values (no need to call get_token)
13314 continue;
13315 }
13316
13317 case token_type::value_float:
13318 {
13319 const auto res = m_lexer.get_number_float();
13320
13321 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
13322 {
13323 return sax->parse_error(m_lexer.get_position(),
13324 m_lexer.get_token_string(),
13325 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
13326 }
13327
13328 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
13329 {
13330 return false;
13331 }
13332
13333 break;
13334 }
13335
13336 case token_type::literal_false:
13337 {
13338 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
13339 {
13340 return false;
13341 }
13342 break;
13343 }
13344
13345 case token_type::literal_null:
13346 {
13347 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
13348 {
13349 return false;
13350 }
13351 break;
13352 }
13353
13354 case token_type::literal_true:
13355 {
13356 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
13357 {
13358 return false;
13359 }
13360 break;
13361 }
13362
13363 case token_type::value_integer:
13364 {
13365 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
13366 {
13367 return false;
13368 }
13369 break;
13370 }
13371
13372 case token_type::value_string:
13373 {
13374 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
13375 {
13376 return false;
13377 }
13378 break;
13379 }
13380
13381 case token_type::value_unsigned:
13382 {
13383 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
13384 {
13385 return false;
13386 }
13387 break;
13388 }
13389
13390 case token_type::parse_error:
13391 {
13392 // using "uninitialized" to avoid an "expected" message
13393 return sax->parse_error(m_lexer.get_position(),
13394 m_lexer.get_token_string(),
13395 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
13396 }
13397 case token_type::end_of_input:
13398 {
13399 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
13400 {
13401 return sax->parse_error(m_lexer.get_position(),
13402 m_lexer.get_token_string(),
13403 parse_error::create(101, m_lexer.get_position(),
13404 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
13405 }
13406
13407 return sax->parse_error(m_lexer.get_position(),
13408 m_lexer.get_token_string(),
13409 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13410 }
13411 case token_type::uninitialized:
13412 case token_type::end_array:
13413 case token_type::end_object:
13414 case token_type::name_separator:
13415 case token_type::value_separator:
13416 case token_type::literal_or_value:
13417 default: // the last token was unexpected
13418 {
13419 return sax->parse_error(m_lexer.get_position(),
13420 m_lexer.get_token_string(),
13421 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13422 }
13423 }
13424 }
13425 else
13426 {
13427 skip_to_state_evaluation = false;
13428 }
13429
13430 // we reached this line after we successfully parsed a value
13431 if (states.empty())
13432 {
13433 // empty stack: we reached the end of the hierarchy: done
13434 return true;
13435 }
13436
13437 if (states.back()) // array
13438 {
13439 // comma -> next value
13440 // or end of array (ignore_trailing_commas = true)
13441 if (get_token() == token_type::value_separator)
13442 {
13443 // parse a new value
13444 get_token();
13445
13446 // if ignore_trailing_commas and last_token is ], we can continue to "closing ]"
13447 if (!(ignore_trailing_commas && last_token == token_type::end_array))
13448 {
13449 continue;
13450 }
13451 }
13452
13453 // closing ]
13454 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
13455 {
13456 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13457 {
13458 return false;
13459 }
13460
13461 // We are done with this array. Before we can parse a
13462 // new value, we need to evaluate the new state first.
13463 // By setting skip_to_state_evaluation to false, we
13464 // are effectively jumping to the beginning of this if.
13465 JSON_ASSERT(!states.empty());
13466 states.pop_back();
13467 skip_to_state_evaluation = true;
13468 continue;
13469 }
13470
13471 return sax->parse_error(m_lexer.get_position(),
13472 m_lexer.get_token_string(),
13473 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
13474 }
13475
13476 // states.back() is false -> object
13477
13478 // comma -> next value
13479 // or end of object (ignore_trailing_commas = true)
13480 if (get_token() == token_type::value_separator)
13481 {
13482 get_token();
13483
13484 // if ignore_trailing_commas and last_token is }, we can continue to "closing }"
13485 if (!(ignore_trailing_commas && last_token == token_type::end_object))
13486 {
13487 // parse key
13488 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13489 {
13490 return sax->parse_error(m_lexer.get_position(),
13491 m_lexer.get_token_string(),
13492 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13493 }
13494
13495 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13496 {
13497 return false;
13498 }
13499
13500 // parse separator (:)
13501 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13502 {
13503 return sax->parse_error(m_lexer.get_position(),
13504 m_lexer.get_token_string(),
13505 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13506 }
13507
13508 // parse values
13509 get_token();
13510 continue;
13511 }
13512 }
13513
13514 // closing }
13515 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
13516 {
13517 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13518 {
13519 return false;
13520 }
13521
13522 // We are done with this object. Before we can parse a
13523 // new value, we need to evaluate the new state first.
13524 // By setting skip_to_state_evaluation to false, we
13525 // are effectively jumping to the beginning of this if.
13526 JSON_ASSERT(!states.empty());
13527 states.pop_back();
13528 skip_to_state_evaluation = true;
13529 continue;
13530 }
13531
13532 return sax->parse_error(m_lexer.get_position(),
13533 m_lexer.get_token_string(),
13534 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
13535 }
13536 }
13537
13540 {
13541 return last_token = m_lexer.scan();
13542 }
13543
13544 std::string exception_message(const token_type expected, const std::string& context)
13545 {
13546 std::string error_msg = "syntax error ";
13547
13548 if (!context.empty())
13549 {
13550 error_msg += concat("while parsing ", context, ' ');
13551 }
13552
13553 error_msg += "- ";
13554
13555 if (last_token == token_type::parse_error)
13556 {
13557 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
13558 m_lexer.get_token_string(), '\'');
13559 }
13560 else
13561 {
13562 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
13563 }
13564
13565 if (expected != token_type::uninitialized)
13566 {
13567 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
13568 }
13569
13570 return error_msg;
13571 }
13572
13573 private:
13575 const parser_callback_t<BasicJsonType> callback = nullptr;
13577 token_type last_token = token_type::uninitialized;
13581 const bool allow_exceptions = true;
13583 const bool ignore_trailing_commas = false;
13584};
13585
13586} // namespace detail
13588
13589// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13590// __ _____ _____ _____
13591// __| | __| | | | JSON for Modern C++
13592// | | |__ | | | | | | version 3.12.0
13593// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13594//
13595// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
13596// SPDX-License-Identifier: MIT
13597
13598
13599
13600// #include <nlohmann/detail/abi_macros.hpp>
13601
13602// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13603// __ _____ _____ _____
13604// __| | __| | | | JSON for Modern C++
13605// | | |__ | | | | | | version 3.12.0
13606// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13607//
13608// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
13609// SPDX-License-Identifier: MIT
13610
13611
13612
13613#include <cstddef> // ptrdiff_t
13614#include <limits> // numeric_limits
13615
13616// #include <nlohmann/detail/macro_scope.hpp>
13617
13618
13620namespace detail
13621{
13622
13623/*
13624@brief an iterator for primitive JSON types
13625
13626This class models an iterator for primitive JSON types (boolean, number,
13627string). Its only purpose is to allow the iterator/const_iterator classes
13628to "iterate" over primitive values. Internally, the iterator is modeled by
13629a `difference_type` variable. Value begin_value (`0`) models the begin and
13630end_value (`1`) models past the end.
13631*/
13633{
13634 private:
13635 using difference_type = std::ptrdiff_t;
13636 static constexpr difference_type begin_value = 0;
13637 static constexpr difference_type end_value = begin_value + 1;
13638
13641 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
13642
13643 public:
13644 constexpr difference_type get_value() const noexcept
13645 {
13646 return m_it;
13647 }
13648
13650 void set_begin() noexcept
13651 {
13652 m_it = begin_value;
13653 }
13654
13656 void set_end() noexcept
13657 {
13658 m_it = end_value;
13659 }
13660
13662 constexpr bool is_begin() const noexcept
13663 {
13664 return m_it == begin_value;
13665 }
13666
13668 constexpr bool is_end() const noexcept
13669 {
13670 return m_it == end_value;
13671 }
13672
13673 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13674 {
13675 return lhs.m_it == rhs.m_it;
13676 }
13677
13678 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13679 {
13680 return lhs.m_it < rhs.m_it;
13681 }
13682
13684 {
13685 auto result = *this;
13686 result += n;
13687 return result;
13688 }
13689
13691 {
13692 return lhs.m_it - rhs.m_it;
13693 }
13694
13696 {
13697 ++m_it;
13698 return *this;
13699 }
13700
13701 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
13702 {
13703 auto result = *this;
13704 ++m_it;
13705 return result;
13706 }
13707
13709 {
13710 --m_it;
13711 return *this;
13712 }
13713
13714 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
13715 {
13716 auto result = *this;
13717 --m_it;
13718 return result;
13719 }
13720
13722 {
13723 m_it += n;
13724 return *this;
13725 }
13726
13728 {
13729 m_it -= n;
13730 return *this;
13731 }
13732};
13733
13734} // namespace detail
13736
13737
13739namespace detail
13740{
13741
13748template<typename BasicJsonType> struct internal_iterator
13749{
13751 typename BasicJsonType::object_t::iterator object_iterator {};
13753 typename BasicJsonType::array_t::iterator array_iterator {};
13755 primitive_iterator_t primitive_iterator {};
13756};
13757
13758} // namespace detail
13760
13761// #include <nlohmann/detail/iterators/iter_impl.hpp>
13762// __ _____ _____ _____
13763// __| | __| | | | JSON for Modern C++
13764// | | |__ | | | | | | version 3.12.0
13765// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13766//
13767// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
13768// SPDX-License-Identifier: MIT
13769
13770
13771
13772#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
13773#include <type_traits> // conditional, is_const, remove_const
13774
13775// #include <nlohmann/detail/exceptions.hpp>
13776
13777// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13778
13779// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13780
13781// #include <nlohmann/detail/macro_scope.hpp>
13782
13783// #include <nlohmann/detail/meta/cpp_future.hpp>
13784
13785// #include <nlohmann/detail/meta/type_traits.hpp>
13786
13787// #include <nlohmann/detail/value_t.hpp>
13788
13789
13791namespace detail
13792{
13793
13794// forward declare to be able to friend it later on
13795template<typename IteratorType> class iteration_proxy;
13796template<typename IteratorType> class iteration_proxy_value;
13797
13814template<typename BasicJsonType>
13815class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
13816{
13818 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
13824
13825 using object_t = typename BasicJsonType::object_t;
13826 using array_t = typename BasicJsonType::array_t;
13827 // make sure BasicJsonType is basic_json or const basic_json
13829 "iter_impl only accepts (const) basic_json");
13830 // superficial check for the LegacyBidirectionalIterator named requirement
13831 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
13832 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
13833 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
13834
13835 public:
13841 using iterator_category = std::bidirectional_iterator_tag;
13842
13844 using value_type = typename BasicJsonType::value_type;
13846 using difference_type = typename BasicJsonType::difference_type;
13848 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
13849 typename BasicJsonType::const_pointer,
13850 typename BasicJsonType::pointer>::type;
13853 typename std::conditional<std::is_const<BasicJsonType>::value,
13854 typename BasicJsonType::const_reference,
13855 typename BasicJsonType::reference>::type;
13856
13857 iter_impl() = default;
13858 ~iter_impl() = default;
13859 iter_impl(iter_impl&&) noexcept = default;
13860 iter_impl& operator=(iter_impl&&) noexcept = default;
13861
13868 explicit iter_impl(pointer object) noexcept : m_object(object)
13869 {
13870 JSON_ASSERT(m_object != nullptr);
13871
13872 switch (m_object->m_data.m_type)
13873 {
13874 case value_t::object:
13875 {
13876 m_it.object_iterator = typename object_t::iterator();
13877 break;
13878 }
13879
13880 case value_t::array:
13881 {
13882 m_it.array_iterator = typename array_t::iterator();
13883 break;
13884 }
13885
13886 case value_t::null:
13887 case value_t::string:
13888 case value_t::boolean:
13889 case value_t::number_integer:
13890 case value_t::number_unsigned:
13891 case value_t::number_float:
13892 case value_t::binary:
13893 case value_t::discarded:
13894 default:
13895 {
13896 m_it.primitive_iterator = primitive_iterator_t();
13897 break;
13898 }
13899 }
13900 }
13901
13919 : m_object(other.m_object), m_it(other.m_it)
13920 {}
13921
13929 {
13930 if (&other != this)
13931 {
13932 m_object = other.m_object;
13933 m_it = other.m_it;
13934 }
13935 return *this;
13936 }
13937
13943 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13944 : m_object(other.m_object), m_it(other.m_it)
13945 {}
13946
13953 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13954 {
13955 m_object = other.m_object;
13956 m_it = other.m_it;
13957 return *this;
13958 }
13959
13965 void set_begin() noexcept
13966 {
13967 JSON_ASSERT(m_object != nullptr);
13968
13969 switch (m_object->m_data.m_type)
13970 {
13971 case value_t::object:
13972 {
13973 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13974 break;
13975 }
13976
13977 case value_t::array:
13978 {
13979 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13980 break;
13981 }
13982
13983 case value_t::null:
13984 {
13985 // set to end so begin()==end() is true: null is empty
13986 m_it.primitive_iterator.set_end();
13987 break;
13988 }
13989
13990 case value_t::string:
13991 case value_t::boolean:
13992 case value_t::number_integer:
13993 case value_t::number_unsigned:
13994 case value_t::number_float:
13995 case value_t::binary:
13996 case value_t::discarded:
13997 default:
13998 {
13999 m_it.primitive_iterator.set_begin();
14000 break;
14001 }
14002 }
14003 }
14004
14009 void set_end() noexcept
14010 {
14011 JSON_ASSERT(m_object != nullptr);
14012
14013 switch (m_object->m_data.m_type)
14014 {
14015 case value_t::object:
14016 {
14017 m_it.object_iterator = m_object->m_data.m_value.object->end();
14018 break;
14019 }
14020
14021 case value_t::array:
14022 {
14023 m_it.array_iterator = m_object->m_data.m_value.array->end();
14024 break;
14025 }
14026
14027 case value_t::null:
14028 case value_t::string:
14029 case value_t::boolean:
14030 case value_t::number_integer:
14031 case value_t::number_unsigned:
14032 case value_t::number_float:
14033 case value_t::binary:
14034 case value_t::discarded:
14035 default:
14036 {
14037 m_it.primitive_iterator.set_end();
14038 break;
14039 }
14040 }
14041 }
14042
14043 public:
14049 {
14050 JSON_ASSERT(m_object != nullptr);
14051
14052 switch (m_object->m_data.m_type)
14053 {
14054 case value_t::object:
14055 {
14056 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
14057 return m_it.object_iterator->second;
14058 }
14059
14060 case value_t::array:
14061 {
14062 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
14063 return *m_it.array_iterator;
14064 }
14065
14066 case value_t::null:
14067 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14068
14069 case value_t::string:
14070 case value_t::boolean:
14071 case value_t::number_integer:
14072 case value_t::number_unsigned:
14073 case value_t::number_float:
14074 case value_t::binary:
14075 case value_t::discarded:
14076 default:
14077 {
14078 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
14079 {
14080 return *m_object;
14081 }
14082
14083 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14084 }
14085 }
14086 }
14087
14093 {
14094 JSON_ASSERT(m_object != nullptr);
14095
14096 switch (m_object->m_data.m_type)
14097 {
14098 case value_t::object:
14099 {
14100 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
14101 return &(m_it.object_iterator->second);
14102 }
14103
14104 case value_t::array:
14105 {
14106 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
14107 return &*m_it.array_iterator;
14108 }
14109
14110 case value_t::null:
14111 case value_t::string:
14112 case value_t::boolean:
14113 case value_t::number_integer:
14114 case value_t::number_unsigned:
14115 case value_t::number_float:
14116 case value_t::binary:
14117 case value_t::discarded:
14118 default:
14119 {
14120 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
14121 {
14122 return m_object;
14123 }
14124
14125 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14126 }
14127 }
14128 }
14129
14134 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
14135 {
14136 auto result = *this;
14137 ++(*this);
14138 return result;
14139 }
14140
14146 {
14147 JSON_ASSERT(m_object != nullptr);
14148
14149 switch (m_object->m_data.m_type)
14150 {
14151 case value_t::object:
14152 {
14153 std::advance(m_it.object_iterator, 1);
14154 break;
14155 }
14156
14157 case value_t::array:
14158 {
14159 std::advance(m_it.array_iterator, 1);
14160 break;
14161 }
14162
14163 case value_t::null:
14164 case value_t::string:
14165 case value_t::boolean:
14166 case value_t::number_integer:
14167 case value_t::number_unsigned:
14168 case value_t::number_float:
14169 case value_t::binary:
14170 case value_t::discarded:
14171 default:
14172 {
14173 ++m_it.primitive_iterator;
14174 break;
14175 }
14176 }
14177
14178 return *this;
14179 }
14180
14185 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
14186 {
14187 auto result = *this;
14188 --(*this);
14189 return result;
14190 }
14191
14197 {
14198 JSON_ASSERT(m_object != nullptr);
14199
14200 switch (m_object->m_data.m_type)
14201 {
14202 case value_t::object:
14203 {
14204 std::advance(m_it.object_iterator, -1);
14205 break;
14206 }
14207
14208 case value_t::array:
14209 {
14210 std::advance(m_it.array_iterator, -1);
14211 break;
14212 }
14213
14214 case value_t::null:
14215 case value_t::string:
14216 case value_t::boolean:
14217 case value_t::number_integer:
14218 case value_t::number_unsigned:
14219 case value_t::number_float:
14220 case value_t::binary:
14221 case value_t::discarded:
14222 default:
14223 {
14224 --m_it.primitive_iterator;
14225 break;
14226 }
14227 }
14228
14229 return *this;
14230 }
14231
14236 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 >
14237 bool operator==(const IterImpl& other) const
14238 {
14239 // if objects are not the same, the comparison is undefined
14240 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14241 {
14242 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14243 }
14244
14245 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14246 if (m_object == nullptr)
14247 {
14248 return true;
14249 }
14250
14251 switch (m_object->m_data.m_type)
14252 {
14253 case value_t::object:
14254 return (m_it.object_iterator == other.m_it.object_iterator);
14255
14256 case value_t::array:
14257 return (m_it.array_iterator == other.m_it.array_iterator);
14258
14259 case value_t::null:
14260 case value_t::string:
14261 case value_t::boolean:
14262 case value_t::number_integer:
14263 case value_t::number_unsigned:
14264 case value_t::number_float:
14265 case value_t::binary:
14266 case value_t::discarded:
14267 default:
14268 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
14269 }
14270 }
14271
14276 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 >
14277 bool operator!=(const IterImpl& other) const
14278 {
14279 return !operator==(other);
14280 }
14281
14286 bool operator<(const iter_impl& other) const
14287 {
14288 // if objects are not the same, the comparison is undefined
14289 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14290 {
14291 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14292 }
14293
14294 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14295 if (m_object == nullptr)
14296 {
14297 // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false
14298 return false;
14299 }
14300
14301 switch (m_object->m_data.m_type)
14302 {
14303 case value_t::object:
14304 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
14305
14306 case value_t::array:
14307 return (m_it.array_iterator < other.m_it.array_iterator);
14308
14309 case value_t::null:
14310 case value_t::string:
14311 case value_t::boolean:
14312 case value_t::number_integer:
14313 case value_t::number_unsigned:
14314 case value_t::number_float:
14315 case value_t::binary:
14316 case value_t::discarded:
14317 default:
14318 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
14319 }
14320 }
14321
14326 bool operator<=(const iter_impl& other) const
14327 {
14328 return !other.operator < (*this);
14329 }
14330
14335 bool operator>(const iter_impl& other) const
14336 {
14337 return !operator<=(other);
14338 }
14339
14344 bool operator>=(const iter_impl& other) const
14345 {
14346 return !operator<(other);
14347 }
14348
14354 {
14355 JSON_ASSERT(m_object != nullptr);
14356
14357 switch (m_object->m_data.m_type)
14358 {
14359 case value_t::object:
14360 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14361
14362 case value_t::array:
14363 {
14364 std::advance(m_it.array_iterator, i);
14365 break;
14366 }
14367
14368 case value_t::null:
14369 case value_t::string:
14370 case value_t::boolean:
14371 case value_t::number_integer:
14372 case value_t::number_unsigned:
14373 case value_t::number_float:
14374 case value_t::binary:
14375 case value_t::discarded:
14376 default:
14377 {
14378 m_it.primitive_iterator += i;
14379 break;
14380 }
14381 }
14382
14383 return *this;
14384 }
14385
14391 {
14392 return operator+=(-i);
14393 }
14394
14400 {
14401 auto result = *this;
14402 result += i;
14403 return result;
14404 }
14405
14411 {
14412 auto result = it;
14413 result += i;
14414 return result;
14415 }
14416
14422 {
14423 auto result = *this;
14424 result -= i;
14425 return result;
14426 }
14427
14433 {
14434 JSON_ASSERT(m_object != nullptr);
14435
14436 switch (m_object->m_data.m_type)
14437 {
14438 case value_t::object:
14439 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14440
14441 case value_t::array:
14442 return m_it.array_iterator - other.m_it.array_iterator;
14443
14444 case value_t::null:
14445 case value_t::string:
14446 case value_t::boolean:
14447 case value_t::number_integer:
14448 case value_t::number_unsigned:
14449 case value_t::number_float:
14450 case value_t::binary:
14451 case value_t::discarded:
14452 default:
14453 return m_it.primitive_iterator - other.m_it.primitive_iterator;
14454 }
14455 }
14456
14462 {
14463 JSON_ASSERT(m_object != nullptr);
14464
14465 switch (m_object->m_data.m_type)
14466 {
14467 case value_t::object:
14468 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
14469
14470 case value_t::array:
14471 return *std::next(m_it.array_iterator, n);
14472
14473 case value_t::null:
14474 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14475
14476 case value_t::string:
14477 case value_t::boolean:
14478 case value_t::number_integer:
14479 case value_t::number_unsigned:
14480 case value_t::number_float:
14481 case value_t::binary:
14482 case value_t::discarded:
14483 default:
14484 {
14485 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
14486 {
14487 return *m_object;
14488 }
14489
14490 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14491 }
14492 }
14493 }
14494
14499 const typename object_t::key_type& key() const
14500 {
14501 JSON_ASSERT(m_object != nullptr);
14502
14503 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
14504 {
14505 return m_it.object_iterator->first;
14506 }
14507
14508 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
14509 }
14510
14516 {
14517 return operator*();
14518 }
14519
14522 pointer m_object = nullptr;
14525};
14526
14527} // namespace detail
14529
14530// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
14531
14532// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
14533// __ _____ _____ _____
14534// __| | __| | | | JSON for Modern C++
14535// | | |__ | | | | | | version 3.12.0
14536// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14537//
14538// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
14539// SPDX-License-Identifier: MIT
14540
14541
14542
14543#include <cstddef> // ptrdiff_t
14544#include <iterator> // reverse_iterator
14545#include <utility> // declval
14546
14547// #include <nlohmann/detail/abi_macros.hpp>
14548
14549
14551namespace detail
14552{
14553
14555// reverse_iterator //
14557
14576template<typename Base>
14577class json_reverse_iterator : public std::reverse_iterator<Base>
14578{
14579 public:
14580 using difference_type = std::ptrdiff_t;
14582 using base_iterator = std::reverse_iterator<Base>;
14584 using reference = typename Base::reference;
14585
14587 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
14588 : base_iterator(it) {}
14589
14591 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
14592
14594 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
14595 {
14596 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
14597 }
14598
14601 {
14602 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
14603 }
14604
14606 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
14607 {
14608 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
14609 }
14610
14613 {
14614 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
14615 }
14616
14619 {
14620 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
14621 }
14622
14625 {
14626 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
14627 }
14628
14631 {
14632 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
14633 }
14634
14637 {
14638 return base_iterator(*this) - base_iterator(other);
14639 }
14640
14643 {
14644 return *(this->operator+(n));
14645 }
14646
14648 auto key() const -> decltype(std::declval<Base>().key())
14649 {
14650 auto it = --this->base();
14651 return it.key();
14652 }
14653
14656 {
14657 auto it = --this->base();
14658 return it.operator * ();
14659 }
14660};
14661
14662} // namespace detail
14664
14665// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
14666
14667// #include <nlohmann/detail/json_custom_base_class.hpp>
14668// __ _____ _____ _____
14669// __| | __| | | | JSON for Modern C++
14670// | | |__ | | | | | | version 3.12.0
14671// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14672//
14673// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
14674// SPDX-License-Identifier: MIT
14675
14676
14677
14678#include <type_traits> // conditional, is_same
14679
14680// #include <nlohmann/detail/abi_macros.hpp>
14681
14682
14684namespace detail
14685{
14686
14698
14699template<class T>
14700using json_base_class = typename std::conditional <
14701 std::is_same<T, void>::value,
14703 T
14704 >::type;
14705
14706} // namespace detail
14708
14709// #include <nlohmann/detail/json_pointer.hpp>
14710// __ _____ _____ _____
14711// __| | __| | | | JSON for Modern C++
14712// | | |__ | | | | | | version 3.12.0
14713// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14714//
14715// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
14716// SPDX-License-Identifier: MIT
14717
14718
14719
14720#include <algorithm> // all_of
14721#include <cctype> // isdigit
14722#include <cerrno> // errno, ERANGE
14723#include <cstdlib> // strtoull
14724#ifndef JSON_NO_IO
14725 #include <iosfwd> // ostream
14726#endif // JSON_NO_IO
14727#include <limits> // max
14728#include <numeric> // accumulate
14729#include <string> // string
14730#include <utility> // move
14731#include <vector> // vector
14732
14733// #include <nlohmann/detail/exceptions.hpp>
14734
14735// #include <nlohmann/detail/macro_scope.hpp>
14736
14737// #include <nlohmann/detail/string_concat.hpp>
14738
14739// #include <nlohmann/detail/string_escape.hpp>
14740
14741// #include <nlohmann/detail/value_t.hpp>
14742
14743
14745
14748template<typename RefStringType>
14750{
14751 // allow basic_json to access private members
14753 friend class basic_json;
14754
14755 template<typename>
14756 friend class json_pointer;
14757
14758 template<typename T>
14760 {
14761 using type = T;
14762 };
14763
14766 {
14767 using type = StringType;
14768 };
14769
14770 public:
14771 // for backwards compatibility accept BasicJsonType
14773
14776 explicit json_pointer(const string_t& s = "")
14777 : reference_tokens(split(s))
14778 {}
14779
14783 {
14784 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
14785 string_t{},
14786 [](const string_t& a, const string_t& b)
14787 {
14788 return detail::concat(a, '/', detail::escape(b));
14789 });
14790 }
14791
14795 operator string_t() const
14796 {
14797 return to_string();
14798 }
14799
14800#ifndef JSON_NO_IO
14803 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
14804 {
14805 o << ptr.to_string();
14806 return o;
14807 }
14808#endif
14809
14813 {
14814 reference_tokens.insert(reference_tokens.end(),
14815 ptr.reference_tokens.begin(),
14816 ptr.reference_tokens.end());
14817 return *this;
14818 }
14819
14823 {
14824 push_back(std::move(token));
14825 return *this;
14826 }
14827
14830 json_pointer& operator/=(std::size_t array_idx)
14831 {
14832 return *this /= std::to_string(array_idx);
14833 }
14834
14838 const json_pointer& rhs)
14839 {
14840 return json_pointer(lhs) /= rhs;
14841 }
14842
14845 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
14846 {
14847 return json_pointer(lhs) /= std::move(token);
14848 }
14849
14852 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
14853 {
14854 return json_pointer(lhs) /= array_idx;
14855 }
14856
14860 {
14861 if (empty())
14862 {
14863 return *this;
14864 }
14865
14866 json_pointer res = *this;
14867 res.pop_back();
14868 return res;
14869 }
14870
14874 {
14875 if (JSON_HEDLEY_UNLIKELY(empty()))
14876 {
14877 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14878 }
14879
14880 reference_tokens.pop_back();
14881 }
14882
14885 const string_t& back() const
14886 {
14887 if (JSON_HEDLEY_UNLIKELY(empty()))
14888 {
14889 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14890 }
14891
14892 return reference_tokens.back();
14893 }
14894
14897 void push_back(const string_t& token)
14898 {
14899 reference_tokens.push_back(token);
14900 }
14901
14904 void push_back(string_t&& token)
14905 {
14906 reference_tokens.push_back(std::move(token));
14907 }
14908
14911 bool empty() const noexcept
14912 {
14913 return reference_tokens.empty();
14914 }
14915
14916 private:
14927 template<typename BasicJsonType>
14928 static typename BasicJsonType::size_type array_index(const string_t& s)
14929 {
14930 using size_type = typename BasicJsonType::size_type;
14931
14932 // error condition (cf. RFC 6901, Sect. 4)
14933 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14934 {
14935 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14936 }
14937
14938 // error condition (cf. RFC 6901, Sect. 4)
14939 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14940 {
14941 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14942 }
14943
14944 const char* p = s.c_str();
14945 char* p_end = nullptr; // NOLINT(misc-const-correctness)
14946 errno = 0; // strtoull doesn't reset errno
14947 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14948 if (p == p_end // invalid input or empty string
14949 || errno == ERANGE // out of range
14950 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14951 {
14952 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14953 }
14954
14955 // only triggered on special platforms (like 32bit), see also
14956 // https://github.com/nlohmann/json/pull/2203
14957 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14958 {
14959 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14960 }
14961
14962 return static_cast<size_type>(res);
14963 }
14964
14966 json_pointer top() const
14967 {
14968 if (JSON_HEDLEY_UNLIKELY(empty()))
14969 {
14970 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14971 }
14972
14973 json_pointer result = *this;
14974 result.reference_tokens = {reference_tokens[0]};
14975 return result;
14976 }
14977
14978 private:
14987 template<typename BasicJsonType>
14988 BasicJsonType& get_and_create(BasicJsonType& j) const
14989 {
14990 auto* result = &j;
14991
14992 // in case no reference tokens exist, return a reference to the JSON value
14993 // j which will be overwritten by a primitive value
14994 for (const auto& reference_token : reference_tokens)
14995 {
14996 switch (result->type())
14997 {
14999 {
15000 if (reference_token == "0")
15001 {
15002 // start a new array if the reference token is 0
15003 result = &result->operator[](0);
15004 }
15005 else
15006 {
15007 // start a new object otherwise
15008 result = &result->operator[](reference_token);
15009 }
15010 break;
15011 }
15012
15014 {
15015 // create an entry in the object
15016 result = &result->operator[](reference_token);
15017 break;
15018 }
15019
15021 {
15022 // create an entry in the array
15023 result = &result->operator[](array_index<BasicJsonType>(reference_token));
15024 break;
15025 }
15026
15027 /*
15028 The following code is only reached if there exists a reference
15029 token _and_ the current value is primitive. In this case, we have
15030 an error situation, because primitive values may only occur as
15031 a single value; that is, with an empty list of reference tokens.
15032 */
15040 default:
15041 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
15042 }
15043 }
15044
15045 return *result;
15046 }
15047
15067 template<typename BasicJsonType>
15068 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
15069 {
15070 for (const auto& reference_token : reference_tokens)
15071 {
15072 // convert null values to arrays or objects before continuing
15073 if (ptr->is_null())
15074 {
15075 // check if the reference token is a number
15076 const bool nums =
15077 std::all_of(reference_token.begin(), reference_token.end(),
15078 [](const unsigned char x)
15079 {
15080 return std::isdigit(x);
15081 });
15082
15083 // change value to an array for numbers or "-" or to object otherwise
15084 *ptr = (nums || reference_token == "-")
15087 }
15088
15089 switch (ptr->type())
15090 {
15092 {
15093 // use unchecked object access
15094 ptr = &ptr->operator[](reference_token);
15095 break;
15096 }
15097
15099 {
15100 if (reference_token == "-")
15101 {
15102 // explicitly treat "-" as index beyond the end
15103 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
15104 }
15105 else
15106 {
15107 // convert array index to number; unchecked access
15108 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
15109 }
15110 break;
15111 }
15112
15121 default:
15122 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15123 }
15124 }
15125
15126 return *ptr;
15127 }
15128
15135 template<typename BasicJsonType>
15136 BasicJsonType& get_checked(BasicJsonType* ptr) const
15137 {
15138 for (const auto& reference_token : reference_tokens)
15139 {
15140 switch (ptr->type())
15141 {
15143 {
15144 // note: at performs range check
15145 ptr = &ptr->at(reference_token);
15146 break;
15147 }
15148
15150 {
15151 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15152 {
15153 // "-" always fails the range check
15155 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15156 ") is out of range"), ptr));
15157 }
15158
15159 // note: at performs range check
15160 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15161 break;
15162 }
15163
15172 default:
15173 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15174 }
15175 }
15176
15177 return *ptr;
15178 }
15179
15193 template<typename BasicJsonType>
15194 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
15195 {
15196 for (const auto& reference_token : reference_tokens)
15197 {
15198 switch (ptr->type())
15199 {
15201 {
15202 // use unchecked object access
15203 ptr = &ptr->operator[](reference_token);
15204 break;
15205 }
15206
15208 {
15209 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15210 {
15211 // "-" cannot be used for const access
15212 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));
15213 }
15214
15215 // use unchecked array access
15216 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
15217 break;
15218 }
15219
15228 default:
15229 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15230 }
15231 }
15232
15233 return *ptr;
15234 }
15235
15242 template<typename BasicJsonType>
15243 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
15244 {
15245 for (const auto& reference_token : reference_tokens)
15246 {
15247 switch (ptr->type())
15248 {
15250 {
15251 // note: at performs range check
15252 ptr = &ptr->at(reference_token);
15253 break;
15254 }
15255
15257 {
15258 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15259 {
15260 // "-" always fails the range check
15262 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15263 ") is out of range"), ptr));
15264 }
15265
15266 // note: at performs range check
15267 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15268 break;
15269 }
15270
15279 default:
15280 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15281 }
15282 }
15283
15284 return *ptr;
15285 }
15286
15291 template<typename BasicJsonType>
15292 bool contains(const BasicJsonType* ptr) const
15293 {
15294 for (const auto& reference_token : reference_tokens)
15295 {
15296 switch (ptr->type())
15297 {
15299 {
15300 if (!ptr->contains(reference_token))
15301 {
15302 // we did not find the key in the object
15303 return false;
15304 }
15305
15306 ptr = &ptr->operator[](reference_token);
15307 break;
15308 }
15309
15311 {
15312 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15313 {
15314 // "-" always fails the range check
15315 return false;
15316 }
15317 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
15318 {
15319 // invalid char
15320 return false;
15321 }
15322 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
15323 {
15324 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
15325 {
15326 // the first char should be between '1' and '9'
15327 return false;
15328 }
15329 for (std::size_t i = 1; i < reference_token.size(); i++)
15330 {
15331 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
15332 {
15333 // other char should be between '0' and '9'
15334 return false;
15335 }
15336 }
15337 }
15338
15339 const auto idx = array_index<BasicJsonType>(reference_token);
15340 if (idx >= ptr->size())
15341 {
15342 // index out of range
15343 return false;
15344 }
15345
15346 ptr = &ptr->operator[](idx);
15347 break;
15348 }
15349
15358 default:
15359 {
15360 // we do not expect primitive values if there is still a
15361 // reference token to process
15362 return false;
15363 }
15364 }
15365 }
15366
15367 // no reference token left means we found a primitive value
15368 return true;
15369 }
15370
15380 static std::vector<string_t> split(const string_t& reference_string)
15381 {
15382 std::vector<string_t> result;
15383
15384 // special case: empty reference string -> no reference tokens
15385 if (reference_string.empty())
15386 {
15387 return result;
15388 }
15389
15390 // check if a nonempty reference string begins with slash
15391 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
15392 {
15393 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
15394 }
15395
15396 // extract the reference tokens:
15397 // - slash: position of the last read slash (or end of string)
15398 // - start: position after the previous slash
15399 for (
15400 // search for the first slash after the first character
15401 std::size_t slash = reference_string.find_first_of('/', 1),
15402 // set the beginning of the first reference token
15403 start = 1;
15404 // we can stop if start == 0 (if slash == string_t::npos)
15405 start != 0;
15406 // set the beginning of the next reference token
15407 // (will eventually be 0 if slash == string_t::npos)
15408 start = (slash == string_t::npos) ? 0 : slash + 1,
15409 // find next slash
15410 slash = reference_string.find_first_of('/', start))
15411 {
15412 // use the text between the beginning of the reference token
15413 // (start) and the last slash (slash).
15414 auto reference_token = reference_string.substr(start, slash - start);
15415
15416 // check reference tokens are properly escaped
15417 for (std::size_t pos = reference_token.find_first_of('~');
15418 pos != string_t::npos;
15419 pos = reference_token.find_first_of('~', pos + 1))
15420 {
15421 JSON_ASSERT(reference_token[pos] == '~');
15422
15423 // ~ must be followed by 0 or 1
15424 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
15425 (reference_token[pos + 1] != '0' &&
15426 reference_token[pos + 1] != '1')))
15427 {
15428 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
15429 }
15430 }
15431
15432 // finally, store the reference token
15433 detail::unescape(reference_token);
15434 result.push_back(reference_token);
15435 }
15436
15437 return result;
15438 }
15439
15440 private:
15448 template<typename BasicJsonType>
15449 static void flatten(const string_t& reference_string,
15450 const BasicJsonType& value,
15451 BasicJsonType& result)
15452 {
15453 switch (value.type())
15454 {
15456 {
15457 if (value.m_data.m_value.array->empty())
15458 {
15459 // flatten empty array as null
15460 result[reference_string] = nullptr;
15461 }
15462 else
15463 {
15464 // iterate array and use index as a reference string
15465 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
15466 {
15467 flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
15468 value.m_data.m_value.array->operator[](i), result);
15469 }
15470 }
15471 break;
15472 }
15473
15475 {
15476 if (value.m_data.m_value.object->empty())
15477 {
15478 // flatten empty object as null
15479 result[reference_string] = nullptr;
15480 }
15481 else
15482 {
15483 // iterate object and use keys as reference string
15484 for (const auto& element : *value.m_data.m_value.object)
15485 {
15486 flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
15487 }
15488 }
15489 break;
15490 }
15491
15500 default:
15501 {
15502 // add a primitive value with its reference string
15503 result[reference_string] = value;
15504 break;
15505 }
15506 }
15507 }
15508
15519 template<typename BasicJsonType>
15520 static BasicJsonType
15521 unflatten(const BasicJsonType& value)
15522 {
15523 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
15524 {
15525 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
15526 }
15527
15528 BasicJsonType result;
15529
15530 // iterate the JSON object values
15531 for (const auto& element : *value.m_data.m_value.object)
15532 {
15533 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
15534 {
15535 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
15536 }
15537
15538 // Assign the value to the reference pointed to by JSON pointer. Note
15539 // that if the JSON pointer is "" (i.e., points to the whole value),
15540 // function get_and_create returns a reference to the result itself.
15541 // An assignment will then create a primitive value.
15542 json_pointer(element.first).get_and_create(result) = element.second;
15543 }
15544
15545 return result;
15546 }
15547
15548 // can't use the conversion operator because of ambiguity
15550 {
15552 result.reference_tokens = reference_tokens;
15553 return result;
15554 }
15555
15557 {
15559 result.reference_tokens = std::move(reference_tokens);
15560 return result;
15561 }
15562
15563 public:
15564#if JSON_HAS_THREE_WAY_COMPARISON
15567 template<typename RefStringTypeRhs>
15568 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
15569 {
15570 return reference_tokens == rhs.reference_tokens;
15571 }
15572
15575 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
15576 bool operator==(const string_t& rhs) const
15577 {
15578 return *this == json_pointer(rhs);
15579 }
15580
15582 template<typename RefStringTypeRhs>
15583 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
15584 {
15585 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
15586 }
15587#else
15590 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15591 // NOLINTNEXTLINE(readability-redundant-declaration)
15592 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15593 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15594
15597 template<typename RefStringTypeLhs, typename StringType>
15598 // NOLINTNEXTLINE(readability-redundant-declaration)
15599 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15600 const StringType& rhs);
15601
15604 template<typename RefStringTypeRhs, typename StringType>
15605 // NOLINTNEXTLINE(readability-redundant-declaration)
15606 friend bool operator==(const StringType& lhs,
15608
15611 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15612 // NOLINTNEXTLINE(readability-redundant-declaration)
15613 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15614 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15615
15618 template<typename RefStringTypeLhs, typename StringType>
15619 // NOLINTNEXTLINE(readability-redundant-declaration)
15620 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15621 const StringType& rhs);
15622
15625 template<typename RefStringTypeRhs, typename StringType>
15626 // NOLINTNEXTLINE(readability-redundant-declaration)
15627 friend bool operator!=(const StringType& lhs,
15629
15631 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15632 // NOLINTNEXTLINE(readability-redundant-declaration)
15633 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
15634 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15635#endif
15636
15637 private:
15639 std::vector<string_t> reference_tokens;
15640};
15641
15642#if !JSON_HAS_THREE_WAY_COMPARISON
15643// functions cannot be defined inside the class due to ODR violations
15644template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15646 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15647{
15648 return lhs.reference_tokens == rhs.reference_tokens;
15649}
15650
15651template<typename RefStringTypeLhs,
15652 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15654inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15655 const StringType& rhs)
15656{
15657 return lhs == json_pointer<RefStringTypeLhs>(rhs);
15658}
15659
15660template<typename RefStringTypeRhs,
15661 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15663inline bool operator==(const StringType& lhs,
15664 const json_pointer<RefStringTypeRhs>& rhs)
15665{
15666 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
15667}
15668
15669template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15671 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15672{
15673 return !(lhs == rhs);
15674}
15675
15676template<typename RefStringTypeLhs,
15677 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15679inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15680 const StringType& rhs)
15681{
15682 return !(lhs == rhs);
15683}
15684
15685template<typename RefStringTypeRhs,
15686 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15688inline bool operator!=(const StringType& lhs,
15689 const json_pointer<RefStringTypeRhs>& rhs)
15690{
15691 return !(lhs == rhs);
15692}
15693
15694template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15696 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15697{
15698 return lhs.reference_tokens < rhs.reference_tokens;
15699}
15700#endif
15701
15703
15704// #include <nlohmann/detail/json_ref.hpp>
15705// __ _____ _____ _____
15706// __| | __| | | | JSON for Modern C++
15707// | | |__ | | | | | | version 3.12.0
15708// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15709//
15710// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
15711// SPDX-License-Identifier: MIT
15712
15713
15714
15715#include <initializer_list>
15716#include <utility>
15717
15718// #include <nlohmann/detail/abi_macros.hpp>
15719
15720// #include <nlohmann/detail/meta/type_traits.hpp>
15721
15722
15724namespace detail
15725{
15726
15727template<typename BasicJsonType>
15729{
15730 public:
15731 using value_type = BasicJsonType;
15732
15734 : owned_value(std::move(value))
15735 {}
15736
15737 json_ref(const value_type& value)
15738 : value_ref(&value)
15739 {}
15740
15741 json_ref(std::initializer_list<json_ref> init)
15742 : owned_value(init)
15743 {}
15744
15745 template <
15746 class... Args,
15747 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
15748 json_ref(Args && ... args)
15749 : owned_value(std::forward<Args>(args)...)
15750 {}
15751
15752 // class should be movable only
15753 json_ref(json_ref&&) noexcept = default;
15754 json_ref(const json_ref&) = delete;
15755 json_ref& operator=(const json_ref&) = delete;
15756 json_ref& operator=(json_ref&&) = delete;
15757 ~json_ref() = default;
15758
15759 value_type moved_or_copied() const
15760 {
15761 if (value_ref == nullptr)
15762 {
15763 return std::move(owned_value);
15764 }
15765 return *value_ref;
15766 }
15767
15768 value_type const& operator*() const
15769 {
15770 return value_ref ? *value_ref : owned_value;
15771 }
15772
15773 value_type const* operator->() const
15774 {
15775 return &** this;
15776 }
15777
15778 private:
15779 mutable value_type owned_value = nullptr;
15780 value_type const* value_ref = nullptr;
15781};
15782
15783} // namespace detail
15785
15786// #include <nlohmann/detail/macro_scope.hpp>
15787
15788// #include <nlohmann/detail/string_concat.hpp>
15789
15790// #include <nlohmann/detail/string_escape.hpp>
15791
15792// #include <nlohmann/detail/string_utils.hpp>
15793
15794// #include <nlohmann/detail/meta/cpp_future.hpp>
15795
15796// #include <nlohmann/detail/meta/type_traits.hpp>
15797
15798// #include <nlohmann/detail/output/binary_writer.hpp>
15799// __ _____ _____ _____
15800// __| | __| | | | JSON for Modern C++
15801// | | |__ | | | | | | version 3.12.0
15802// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15803//
15804// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
15805// SPDX-License-Identifier: MIT
15806
15807
15808
15809#include <algorithm> // reverse
15810#include <array> // array
15811#include <map> // map
15812#include <cmath> // isnan, isinf
15813#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
15814#include <cstring> // memcpy
15815#include <limits> // numeric_limits
15816#include <string> // string
15817#include <utility> // move
15818#include <vector> // vector
15819
15820// #include <nlohmann/detail/input/binary_reader.hpp>
15821
15822// #include <nlohmann/detail/macro_scope.hpp>
15823
15824// #include <nlohmann/detail/output/output_adapters.hpp>
15825// __ _____ _____ _____
15826// __| | __| | | | JSON for Modern C++
15827// | | |__ | | | | | | version 3.12.0
15828// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15829//
15830// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
15831// SPDX-License-Identifier: MIT
15832
15833
15834
15835#include <algorithm> // copy
15836#include <cstddef> // size_t
15837#include <iterator> // back_inserter
15838#include <memory> // shared_ptr, make_shared
15839#include <string> // basic_string
15840#include <vector> // vector
15841
15842#ifndef JSON_NO_IO
15843 #include <ios> // streamsize
15844 #include <ostream> // basic_ostream
15845#endif // JSON_NO_IO
15846
15847// #include <nlohmann/detail/macro_scope.hpp>
15848
15849
15851namespace detail
15852{
15853
15855template<typename CharType> struct output_adapter_protocol
15856{
15857 virtual void write_character(CharType c) = 0;
15858 virtual void write_characters(const CharType* s, std::size_t length) = 0;
15859 virtual ~output_adapter_protocol() = default;
15860
15865 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
15866};
15867
15869template<typename CharType>
15870using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
15871
15873template<typename CharType, typename AllocatorType = std::allocator<CharType>>
15875{
15876 public:
15877 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
15878 : v(vec)
15879 {}
15880
15881 void write_character(CharType c) override
15882 {
15883 v.push_back(c);
15884 }
15885
15887 void write_characters(const CharType* s, std::size_t length) override
15888 {
15889 v.insert(v.end(), s, s + length);
15890 }
15891
15892 private:
15893 std::vector<CharType, AllocatorType>& v;
15894};
15895
15896#ifndef JSON_NO_IO
15898template<typename CharType>
15900{
15901 public:
15902 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15903 : stream(s)
15904 {}
15905
15906 void write_character(CharType c) override
15907 {
15908 stream.put(c);
15909 }
15910
15912 void write_characters(const CharType* s, std::size_t length) override
15913 {
15914 stream.write(s, static_cast<std::streamsize>(length));
15915 }
15916
15917 private:
15918 std::basic_ostream<CharType>& stream;
15919};
15920#endif // JSON_NO_IO
15921
15923template<typename CharType, typename StringType = std::basic_string<CharType>>
15925{
15926 public:
15927 explicit output_string_adapter(StringType& s) noexcept
15928 : str(s)
15929 {}
15930
15931 void write_character(CharType c) override
15932 {
15933 str.push_back(c);
15934 }
15935
15937 void write_characters(const CharType* s, std::size_t length) override
15938 {
15939 str.append(s, length);
15940 }
15941
15942 private:
15943 StringType& str;
15944};
15945
15946template<typename CharType, typename StringType = std::basic_string<CharType>>
15948{
15949 public:
15950 template<typename AllocatorType = std::allocator<CharType>>
15951 output_adapter(std::vector<CharType, AllocatorType>& vec)
15952 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15953
15954#ifndef JSON_NO_IO
15955 output_adapter(std::basic_ostream<CharType>& s)
15956 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15957#endif // JSON_NO_IO
15958
15959 output_adapter(StringType& s)
15960 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15961
15963 {
15964 return oa;
15965 }
15966
15967 private:
15969};
15970
15971} // namespace detail
15973
15974// #include <nlohmann/detail/string_concat.hpp>
15975
15976
15978namespace detail
15979{
15980
15983{
15984 draft2,
15985 draft3,
15986};
15987
15989// binary writer //
15991
15995template<typename BasicJsonType, typename CharType>
15997{
15998 using string_t = typename BasicJsonType::string_t;
15999 using binary_t = typename BasicJsonType::binary_t;
16000 using number_float_t = typename BasicJsonType::number_float_t;
16001
16002 public:
16008 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
16009 {
16010 JSON_ASSERT(oa);
16011 }
16012
16017 void write_bson(const BasicJsonType& j)
16018 {
16019 switch (j.type())
16020 {
16021 case value_t::object:
16022 {
16023 write_bson_object(*j.m_data.m_value.object);
16024 break;
16025 }
16026
16027 case value_t::null:
16028 case value_t::array:
16029 case value_t::string:
16030 case value_t::boolean:
16031 case value_t::number_integer:
16032 case value_t::number_unsigned:
16033 case value_t::number_float:
16034 case value_t::binary:
16035 case value_t::discarded:
16036 default:
16037 {
16038 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
16039 }
16040 }
16041 }
16042
16046 void write_cbor(const BasicJsonType& j)
16047 {
16048 switch (j.type())
16049 {
16050 case value_t::null:
16051 {
16052 oa->write_character(to_char_type(0xF6));
16053 break;
16054 }
16055
16056 case value_t::boolean:
16057 {
16058 oa->write_character(j.m_data.m_value.boolean
16059 ? to_char_type(0xF5)
16060 : to_char_type(0xF4));
16061 break;
16062 }
16063
16064 case value_t::number_integer:
16065 {
16066 if (j.m_data.m_value.number_integer >= 0)
16067 {
16068 // CBOR does not differentiate between positive signed
16069 // integers and unsigned integers. Therefore, we used the
16070 // code from the value_t::number_unsigned case here.
16071 if (j.m_data.m_value.number_integer <= 0x17)
16072 {
16073 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16074 }
16075 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
16076 {
16077 oa->write_character(to_char_type(0x18));
16078 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16079 }
16080 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
16081 {
16082 oa->write_character(to_char_type(0x19));
16083 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16084 }
16085 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
16086 {
16087 oa->write_character(to_char_type(0x1A));
16088 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16089 }
16090 else
16091 {
16092 oa->write_character(to_char_type(0x1B));
16093 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16094 }
16095 }
16096 else
16097 {
16098 // The conversions below encode the sign in the first
16099 // byte, and the value is converted to a positive number.
16100 const auto positive_number = -1 - j.m_data.m_value.number_integer;
16101 if (j.m_data.m_value.number_integer >= -24)
16102 {
16103 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
16104 }
16105 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
16106 {
16107 oa->write_character(to_char_type(0x38));
16108 write_number(static_cast<std::uint8_t>(positive_number));
16109 }
16110 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
16111 {
16112 oa->write_character(to_char_type(0x39));
16113 write_number(static_cast<std::uint16_t>(positive_number));
16114 }
16115 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
16116 {
16117 oa->write_character(to_char_type(0x3A));
16118 write_number(static_cast<std::uint32_t>(positive_number));
16119 }
16120 else
16121 {
16122 oa->write_character(to_char_type(0x3B));
16123 write_number(static_cast<std::uint64_t>(positive_number));
16124 }
16125 }
16126 break;
16127 }
16128
16129 case value_t::number_unsigned:
16130 {
16131 if (j.m_data.m_value.number_unsigned <= 0x17)
16132 {
16133 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
16134 }
16135 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16136 {
16137 oa->write_character(to_char_type(0x18));
16138 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
16139 }
16140 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16141 {
16142 oa->write_character(to_char_type(0x19));
16143 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
16144 }
16145 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16146 {
16147 oa->write_character(to_char_type(0x1A));
16148 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
16149 }
16150 else
16151 {
16152 oa->write_character(to_char_type(0x1B));
16153 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
16154 }
16155 break;
16156 }
16157
16158 case value_t::number_float:
16159 {
16160 if (std::isnan(j.m_data.m_value.number_float))
16161 {
16162 // NaN is 0xf97e00 in CBOR
16163 oa->write_character(to_char_type(0xF9));
16164 oa->write_character(to_char_type(0x7E));
16165 oa->write_character(to_char_type(0x00));
16166 }
16167 else if (std::isinf(j.m_data.m_value.number_float))
16168 {
16169 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
16170 oa->write_character(to_char_type(0xf9));
16171 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
16172 oa->write_character(to_char_type(0x00));
16173 }
16174 else
16175 {
16176 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
16177 }
16178 break;
16179 }
16180
16181 case value_t::string:
16182 {
16183 // step 1: write control byte and the string length
16184 const auto N = j.m_data.m_value.string->size();
16185 if (N <= 0x17)
16186 {
16187 write_number(static_cast<std::uint8_t>(0x60 + N));
16188 }
16189 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16190 {
16191 oa->write_character(to_char_type(0x78));
16192 write_number(static_cast<std::uint8_t>(N));
16193 }
16194 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16195 {
16196 oa->write_character(to_char_type(0x79));
16197 write_number(static_cast<std::uint16_t>(N));
16198 }
16199 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16200 {
16201 oa->write_character(to_char_type(0x7A));
16202 write_number(static_cast<std::uint32_t>(N));
16203 }
16204 // LCOV_EXCL_START
16205 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16206 {
16207 oa->write_character(to_char_type(0x7B));
16208 write_number(static_cast<std::uint64_t>(N));
16209 }
16210 // LCOV_EXCL_STOP
16211
16212 // step 2: write the string
16213 oa->write_characters(
16214 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16215 j.m_data.m_value.string->size());
16216 break;
16217 }
16218
16219 case value_t::array:
16220 {
16221 // step 1: write control byte and the array size
16222 const auto N = j.m_data.m_value.array->size();
16223 if (N <= 0x17)
16224 {
16225 write_number(static_cast<std::uint8_t>(0x80 + N));
16226 }
16227 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16228 {
16229 oa->write_character(to_char_type(0x98));
16230 write_number(static_cast<std::uint8_t>(N));
16231 }
16232 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16233 {
16234 oa->write_character(to_char_type(0x99));
16235 write_number(static_cast<std::uint16_t>(N));
16236 }
16237 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16238 {
16239 oa->write_character(to_char_type(0x9A));
16240 write_number(static_cast<std::uint32_t>(N));
16241 }
16242 // LCOV_EXCL_START
16243 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16244 {
16245 oa->write_character(to_char_type(0x9B));
16246 write_number(static_cast<std::uint64_t>(N));
16247 }
16248 // LCOV_EXCL_STOP
16249
16250 // step 2: write each element
16251 for (const auto& el : *j.m_data.m_value.array)
16252 {
16253 write_cbor(el);
16254 }
16255 break;
16256 }
16257
16258 case value_t::binary:
16259 {
16260 if (j.m_data.m_value.binary->has_subtype())
16261 {
16262 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
16263 {
16264 write_number(static_cast<std::uint8_t>(0xd8));
16265 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
16266 }
16267 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
16268 {
16269 write_number(static_cast<std::uint8_t>(0xd9));
16270 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
16271 }
16272 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
16273 {
16274 write_number(static_cast<std::uint8_t>(0xda));
16275 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
16276 }
16277 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
16278 {
16279 write_number(static_cast<std::uint8_t>(0xdb));
16280 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
16281 }
16282 }
16283
16284 // step 1: write control byte and the binary array size
16285 const auto N = j.m_data.m_value.binary->size();
16286 if (N <= 0x17)
16287 {
16288 write_number(static_cast<std::uint8_t>(0x40 + N));
16289 }
16290 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16291 {
16292 oa->write_character(to_char_type(0x58));
16293 write_number(static_cast<std::uint8_t>(N));
16294 }
16295 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16296 {
16297 oa->write_character(to_char_type(0x59));
16298 write_number(static_cast<std::uint16_t>(N));
16299 }
16300 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16301 {
16302 oa->write_character(to_char_type(0x5A));
16303 write_number(static_cast<std::uint32_t>(N));
16304 }
16305 // LCOV_EXCL_START
16306 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16307 {
16308 oa->write_character(to_char_type(0x5B));
16309 write_number(static_cast<std::uint64_t>(N));
16310 }
16311 // LCOV_EXCL_STOP
16312
16313 // step 2: write each element
16314 oa->write_characters(
16315 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16316 N);
16317
16318 break;
16319 }
16320
16321 case value_t::object:
16322 {
16323 // step 1: write control byte and the object size
16324 const auto N = j.m_data.m_value.object->size();
16325 if (N <= 0x17)
16326 {
16327 write_number(static_cast<std::uint8_t>(0xA0 + N));
16328 }
16329 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16330 {
16331 oa->write_character(to_char_type(0xB8));
16332 write_number(static_cast<std::uint8_t>(N));
16333 }
16334 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16335 {
16336 oa->write_character(to_char_type(0xB9));
16337 write_number(static_cast<std::uint16_t>(N));
16338 }
16339 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16340 {
16341 oa->write_character(to_char_type(0xBA));
16342 write_number(static_cast<std::uint32_t>(N));
16343 }
16344 // LCOV_EXCL_START
16345 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16346 {
16347 oa->write_character(to_char_type(0xBB));
16348 write_number(static_cast<std::uint64_t>(N));
16349 }
16350 // LCOV_EXCL_STOP
16351
16352 // step 2: write each element
16353 for (const auto& el : *j.m_data.m_value.object)
16354 {
16355 write_cbor(el.first);
16356 write_cbor(el.second);
16357 }
16358 break;
16359 }
16360
16361 case value_t::discarded:
16362 default:
16363 break;
16364 }
16365 }
16366
16370 void write_msgpack(const BasicJsonType& j)
16371 {
16372 switch (j.type())
16373 {
16374 case value_t::null: // nil
16375 {
16376 oa->write_character(to_char_type(0xC0));
16377 break;
16378 }
16379
16380 case value_t::boolean: // true and false
16381 {
16382 oa->write_character(j.m_data.m_value.boolean
16383 ? to_char_type(0xC3)
16384 : to_char_type(0xC2));
16385 break;
16386 }
16387
16388 case value_t::number_integer:
16389 {
16390 if (j.m_data.m_value.number_integer >= 0)
16391 {
16392 // MessagePack does not differentiate between positive
16393 // signed integers and unsigned integers. Therefore, we used
16394 // the code from the value_t::number_unsigned case here.
16395 if (j.m_data.m_value.number_unsigned < 128)
16396 {
16397 // positive fixnum
16398 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16399 }
16400 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16401 {
16402 // uint 8
16403 oa->write_character(to_char_type(0xCC));
16404 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16405 }
16406 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16407 {
16408 // uint 16
16409 oa->write_character(to_char_type(0xCD));
16410 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16411 }
16412 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16413 {
16414 // uint 32
16415 oa->write_character(to_char_type(0xCE));
16416 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16417 }
16418 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16419 {
16420 // uint 64
16421 oa->write_character(to_char_type(0xCF));
16422 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16423 }
16424 }
16425 else
16426 {
16427 if (j.m_data.m_value.number_integer >= -32)
16428 {
16429 // negative fixnum
16430 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16431 }
16432 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
16433 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16434 {
16435 // int 8
16436 oa->write_character(to_char_type(0xD0));
16437 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16438 }
16439 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
16440 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16441 {
16442 // int 16
16443 oa->write_character(to_char_type(0xD1));
16444 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
16445 }
16446 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
16447 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16448 {
16449 // int 32
16450 oa->write_character(to_char_type(0xD2));
16451 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
16452 }
16453 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
16454 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16455 {
16456 // int 64
16457 oa->write_character(to_char_type(0xD3));
16458 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
16459 }
16460 }
16461 break;
16462 }
16463
16464 case value_t::number_unsigned:
16465 {
16466 if (j.m_data.m_value.number_unsigned < 128)
16467 {
16468 // positive fixnum
16469 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16470 }
16471 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16472 {
16473 // uint 8
16474 oa->write_character(to_char_type(0xCC));
16475 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16476 }
16477 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16478 {
16479 // uint 16
16480 oa->write_character(to_char_type(0xCD));
16481 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16482 }
16483 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16484 {
16485 // uint 32
16486 oa->write_character(to_char_type(0xCE));
16487 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16488 }
16489 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16490 {
16491 // uint 64
16492 oa->write_character(to_char_type(0xCF));
16493 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16494 }
16495 break;
16496 }
16497
16498 case value_t::number_float:
16499 {
16500 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
16501 break;
16502 }
16503
16504 case value_t::string:
16505 {
16506 // step 1: write control byte and the string length
16507 const auto N = j.m_data.m_value.string->size();
16508 if (N <= 31)
16509 {
16510 // fixstr
16511 write_number(static_cast<std::uint8_t>(0xA0 | N));
16512 }
16513 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16514 {
16515 // str 8
16516 oa->write_character(to_char_type(0xD9));
16517 write_number(static_cast<std::uint8_t>(N));
16518 }
16519 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16520 {
16521 // str 16
16522 oa->write_character(to_char_type(0xDA));
16523 write_number(static_cast<std::uint16_t>(N));
16524 }
16525 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16526 {
16527 // str 32
16528 oa->write_character(to_char_type(0xDB));
16529 write_number(static_cast<std::uint32_t>(N));
16530 }
16531
16532 // step 2: write the string
16533 oa->write_characters(
16534 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16535 j.m_data.m_value.string->size());
16536 break;
16537 }
16538
16539 case value_t::array:
16540 {
16541 // step 1: write control byte and the array size
16542 const auto N = j.m_data.m_value.array->size();
16543 if (N <= 15)
16544 {
16545 // fixarray
16546 write_number(static_cast<std::uint8_t>(0x90 | N));
16547 }
16548 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16549 {
16550 // array 16
16551 oa->write_character(to_char_type(0xDC));
16552 write_number(static_cast<std::uint16_t>(N));
16553 }
16554 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16555 {
16556 // array 32
16557 oa->write_character(to_char_type(0xDD));
16558 write_number(static_cast<std::uint32_t>(N));
16559 }
16560
16561 // step 2: write each element
16562 for (const auto& el : *j.m_data.m_value.array)
16563 {
16564 write_msgpack(el);
16565 }
16566 break;
16567 }
16568
16569 case value_t::binary:
16570 {
16571 // step 0: determine if the binary type has a set subtype to
16572 // determine whether to use the ext or fixext types
16573 const bool use_ext = j.m_data.m_value.binary->has_subtype();
16574
16575 // step 1: write control byte and the byte string length
16576 const auto N = j.m_data.m_value.binary->size();
16577 if (N <= (std::numeric_limits<std::uint8_t>::max)())
16578 {
16579 std::uint8_t output_type{};
16580 bool fixed = true;
16581 if (use_ext)
16582 {
16583 switch (N)
16584 {
16585 case 1:
16586 output_type = 0xD4; // fixext 1
16587 break;
16588 case 2:
16589 output_type = 0xD5; // fixext 2
16590 break;
16591 case 4:
16592 output_type = 0xD6; // fixext 4
16593 break;
16594 case 8:
16595 output_type = 0xD7; // fixext 8
16596 break;
16597 case 16:
16598 output_type = 0xD8; // fixext 16
16599 break;
16600 default:
16601 output_type = 0xC7; // ext 8
16602 fixed = false;
16603 break;
16604 }
16605
16606 }
16607 else
16608 {
16609 output_type = 0xC4; // bin 8
16610 fixed = false;
16611 }
16612
16613 oa->write_character(to_char_type(output_type));
16614 if (!fixed)
16615 {
16616 write_number(static_cast<std::uint8_t>(N));
16617 }
16618 }
16619 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16620 {
16621 const std::uint8_t output_type = use_ext
16622 ? 0xC8 // ext 16
16623 : 0xC5; // bin 16
16624
16625 oa->write_character(to_char_type(output_type));
16626 write_number(static_cast<std::uint16_t>(N));
16627 }
16628 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16629 {
16630 const std::uint8_t output_type = use_ext
16631 ? 0xC9 // ext 32
16632 : 0xC6; // bin 32
16633
16634 oa->write_character(to_char_type(output_type));
16635 write_number(static_cast<std::uint32_t>(N));
16636 }
16637
16638 // step 1.5: if this is an ext type, write the subtype
16639 if (use_ext)
16640 {
16641 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
16642 }
16643
16644 // step 2: write the byte string
16645 oa->write_characters(
16646 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16647 N);
16648
16649 break;
16650 }
16651
16652 case value_t::object:
16653 {
16654 // step 1: write control byte and the object size
16655 const auto N = j.m_data.m_value.object->size();
16656 if (N <= 15)
16657 {
16658 // fixmap
16659 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
16660 }
16661 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16662 {
16663 // map 16
16664 oa->write_character(to_char_type(0xDE));
16665 write_number(static_cast<std::uint16_t>(N));
16666 }
16667 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16668 {
16669 // map 32
16670 oa->write_character(to_char_type(0xDF));
16671 write_number(static_cast<std::uint32_t>(N));
16672 }
16673
16674 // step 2: write each element
16675 for (const auto& el : *j.m_data.m_value.object)
16676 {
16677 write_msgpack(el.first);
16678 write_msgpack(el.second);
16679 }
16680 break;
16681 }
16682
16683 case value_t::discarded:
16684 default:
16685 break;
16686 }
16687 }
16688
16697 void write_ubjson(const BasicJsonType& j, const bool use_count,
16698 const bool use_type, const bool add_prefix = true,
16699 const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2)
16700 {
16701 const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3;
16702
16703 switch (j.type())
16704 {
16705 case value_t::null:
16706 {
16707 if (add_prefix)
16708 {
16709 oa->write_character(to_char_type('Z'));
16710 }
16711 break;
16712 }
16713
16714 case value_t::boolean:
16715 {
16716 if (add_prefix)
16717 {
16718 oa->write_character(j.m_data.m_value.boolean
16719 ? to_char_type('T')
16720 : to_char_type('F'));
16721 }
16722 break;
16723 }
16724
16725 case value_t::number_integer:
16726 {
16727 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
16728 break;
16729 }
16730
16731 case value_t::number_unsigned:
16732 {
16733 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
16734 break;
16735 }
16736
16737 case value_t::number_float:
16738 {
16739 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
16740 break;
16741 }
16742
16743 case value_t::string:
16744 {
16745 if (add_prefix)
16746 {
16747 oa->write_character(to_char_type('S'));
16748 }
16749 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
16750 oa->write_characters(
16751 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16752 j.m_data.m_value.string->size());
16753 break;
16754 }
16755
16756 case value_t::array:
16757 {
16758 if (add_prefix)
16759 {
16760 oa->write_character(to_char_type('['));
16761 }
16762
16763 bool prefix_required = true;
16764 if (use_type && !j.m_data.m_value.array->empty())
16765 {
16766 JSON_ASSERT(use_count);
16767 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16768 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
16769 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16770 {
16771 return ubjson_prefix(v, use_bjdata) == first_prefix;
16772 });
16773
16774 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16775
16776 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16777 {
16778 prefix_required = false;
16779 oa->write_character(to_char_type('$'));
16780 oa->write_character(first_prefix);
16781 }
16782 }
16783
16784 if (use_count)
16785 {
16786 oa->write_character(to_char_type('#'));
16787 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
16788 }
16789
16790 for (const auto& el : *j.m_data.m_value.array)
16791 {
16792 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16793 }
16794
16795 if (!use_count)
16796 {
16797 oa->write_character(to_char_type(']'));
16798 }
16799
16800 break;
16801 }
16802
16803 case value_t::binary:
16804 {
16805 if (add_prefix)
16806 {
16807 oa->write_character(to_char_type('['));
16808 }
16809
16810 if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
16811 {
16812 JSON_ASSERT(use_count);
16813 oa->write_character(to_char_type('$'));
16814 oa->write_character(bjdata_draft3 ? 'B' : 'U');
16815 }
16816
16817 if (use_count)
16818 {
16819 oa->write_character(to_char_type('#'));
16820 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
16821 }
16822
16823 if (use_type)
16824 {
16825 oa->write_characters(
16826 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16827 j.m_data.m_value.binary->size());
16828 }
16829 else
16830 {
16831 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
16832 {
16833 oa->write_character(to_char_type(bjdata_draft3 ? 'B' : 'U'));
16834 oa->write_character(j.m_data.m_value.binary->data()[i]);
16835 }
16836 }
16837
16838 if (!use_count)
16839 {
16840 oa->write_character(to_char_type(']'));
16841 }
16842
16843 break;
16844 }
16845
16846 case value_t::object:
16847 {
16848 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())
16849 {
16850 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)
16851 {
16852 break;
16853 }
16854 }
16855
16856 if (add_prefix)
16857 {
16858 oa->write_character(to_char_type('{'));
16859 }
16860
16861 bool prefix_required = true;
16862 if (use_type && !j.m_data.m_value.object->empty())
16863 {
16864 JSON_ASSERT(use_count);
16865 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16866 const bool same_prefix = std::all_of(j.begin(), j.end(),
16867 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16868 {
16869 return ubjson_prefix(v, use_bjdata) == first_prefix;
16870 });
16871
16872 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16873
16874 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16875 {
16876 prefix_required = false;
16877 oa->write_character(to_char_type('$'));
16878 oa->write_character(first_prefix);
16879 }
16880 }
16881
16882 if (use_count)
16883 {
16884 oa->write_character(to_char_type('#'));
16885 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
16886 }
16887
16888 for (const auto& el : *j.m_data.m_value.object)
16889 {
16890 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
16891 oa->write_characters(
16892 reinterpret_cast<const CharType*>(el.first.c_str()),
16893 el.first.size());
16894 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16895 }
16896
16897 if (!use_count)
16898 {
16899 oa->write_character(to_char_type('}'));
16900 }
16901
16902 break;
16903 }
16904
16905 case value_t::discarded:
16906 default:
16907 break;
16908 }
16909 }
16910
16911 private:
16913 // BSON //
16915
16920 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16921 {
16922 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16923 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16924 {
16925 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16926 }
16927
16928 static_cast<void>(j);
16929 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16930 }
16931
16936 const std::uint8_t element_type)
16937 {
16938 oa->write_character(to_char_type(element_type)); // boolean
16939 oa->write_characters(
16940 reinterpret_cast<const CharType*>(name.c_str()),
16941 name.size() + 1u);
16942 }
16943
16948 const bool value)
16949 {
16950 write_bson_entry_header(name, 0x08);
16951 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16952 }
16953
16957 void write_bson_double(const string_t& name,
16958 const double value)
16959 {
16960 write_bson_entry_header(name, 0x01);
16961 write_number<double>(value, true);
16962 }
16963
16967 static std::size_t calc_bson_string_size(const string_t& value)
16968 {
16969 return sizeof(std::int32_t) + value.size() + 1ul;
16970 }
16971
16975 void write_bson_string(const string_t& name,
16976 const string_t& value)
16977 {
16978 write_bson_entry_header(name, 0x02);
16979
16980 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16981 oa->write_characters(
16982 reinterpret_cast<const CharType*>(value.c_str()),
16983 value.size() + 1);
16984 }
16985
16989 void write_bson_null(const string_t& name)
16990 {
16991 write_bson_entry_header(name, 0x0A);
16992 }
16993
16997 static std::size_t calc_bson_integer_size(const std::int64_t value)
16998 {
16999 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
17000 ? sizeof(std::int32_t)
17001 : sizeof(std::int64_t);
17002 }
17003
17008 const std::int64_t value)
17009 {
17010 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
17011 {
17012 write_bson_entry_header(name, 0x10); // int32
17013 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
17014 }
17015 else
17016 {
17017 write_bson_entry_header(name, 0x12); // int64
17018 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
17019 }
17020 }
17021
17025 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
17026 {
17027 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17028 ? sizeof(std::int32_t)
17029 : sizeof(std::int64_t);
17030 }
17031
17036 const BasicJsonType& j)
17037 {
17038 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17039 {
17040 write_bson_entry_header(name, 0x10 /* int32 */);
17041 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
17042 }
17043 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17044 {
17045 write_bson_entry_header(name, 0x12 /* int64 */);
17046 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
17047 }
17048 else
17049 {
17050 write_bson_entry_header(name, 0x11 /* uint64 */);
17051 write_number<std::uint64_t>(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned), true);
17052 }
17053 }
17054
17059 const typename BasicJsonType::object_t& value)
17060 {
17061 write_bson_entry_header(name, 0x03); // object
17062 write_bson_object(value);
17063 }
17064
17068 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
17069 {
17070 std::size_t array_index = 0ul;
17071
17072 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)
17073 {
17074 return result + calc_bson_element_size(std::to_string(array_index++), el);
17075 });
17076
17077 return sizeof(std::int32_t) + embedded_document_size + 1ul;
17078 }
17079
17083 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
17084 {
17085 return sizeof(std::int32_t) + value.size() + 1ul;
17086 }
17087
17091 void write_bson_array(const string_t& name,
17092 const typename BasicJsonType::array_t& value)
17093 {
17094 write_bson_entry_header(name, 0x04); // array
17095 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
17096
17097 std::size_t array_index = 0ul;
17098
17099 for (const auto& el : value)
17100 {
17101 write_bson_element(std::to_string(array_index++), el);
17102 }
17103
17104 oa->write_character(to_char_type(0x00));
17105 }
17106
17110 void write_bson_binary(const string_t& name,
17111 const binary_t& value)
17112 {
17113 write_bson_entry_header(name, 0x05);
17114
17115 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
17116 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
17117
17118 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
17119 }
17120
17125 static std::size_t calc_bson_element_size(const string_t& name,
17126 const BasicJsonType& j)
17127 {
17128 const auto header_size = calc_bson_entry_header_size(name, j);
17129 switch (j.type())
17130 {
17131 case value_t::object:
17132 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
17133
17134 case value_t::array:
17135 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
17136
17137 case value_t::binary:
17138 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
17139
17140 case value_t::boolean:
17141 return header_size + 1ul;
17142
17143 case value_t::number_float:
17144 return header_size + 8ul;
17145
17146 case value_t::number_integer:
17147 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
17148
17149 case value_t::number_unsigned:
17150 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
17151
17152 case value_t::string:
17153 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
17154
17155 case value_t::null:
17156 return header_size + 0ul;
17157
17158 // LCOV_EXCL_START
17159 case value_t::discarded:
17160 default:
17161 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17162 return 0ul;
17163 // LCOV_EXCL_STOP
17164 }
17165 }
17166
17174 const BasicJsonType& j)
17175 {
17176 switch (j.type())
17177 {
17178 case value_t::object:
17179 return write_bson_object_entry(name, *j.m_data.m_value.object);
17180
17181 case value_t::array:
17182 return write_bson_array(name, *j.m_data.m_value.array);
17183
17184 case value_t::binary:
17185 return write_bson_binary(name, *j.m_data.m_value.binary);
17186
17187 case value_t::boolean:
17188 return write_bson_boolean(name, j.m_data.m_value.boolean);
17189
17190 case value_t::number_float:
17191 return write_bson_double(name, j.m_data.m_value.number_float);
17192
17193 case value_t::number_integer:
17194 return write_bson_integer(name, j.m_data.m_value.number_integer);
17195
17196 case value_t::number_unsigned:
17197 return write_bson_unsigned(name, j);
17198
17199 case value_t::string:
17200 return write_bson_string(name, *j.m_data.m_value.string);
17201
17202 case value_t::null:
17203 return write_bson_null(name);
17204
17205 // LCOV_EXCL_START
17206 case value_t::discarded:
17207 default:
17208 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17209 return;
17210 // LCOV_EXCL_STOP
17211 }
17212 }
17213
17220 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
17221 {
17222 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
17223 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
17224 {
17225 return result += calc_bson_element_size(el.first, el.second);
17226 });
17227
17228 return sizeof(std::int32_t) + document_size + 1ul;
17229 }
17230
17235 void write_bson_object(const typename BasicJsonType::object_t& value)
17236 {
17237 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
17238
17239 for (const auto& el : value)
17240 {
17241 write_bson_element(el.first, el.second);
17242 }
17243
17244 oa->write_character(to_char_type(0x00));
17245 }
17246
17248 // CBOR //
17250
17251 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
17252 {
17253 return to_char_type(0xFA); // Single-Precision Float
17254 }
17255
17256 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
17257 {
17258 return to_char_type(0xFB); // Double-Precision Float
17259 }
17260
17262 // MsgPack //
17264
17265 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
17266 {
17267 return to_char_type(0xCA); // float 32
17268 }
17269
17270 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
17271 {
17272 return to_char_type(0xCB); // float 64
17273 }
17274
17276 // UBJSON //
17278
17279 // UBJSON: write number (floating point)
17280 template<typename NumberType, typename std::enable_if<
17281 std::is_floating_point<NumberType>::value, int>::type = 0>
17282 void write_number_with_ubjson_prefix(const NumberType n,
17283 const bool add_prefix,
17284 const bool use_bjdata)
17285 {
17286 if (add_prefix)
17287 {
17288 oa->write_character(get_ubjson_float_prefix(n));
17289 }
17290 write_number(n, use_bjdata);
17291 }
17292
17293 // UBJSON: write number (unsigned integer)
17294 template<typename NumberType, typename std::enable_if<
17295 std::is_unsigned<NumberType>::value, int>::type = 0>
17296 void write_number_with_ubjson_prefix(const NumberType n,
17297 const bool add_prefix,
17298 const bool use_bjdata)
17299 {
17300 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17301 {
17302 if (add_prefix)
17303 {
17304 oa->write_character(to_char_type('i')); // int8
17305 }
17306 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17307 }
17308 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
17309 {
17310 if (add_prefix)
17311 {
17312 oa->write_character(to_char_type('U')); // uint8
17313 }
17314 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17315 }
17316 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17317 {
17318 if (add_prefix)
17319 {
17320 oa->write_character(to_char_type('I')); // int16
17321 }
17322 write_number(static_cast<std::int16_t>(n), use_bjdata);
17323 }
17324 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
17325 {
17326 if (add_prefix)
17327 {
17328 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17329 }
17330 write_number(static_cast<std::uint16_t>(n), use_bjdata);
17331 }
17332 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17333 {
17334 if (add_prefix)
17335 {
17336 oa->write_character(to_char_type('l')); // int32
17337 }
17338 write_number(static_cast<std::int32_t>(n), use_bjdata);
17339 }
17340 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
17341 {
17342 if (add_prefix)
17343 {
17344 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17345 }
17346 write_number(static_cast<std::uint32_t>(n), use_bjdata);
17347 }
17348 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17349 {
17350 if (add_prefix)
17351 {
17352 oa->write_character(to_char_type('L')); // int64
17353 }
17354 write_number(static_cast<std::int64_t>(n), use_bjdata);
17355 }
17356 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
17357 {
17358 if (add_prefix)
17359 {
17360 oa->write_character(to_char_type('M')); // uint64 - bjdata only
17361 }
17362 write_number(static_cast<std::uint64_t>(n), use_bjdata);
17363 }
17364 else
17365 {
17366 if (add_prefix)
17367 {
17368 oa->write_character(to_char_type('H')); // high-precision number
17369 }
17370
17371 const auto number = BasicJsonType(n).dump();
17372 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17373 for (std::size_t i = 0; i < number.size(); ++i)
17374 {
17375 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17376 }
17377 }
17378 }
17379
17380 // UBJSON: write number (signed integer)
17381 template < typename NumberType, typename std::enable_if <
17382 std::is_signed<NumberType>::value&&
17383 !std::is_floating_point<NumberType>::value, int >::type = 0 >
17384 void write_number_with_ubjson_prefix(const NumberType n,
17385 const bool add_prefix,
17386 const bool use_bjdata)
17387 {
17388 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
17389 {
17390 if (add_prefix)
17391 {
17392 oa->write_character(to_char_type('i')); // int8
17393 }
17394 write_number(static_cast<std::int8_t>(n), use_bjdata);
17395 }
17396 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)()))
17397 {
17398 if (add_prefix)
17399 {
17400 oa->write_character(to_char_type('U')); // uint8
17401 }
17402 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17403 }
17404 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
17405 {
17406 if (add_prefix)
17407 {
17408 oa->write_character(to_char_type('I')); // int16
17409 }
17410 write_number(static_cast<std::int16_t>(n), use_bjdata);
17411 }
17412 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)())))
17413 {
17414 if (add_prefix)
17415 {
17416 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17417 }
17418 write_number(static_cast<uint16_t>(n), use_bjdata);
17419 }
17420 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
17421 {
17422 if (add_prefix)
17423 {
17424 oa->write_character(to_char_type('l')); // int32
17425 }
17426 write_number(static_cast<std::int32_t>(n), use_bjdata);
17427 }
17428 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)())))
17429 {
17430 if (add_prefix)
17431 {
17432 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17433 }
17434 write_number(static_cast<uint32_t>(n), use_bjdata);
17435 }
17436 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
17437 {
17438 if (add_prefix)
17439 {
17440 oa->write_character(to_char_type('L')); // int64
17441 }
17442 write_number(static_cast<std::int64_t>(n), use_bjdata);
17443 }
17444 // LCOV_EXCL_START
17445 else
17446 {
17447 if (add_prefix)
17448 {
17449 oa->write_character(to_char_type('H')); // high-precision number
17450 }
17451
17452 const auto number = BasicJsonType(n).dump();
17453 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17454 for (std::size_t i = 0; i < number.size(); ++i)
17455 {
17456 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17457 }
17458 }
17459 // LCOV_EXCL_STOP
17460 }
17461
17465 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
17466 {
17467 switch (j.type())
17468 {
17469 case value_t::null:
17470 return 'Z';
17471
17472 case value_t::boolean:
17473 return j.m_data.m_value.boolean ? 'T' : 'F';
17474
17475 case value_t::number_integer:
17476 {
17477 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)())
17478 {
17479 return 'i';
17480 }
17481 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)())
17482 {
17483 return 'U';
17484 }
17485 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)())
17486 {
17487 return 'I';
17488 }
17489 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)()))
17490 {
17491 return 'u';
17492 }
17493 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)())
17494 {
17495 return 'l';
17496 }
17497 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)()))
17498 {
17499 return 'm';
17500 }
17501 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)())
17502 {
17503 return 'L';
17504 }
17505 // anything else is treated as a high-precision number
17506 return 'H'; // LCOV_EXCL_LINE
17507 }
17508
17509 case value_t::number_unsigned:
17510 {
17511 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17512 {
17513 return 'i';
17514 }
17515 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
17516 {
17517 return 'U';
17518 }
17519 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17520 {
17521 return 'I';
17522 }
17523 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
17524 {
17525 return 'u';
17526 }
17527 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17528 {
17529 return 'l';
17530 }
17531 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
17532 {
17533 return 'm';
17534 }
17535 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17536 {
17537 return 'L';
17538 }
17539 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
17540 {
17541 return 'M';
17542 }
17543 // anything else is treated as a high-precision number
17544 return 'H'; // LCOV_EXCL_LINE
17545 }
17546
17547 case value_t::number_float:
17548 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
17549
17550 case value_t::string:
17551 return 'S';
17552
17553 case value_t::array: // fallthrough
17554 case value_t::binary:
17555 return '[';
17556
17557 case value_t::object:
17558 return '{';
17559
17560 case value_t::discarded:
17561 default: // discarded values
17562 return 'N';
17563 }
17564 }
17565
17566 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
17567 {
17568 return 'd'; // float 32
17569 }
17570
17571 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
17572 {
17573 return 'D'; // float 64
17574 }
17575
17579 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
17580 {
17581 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
17582 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'},
17583 {"char", 'C'}, {"byte", 'B'}
17584 };
17585
17586 string_t key = "_ArrayType_";
17587 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
17588 if (it == bjdtype.end())
17589 {
17590 return true;
17591 }
17592 CharType dtype = it->second;
17593
17594 key = "_ArraySize_";
17595 std::size_t len = (value.at(key).empty() ? 0 : 1);
17596 for (const auto& el : value.at(key))
17597 {
17598 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
17599 }
17600
17601 key = "_ArrayData_";
17602 if (value.at(key).size() != len)
17603 {
17604 return true;
17605 }
17606
17607 oa->write_character('[');
17608 oa->write_character('$');
17609 oa->write_character(dtype);
17610 oa->write_character('#');
17611
17612 key = "_ArraySize_";
17613 write_ubjson(value.at(key), use_count, use_type, true, true, bjdata_version);
17614
17615 key = "_ArrayData_";
17616 if (dtype == 'U' || dtype == 'C' || dtype == 'B')
17617 {
17618 for (const auto& el : value.at(key))
17619 {
17620 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
17621 }
17622 }
17623 else if (dtype == 'i')
17624 {
17625 for (const auto& el : value.at(key))
17626 {
17627 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
17628 }
17629 }
17630 else if (dtype == 'u')
17631 {
17632 for (const auto& el : value.at(key))
17633 {
17634 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
17635 }
17636 }
17637 else if (dtype == 'I')
17638 {
17639 for (const auto& el : value.at(key))
17640 {
17641 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
17642 }
17643 }
17644 else if (dtype == 'm')
17645 {
17646 for (const auto& el : value.at(key))
17647 {
17648 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
17649 }
17650 }
17651 else if (dtype == 'l')
17652 {
17653 for (const auto& el : value.at(key))
17654 {
17655 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
17656 }
17657 }
17658 else if (dtype == 'M')
17659 {
17660 for (const auto& el : value.at(key))
17661 {
17662 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
17663 }
17664 }
17665 else if (dtype == 'L')
17666 {
17667 for (const auto& el : value.at(key))
17668 {
17669 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
17670 }
17671 }
17672 else if (dtype == 'd')
17673 {
17674 for (const auto& el : value.at(key))
17675 {
17676 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
17677 }
17678 }
17679 else if (dtype == 'D')
17680 {
17681 for (const auto& el : value.at(key))
17682 {
17683 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
17684 }
17685 }
17686 return false;
17687 }
17688
17690 // Utility functions //
17692
17693 /*
17694 @brief write a number to output input
17695 @param[in] n number of type @a NumberType
17696 @param[in] OutputIsLittleEndian Set to true if output data is
17697 required to be little endian
17698 @tparam NumberType the type of the number
17699
17700 @note This function needs to respect the system's endianness, because bytes
17701 in CBOR, MessagePack, and UBJSON are stored in network order (big
17702 endian) and therefore need reordering on little endian systems.
17703 On the other hand, BSON and BJData use little endian and should reorder
17704 on big endian systems.
17705 */
17706 template<typename NumberType>
17707 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
17708 {
17709 // step 1: write the number to an array of length NumberType
17710 std::array<CharType, sizeof(NumberType)> vec{};
17711 std::memcpy(vec.data(), &n, sizeof(NumberType));
17712
17713 // step 2: write the array to output (with possible reordering)
17714 if (is_little_endian != OutputIsLittleEndian)
17715 {
17716 // reverse byte order prior to conversion if necessary
17717 std::reverse(vec.begin(), vec.end());
17718 }
17719
17720 oa->write_characters(vec.data(), sizeof(NumberType));
17721 }
17722
17724 {
17725#ifdef __GNUC__
17726#pragma GCC diagnostic push
17727#pragma GCC diagnostic ignored "-Wfloat-equal"
17728#endif
17729 if (!std::isfinite(n) || ((static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
17730 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
17731 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))))
17732 {
17733 oa->write_character(format == detail::input_format_t::cbor
17734 ? get_cbor_float_prefix(static_cast<float>(n))
17735 : get_msgpack_float_prefix(static_cast<float>(n)));
17736 write_number(static_cast<float>(n));
17737 }
17738 else
17739 {
17740 oa->write_character(format == detail::input_format_t::cbor
17741 ? get_cbor_float_prefix(n)
17742 : get_msgpack_float_prefix(n));
17743 write_number(n);
17744 }
17745#ifdef __GNUC__
17746#pragma GCC diagnostic pop
17747#endif
17748 }
17749
17750 public:
17751 // The following to_char_type functions are implement the conversion
17752 // between uint8_t and CharType. In case CharType is not unsigned,
17753 // such a conversion is required to allow values greater than 128.
17754 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
17755 template < typename C = CharType,
17756 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
17757 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17758 {
17759 return *reinterpret_cast<char*>(&x);
17760 }
17761
17762 template < typename C = CharType,
17763 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
17764 static CharType to_char_type(std::uint8_t x) noexcept
17765 {
17766 // The std::is_trivial trait is deprecated in C++26. The replacement is to use
17767 // std::is_trivially_copyable and std::is_trivially_default_constructible.
17768 // However, some older library implementations support std::is_trivial
17769 // but not all the std::is_trivially_* traits.
17770 // Since detecting full support across all libraries is difficult,
17771 // we use std::is_trivial unless we are using a standard where it has been deprecated.
17772 // For more details, see: https://github.com/nlohmann/json/pull/4775#issuecomment-2884361627
17773#ifdef JSON_HAS_CPP_26
17774 static_assert(std::is_trivially_copyable<CharType>::value, "CharType must be trivially copyable");
17775 static_assert(std::is_trivially_default_constructible<CharType>::value, "CharType must be trivially default constructible");
17776#else
17777 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
17778#endif
17779
17780 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
17781 CharType result;
17782 std::memcpy(&result, &x, sizeof(x));
17783 return result;
17784 }
17785
17786 template<typename C = CharType,
17788 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17789 {
17790 return x;
17791 }
17792
17793 template < typename InputCharType, typename C = CharType,
17794 enable_if_t <
17795 std::is_signed<C>::value &&
17796 std::is_signed<char>::value &&
17797 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
17798 > * = nullptr >
17799 static constexpr CharType to_char_type(InputCharType x) noexcept
17800 {
17801 return x;
17802 }
17803
17804 private:
17806 const bool is_little_endian = little_endianness();
17807
17810};
17811
17812} // namespace detail
17814
17815// #include <nlohmann/detail/output/output_adapters.hpp>
17816
17817// #include <nlohmann/detail/output/serializer.hpp>
17818// __ _____ _____ _____
17819// __| | __| | | | JSON for Modern C++
17820// | | |__ | | | | | | version 3.12.0
17821// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17822//
17823// SPDX-FileCopyrightText: 2008, 2009 Björn Hoehrmann <bjoern@hoehrmann.de>
17824// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
17825// SPDX-License-Identifier: MIT
17826
17827
17828
17829#include <algorithm> // reverse, remove, fill, find, none_of
17830#include <array> // array
17831#include <clocale> // localeconv, lconv
17832#include <cmath> // labs, isfinite, isnan, signbit
17833#include <cstddef> // size_t, ptrdiff_t
17834#include <cstdint> // uint8_t
17835#include <cstdio> // snprintf
17836#include <limits> // numeric_limits
17837#include <string> // string, char_traits
17838#include <iomanip> // setfill, setw
17839#include <type_traits> // is_same
17840#include <utility> // move
17841
17842// #include <nlohmann/detail/conversions/to_chars.hpp>
17843// __ _____ _____ _____
17844// __| | __| | | | JSON for Modern C++
17845// | | |__ | | | | | | version 3.12.0
17846// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17847//
17848// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
17849// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
17850// SPDX-License-Identifier: MIT
17851
17852
17853
17854#include <array> // array
17855#include <cmath> // signbit, isfinite
17856#include <cstdint> // intN_t, uintN_t
17857#include <cstring> // memcpy, memmove
17858#include <limits> // numeric_limits
17859#include <type_traits> // conditional
17860
17861// #include <nlohmann/detail/macro_scope.hpp>
17862
17863
17865namespace detail
17866{
17867
17887namespace dtoa_impl
17888{
17889
17890template<typename Target, typename Source>
17891Target reinterpret_bits(const Source source)
17892{
17893 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
17894
17895 Target target;
17896 std::memcpy(&target, &source, sizeof(Source));
17897 return target;
17898}
17899
17900struct diyfp // f * 2^e
17901{
17902 static constexpr int kPrecision = 64; // = q
17903
17904 std::uint64_t f = 0;
17905 int e = 0;
17906
17907 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
17908
17913 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
17914 {
17915 JSON_ASSERT(x.e == y.e);
17916 JSON_ASSERT(x.f >= y.f);
17917
17918 return {x.f - y.f, x.e};
17919 }
17920
17925 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17926 {
17927 static_assert(kPrecision == 64, "internal error");
17928
17929 // Computes:
17930 // f = round((x.f * y.f) / 2^q)
17931 // e = x.e + y.e + q
17932
17933 // Emulate the 64-bit * 64-bit multiplication:
17934 //
17935 // p = u * v
17936 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17937 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17938 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17939 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17940 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17941 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17942 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17943 //
17944 // (Since Q might be larger than 2^32 - 1)
17945 //
17946 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17947 //
17948 // (Q_hi + H does not overflow a 64-bit int)
17949 //
17950 // = p_lo + 2^64 p_hi
17951
17952 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17953 const std::uint64_t u_hi = x.f >> 32u;
17954 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17955 const std::uint64_t v_hi = y.f >> 32u;
17956
17957 const std::uint64_t p0 = u_lo * v_lo;
17958 const std::uint64_t p1 = u_lo * v_hi;
17959 const std::uint64_t p2 = u_hi * v_lo;
17960 const std::uint64_t p3 = u_hi * v_hi;
17961
17962 const std::uint64_t p0_hi = p0 >> 32u;
17963 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17964 const std::uint64_t p1_hi = p1 >> 32u;
17965 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17966 const std::uint64_t p2_hi = p2 >> 32u;
17967
17968 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17969
17970 // The full product might now be computed as
17971 //
17972 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17973 // p_lo = p0_lo + (Q << 32)
17974 //
17975 // But in this particular case here, the full p_lo is not required.
17976 // Effectively, we only need to add the highest bit in p_lo to p_hi (and
17977 // Q_hi + 1 does not overflow).
17978
17979 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17980
17981 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17982
17983 return {h, x.e + y.e + 64};
17984 }
17985
17990 static diyfp normalize(diyfp x) noexcept
17991 {
17992 JSON_ASSERT(x.f != 0);
17993
17994 while ((x.f >> 63u) == 0)
17995 {
17996 x.f <<= 1u;
17997 x.e--;
17998 }
17999
18000 return x;
18001 }
18002
18007 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
18008 {
18009 const int delta = x.e - target_exponent;
18010
18011 JSON_ASSERT(delta >= 0);
18012 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
18013
18014 return {x.f << delta, target_exponent};
18015 }
18016};
18017
18024
18031template<typename FloatType>
18033{
18034 JSON_ASSERT(std::isfinite(value));
18035 JSON_ASSERT(value > 0);
18036
18037 // Convert the IEEE representation into a diyfp.
18038 //
18039 // If v is denormal:
18040 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
18041 // If v is normalized:
18042 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
18043
18044 static_assert(std::numeric_limits<FloatType>::is_iec559,
18045 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
18046
18047 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
18048 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
18049 constexpr int kMinExp = 1 - kBias;
18050 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
18051
18052 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
18053
18054 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
18055 const std::uint64_t E = bits >> (kPrecision - 1);
18056 const std::uint64_t F = bits & (kHiddenBit - 1);
18057
18058 const bool is_denormal = E == 0;
18059 const diyfp v = is_denormal
18060 ? diyfp(F, kMinExp)
18061 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
18062
18063 // Compute the boundaries m- and m+ of the floating-point value
18064 // v = f * 2^e.
18065 //
18066 // Determine v- and v+, the floating-point predecessor and successor of v,
18067 // respectively.
18068 //
18069 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
18070 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
18071 //
18072 // v+ = v + 2^e
18073 //
18074 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
18075 // between m- and m+ round to v, regardless of how the input rounding
18076 // algorithm breaks ties.
18077 //
18078 // ---+-------------+-------------+-------------+-------------+--- (A)
18079 // v- m- v m+ v+
18080 //
18081 // -----------------+------+------+-------------+-------------+--- (B)
18082 // v- m- v m+ v+
18083
18084 const bool lower_boundary_is_closer = F == 0 && E > 1;
18085 const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
18086 const diyfp m_minus = lower_boundary_is_closer
18087 ? diyfp((4 * v.f) - 1, v.e - 2) // (B)
18088 : diyfp((2 * v.f) - 1, v.e - 1); // (A)
18089
18090 // Determine the normalized w+ = m+.
18091 const diyfp w_plus = diyfp::normalize(m_plus);
18092
18093 // Determine w- = m- such that e_(w-) = e_(w+).
18094 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
18095
18096 return {diyfp::normalize(v), w_minus, w_plus};
18097}
18098
18099// Given normalized diyfp w, Grisu needs to find a (normalized) cached
18100// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
18101// within a certain range [alpha, gamma] (Definition 3.2 from [1])
18102//
18103// alpha <= e = e_c + e_w + q <= gamma
18104//
18105// or
18106//
18107// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
18108// <= f_c * f_w * 2^gamma
18109//
18110// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
18111//
18112// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
18113//
18114// or
18115//
18116// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
18117//
18118// The choice of (alpha,gamma) determines the size of the table and the form of
18119// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
18120// in practice:
18121//
18122// The idea is to cut the number c * w = f * 2^e into two parts, which can be
18123// processed independently: An integral part p1, and a fractional part p2:
18124//
18125// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
18126// = (f div 2^-e) + (f mod 2^-e) * 2^e
18127// = p1 + p2 * 2^e
18128//
18129// The conversion of p1 into decimal form requires a series of divisions and
18130// modulos by (a power of) 10. These operations are faster for 32-bit than for
18131// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
18132// achieved by choosing
18133//
18134// -e >= 32 or e <= -32 := gamma
18135//
18136// In order to convert the fractional part
18137//
18138// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
18139//
18140// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
18141// d[-i] are extracted in order:
18142//
18143// (10 * p2) div 2^-e = d[-1]
18144// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
18145//
18146// The multiplication by 10 must not overflow. It is sufficient to choose
18147//
18148// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
18149//
18150// Since p2 = f mod 2^-e < 2^-e,
18151//
18152// -e <= 60 or e >= -60 := alpha
18153
18154constexpr int kAlpha = -60;
18155constexpr int kGamma = -32;
18156
18157struct cached_power // c = f * 2^e ~= 10^k
18158{
18159 std::uint64_t f;
18160 int e;
18161 int k;
18162};
18163
18172{
18173 // Now
18174 //
18175 // alpha <= e_c + e + q <= gamma (1)
18176 // ==> f_c * 2^alpha <= c * 2^e * 2^q
18177 //
18178 // and since the c's are normalized, 2^(q-1) <= f_c,
18179 //
18180 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
18181 // ==> 2^(alpha - e - 1) <= c
18182 //
18183 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
18184 //
18185 // k = ceil( log_10( 2^(alpha - e - 1) ) )
18186 // = ceil( (alpha - e - 1) * log_10(2) )
18187 //
18188 // From the paper:
18189 // "In theory the result of the procedure could be wrong since c is rounded,
18190 // and the computation itself is approximated [...]. In practice, however,
18191 // this simple function is sufficient."
18192 //
18193 // For IEEE double precision floating-point numbers converted into
18194 // normalized diyfp's w = f * 2^e, with q = 64,
18195 //
18196 // e >= -1022 (min IEEE exponent)
18197 // -52 (p - 1)
18198 // -52 (p - 1, possibly normalize denormal IEEE numbers)
18199 // -11 (normalize the diyfp)
18200 // = -1137
18201 //
18202 // and
18203 //
18204 // e <= +1023 (max IEEE exponent)
18205 // -52 (p - 1)
18206 // -11 (normalize the diyfp)
18207 // = 960
18208 //
18209 // This binary exponent range [-1137,960] results in a decimal exponent
18210 // range [-307,324]. One does not need to store a cached power for each
18211 // k in this range. For each such k it suffices to find a cached power
18212 // such that the exponent of the product lies in [alpha,gamma].
18213 // This implies that the difference of the decimal exponents of adjacent
18214 // table entries must be less than or equal to
18215 //
18216 // floor( (gamma - alpha) * log_10(2) ) = 8.
18217 //
18218 // (A smaller distance gamma-alpha would require a larger table.)
18219
18220 // NB:
18221 // Actually, this function returns c, such that -60 <= e_c + e + 64 <= -34.
18222
18223 constexpr int kCachedPowersMinDecExp = -300;
18224 constexpr int kCachedPowersDecStep = 8;
18225
18226 static constexpr std::array<cached_power, 79> kCachedPowers =
18227 {
18228 {
18229 { 0xAB70FE17C79AC6CA, -1060, -300 },
18230 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
18231 { 0xBE5691EF416BD60C, -1007, -284 },
18232 { 0x8DD01FAD907FFC3C, -980, -276 },
18233 { 0xD3515C2831559A83, -954, -268 },
18234 { 0x9D71AC8FADA6C9B5, -927, -260 },
18235 { 0xEA9C227723EE8BCB, -901, -252 },
18236 { 0xAECC49914078536D, -874, -244 },
18237 { 0x823C12795DB6CE57, -847, -236 },
18238 { 0xC21094364DFB5637, -821, -228 },
18239 { 0x9096EA6F3848984F, -794, -220 },
18240 { 0xD77485CB25823AC7, -768, -212 },
18241 { 0xA086CFCD97BF97F4, -741, -204 },
18242 { 0xEF340A98172AACE5, -715, -196 },
18243 { 0xB23867FB2A35B28E, -688, -188 },
18244 { 0x84C8D4DFD2C63F3B, -661, -180 },
18245 { 0xC5DD44271AD3CDBA, -635, -172 },
18246 { 0x936B9FCEBB25C996, -608, -164 },
18247 { 0xDBAC6C247D62A584, -582, -156 },
18248 { 0xA3AB66580D5FDAF6, -555, -148 },
18249 { 0xF3E2F893DEC3F126, -529, -140 },
18250 { 0xB5B5ADA8AAFF80B8, -502, -132 },
18251 { 0x87625F056C7C4A8B, -475, -124 },
18252 { 0xC9BCFF6034C13053, -449, -116 },
18253 { 0x964E858C91BA2655, -422, -108 },
18254 { 0xDFF9772470297EBD, -396, -100 },
18255 { 0xA6DFBD9FB8E5B88F, -369, -92 },
18256 { 0xF8A95FCF88747D94, -343, -84 },
18257 { 0xB94470938FA89BCF, -316, -76 },
18258 { 0x8A08F0F8BF0F156B, -289, -68 },
18259 { 0xCDB02555653131B6, -263, -60 },
18260 { 0x993FE2C6D07B7FAC, -236, -52 },
18261 { 0xE45C10C42A2B3B06, -210, -44 },
18262 { 0xAA242499697392D3, -183, -36 },
18263 { 0xFD87B5F28300CA0E, -157, -28 },
18264 { 0xBCE5086492111AEB, -130, -20 },
18265 { 0x8CBCCC096F5088CC, -103, -12 },
18266 { 0xD1B71758E219652C, -77, -4 },
18267 { 0x9C40000000000000, -50, 4 },
18268 { 0xE8D4A51000000000, -24, 12 },
18269 { 0xAD78EBC5AC620000, 3, 20 },
18270 { 0x813F3978F8940984, 30, 28 },
18271 { 0xC097CE7BC90715B3, 56, 36 },
18272 { 0x8F7E32CE7BEA5C70, 83, 44 },
18273 { 0xD5D238A4ABE98068, 109, 52 },
18274 { 0x9F4F2726179A2245, 136, 60 },
18275 { 0xED63A231D4C4FB27, 162, 68 },
18276 { 0xB0DE65388CC8ADA8, 189, 76 },
18277 { 0x83C7088E1AAB65DB, 216, 84 },
18278 { 0xC45D1DF942711D9A, 242, 92 },
18279 { 0x924D692CA61BE758, 269, 100 },
18280 { 0xDA01EE641A708DEA, 295, 108 },
18281 { 0xA26DA3999AEF774A, 322, 116 },
18282 { 0xF209787BB47D6B85, 348, 124 },
18283 { 0xB454E4A179DD1877, 375, 132 },
18284 { 0x865B86925B9BC5C2, 402, 140 },
18285 { 0xC83553C5C8965D3D, 428, 148 },
18286 { 0x952AB45CFA97A0B3, 455, 156 },
18287 { 0xDE469FBD99A05FE3, 481, 164 },
18288 { 0xA59BC234DB398C25, 508, 172 },
18289 { 0xF6C69A72A3989F5C, 534, 180 },
18290 { 0xB7DCBF5354E9BECE, 561, 188 },
18291 { 0x88FCF317F22241E2, 588, 196 },
18292 { 0xCC20CE9BD35C78A5, 614, 204 },
18293 { 0x98165AF37B2153DF, 641, 212 },
18294 { 0xE2A0B5DC971F303A, 667, 220 },
18295 { 0xA8D9D1535CE3B396, 694, 228 },
18296 { 0xFB9B7CD9A4A7443C, 720, 236 },
18297 { 0xBB764C4CA7A44410, 747, 244 },
18298 { 0x8BAB8EEFB6409C1A, 774, 252 },
18299 { 0xD01FEF10A657842C, 800, 260 },
18300 { 0x9B10A4E5E9913129, 827, 268 },
18301 { 0xE7109BFBA19C0C9D, 853, 276 },
18302 { 0xAC2820D9623BF429, 880, 284 },
18303 { 0x80444B5E7AA7CF85, 907, 292 },
18304 { 0xBF21E44003ACDD2D, 933, 300 },
18305 { 0x8E679C2F5E44FF8F, 960, 308 },
18306 { 0xD433179D9C8CB841, 986, 316 },
18307 { 0x9E19DB92B4E31BA9, 1013, 324 },
18308 }
18309 };
18310
18311 // This computation gives exactly the same results for k as
18312 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
18313 // for |e| <= 1500, but doesn't require floating-point operations.
18314 // NB: log_10(2) ~= 78913 / 2^18
18315 JSON_ASSERT(e >= -1500);
18316 JSON_ASSERT(e <= 1500);
18317 const int f = kAlpha - e - 1;
18318 const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
18319
18320 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
18321 JSON_ASSERT(index >= 0);
18322 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
18323
18324 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
18325 JSON_ASSERT(kAlpha <= cached.e + e + 64);
18326 JSON_ASSERT(kGamma >= cached.e + e + 64);
18327
18328 return cached;
18329}
18330
18335inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
18336{
18337 // LCOV_EXCL_START
18338 if (n >= 1000000000)
18339 {
18340 pow10 = 1000000000;
18341 return 10;
18342 }
18343 // LCOV_EXCL_STOP
18344 if (n >= 100000000)
18345 {
18346 pow10 = 100000000;
18347 return 9;
18348 }
18349 if (n >= 10000000)
18350 {
18351 pow10 = 10000000;
18352 return 8;
18353 }
18354 if (n >= 1000000)
18355 {
18356 pow10 = 1000000;
18357 return 7;
18358 }
18359 if (n >= 100000)
18360 {
18361 pow10 = 100000;
18362 return 6;
18363 }
18364 if (n >= 10000)
18365 {
18366 pow10 = 10000;
18367 return 5;
18368 }
18369 if (n >= 1000)
18370 {
18371 pow10 = 1000;
18372 return 4;
18373 }
18374 if (n >= 100)
18375 {
18376 pow10 = 100;
18377 return 3;
18378 }
18379 if (n >= 10)
18380 {
18381 pow10 = 10;
18382 return 2;
18383 }
18384
18385 pow10 = 1;
18386 return 1;
18387}
18388
18389inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
18390 std::uint64_t rest, std::uint64_t ten_k)
18391{
18392 JSON_ASSERT(len >= 1);
18393 JSON_ASSERT(dist <= delta);
18394 JSON_ASSERT(rest <= delta);
18395 JSON_ASSERT(ten_k > 0);
18396
18397 // <--------------------------- delta ---->
18398 // <---- dist --------->
18399 // --------------[------------------+-------------------]--------------
18400 // M- w M+
18401 //
18402 // ten_k
18403 // <------>
18404 // <---- rest ---->
18405 // --------------[------------------+----+--------------]--------------
18406 // w V
18407 // = buf * 10^k
18408 //
18409 // ten_k represents a unit-in-the-last-place in the decimal representation
18410 // stored in buf.
18411 // Decrement buf by ten_k while this takes buf closer to w.
18412
18413 // The tests are written in this order to avoid overflow in unsigned
18414 // integer arithmetic.
18415
18416 while (rest < dist
18417 && delta - rest >= ten_k
18418 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
18419 {
18420 JSON_ASSERT(buf[len - 1] != '0');
18421 buf[len - 1]--;
18422 rest += ten_k;
18423 }
18424}
18425
18430inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
18431 diyfp M_minus, diyfp w, diyfp M_plus)
18432{
18433 static_assert(kAlpha >= -60, "internal error");
18434 static_assert(kGamma <= -32, "internal error");
18435
18436 // Generates the digits (and the exponent) of a decimal floating-point
18437 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
18438 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
18439 //
18440 // <--------------------------- delta ---->
18441 // <---- dist --------->
18442 // --------------[------------------+-------------------]--------------
18443 // M- w M+
18444 //
18445 // Grisu2 generates the digits of M+ from left to right and stops as soon as
18446 // V is in [M-,M+].
18447
18448 JSON_ASSERT(M_plus.e >= kAlpha);
18449 JSON_ASSERT(M_plus.e <= kGamma);
18450
18451 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
18452 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
18453
18454 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
18455 //
18456 // M+ = f * 2^e
18457 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
18458 // = ((p1 ) * 2^-e + (p2 )) * 2^e
18459 // = p1 + p2 * 2^e
18460
18461 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
18462
18463 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.)
18464 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
18465
18466 // 1)
18467 //
18468 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
18469
18470 JSON_ASSERT(p1 > 0);
18471
18472 std::uint32_t pow10{};
18473 const int k = find_largest_pow10(p1, pow10);
18474
18475 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
18476 //
18477 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
18478 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
18479 //
18480 // M+ = p1 + p2 * 2^e
18481 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
18482 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
18483 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
18484 //
18485 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
18486 //
18487 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
18488 //
18489 // but stop as soon as
18490 //
18491 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
18492
18493 int n = k;
18494 while (n > 0)
18495 {
18496 // Invariants:
18497 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
18498 // pow10 = 10^(n-1) <= p1 < 10^n
18499 //
18500 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
18501 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
18502 //
18503 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
18504 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
18505 //
18506 JSON_ASSERT(d <= 9);
18507 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18508 //
18509 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
18510 //
18511 p1 = r;
18512 n--;
18513 //
18514 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
18515 // pow10 = 10^n
18516 //
18517
18518 // Now check if enough digits have been generated.
18519 // Compute
18520 //
18521 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
18522 //
18523 // Note:
18524 // Since rest and delta share the same exponent e, it suffices to
18525 // compare the significands.
18526 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
18527 if (rest <= delta)
18528 {
18529 // V = buffer * 10^n, with M- <= V <= M+.
18530
18531 decimal_exponent += n;
18532
18533 // We may now just stop. But instead, it looks as if the buffer
18534 // could be decremented to bring V closer to w.
18535 //
18536 // pow10 = 10^n is now 1 ulp in the decimal representation V.
18537 // The rounding procedure works with diyfp's with an implicit
18538 // exponent of e.
18539 //
18540 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
18541 //
18542 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
18543 grisu2_round(buffer, length, dist, delta, rest, ten_n);
18544
18545 return;
18546 }
18547
18548 pow10 /= 10;
18549 //
18550 // pow10 = 10^(n-1) <= p1 < 10^n
18551 // Invariants restored.
18552 }
18553
18554 // 2)
18555 //
18556 // The digits of the integral part have been generated:
18557 //
18558 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
18559 // = buffer + p2 * 2^e
18560 //
18561 // Now generate the digits of the fractional part p2 * 2^e.
18562 //
18563 // Note:
18564 // No decimal point is generated: the exponent is adjusted instead.
18565 //
18566 // p2 actually represents the fraction
18567 //
18568 // p2 * 2^e
18569 // = p2 / 2^-e
18570 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
18571 //
18572 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
18573 //
18574 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
18575 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
18576 //
18577 // using
18578 //
18579 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
18580 // = ( d) * 2^-e + ( r)
18581 //
18582 // or
18583 // 10^m * p2 * 2^e = d + r * 2^e
18584 //
18585 // i.e.
18586 //
18587 // M+ = buffer + p2 * 2^e
18588 // = buffer + 10^-m * (d + r * 2^e)
18589 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
18590 //
18591 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
18592
18593 JSON_ASSERT(p2 > delta);
18594
18595 int m = 0;
18596 for (;;)
18597 {
18598 // Invariant:
18599 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
18600 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
18601 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
18602 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
18603 //
18604 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
18605 p2 *= 10;
18606 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
18607 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
18608 //
18609 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
18610 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
18611 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
18612 //
18613 JSON_ASSERT(d <= 9);
18614 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18615 //
18616 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
18617 //
18618 p2 = r;
18619 m++;
18620 //
18621 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
18622 // Invariant restored.
18623
18624 // Check if enough digits have been generated.
18625 //
18626 // 10^-m * p2 * 2^e <= delta * 2^e
18627 // p2 * 2^e <= 10^m * delta * 2^e
18628 // p2 <= 10^m * delta
18629 delta *= 10;
18630 dist *= 10;
18631 if (p2 <= delta)
18632 {
18633 break;
18634 }
18635 }
18636
18637 // V = buffer * 10^-m, with M- <= V <= M+.
18638
18639 decimal_exponent -= m;
18640
18641 // 1 ulp in the decimal representation is now 10^-m.
18642 // Since delta and dist are now scaled by 10^m, we need to do the
18643 // same with ulp in order to keep the units in sync.
18644 //
18645 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
18646 //
18647 const std::uint64_t ten_m = one.f;
18648 grisu2_round(buffer, length, dist, delta, p2, ten_m);
18649
18650 // By construction this algorithm generates the shortest possible decimal
18651 // number (Loitsch, Theorem 6.2) which rounds back to w.
18652 // For an input number of precision p, at least
18653 //
18654 // N = 1 + ceil(p * log_10(2))
18655 //
18656 // decimal digits are sufficient to identify all binary floating-point
18657 // numbers (Matula, "In-and-Out conversions").
18658 // This implies that the algorithm does not produce more than N decimal
18659 // digits.
18660 //
18661 // N = 17 for p = 53 (IEEE double precision)
18662 // N = 9 for p = 24 (IEEE single precision)
18663}
18664
18671inline void grisu2(char* buf, int& len, int& decimal_exponent,
18672 diyfp m_minus, diyfp v, diyfp m_plus)
18673{
18674 JSON_ASSERT(m_plus.e == m_minus.e);
18675 JSON_ASSERT(m_plus.e == v.e);
18676
18677 // --------(-----------------------+-----------------------)-------- (A)
18678 // m- v m+
18679 //
18680 // --------------------(-----------+-----------------------)-------- (B)
18681 // m- v m+
18682 //
18683 // First scale v (and m- and m+) such that the exponent is in the range
18684 // [alpha, gamma].
18685
18686 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
18687
18688 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
18689
18690 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
18691 const diyfp w = diyfp::mul(v, c_minus_k);
18692 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
18693 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
18694
18695 // ----(---+---)---------------(---+---)---------------(---+---)----
18696 // w- w w+
18697 // = c*m- = c*v = c*m+
18698 //
18699 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
18700 // w+ are now off by a small amount.
18701 // In fact:
18702 //
18703 // w - v * 10^k < 1 ulp
18704 //
18705 // To account for this inaccuracy, add resp. subtract 1 ulp.
18706 //
18707 // --------+---[---------------(---+---)---------------]---+--------
18708 // w- M- w M+ w+
18709 //
18710 // Now any number in [M-, M+] (bounds included) will round to w when input,
18711 // regardless of how the input rounding algorithm breaks ties.
18712 //
18713 // And digit_gen generates the shortest possible such number in [M-, M+].
18714 // Note that this does not mean that Grisu2 always generates the shortest
18715 // possible number in the interval (m-, m+).
18716 const diyfp M_minus(w_minus.f + 1, w_minus.e);
18717 const diyfp M_plus (w_plus.f - 1, w_plus.e );
18718
18719 decimal_exponent = -cached.k; // = -(-k) = k
18720
18721 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
18722}
18723
18729template<typename FloatType>
18731void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
18732{
18733 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
18734 "internal error: not enough precision");
18735
18736 JSON_ASSERT(std::isfinite(value));
18737 JSON_ASSERT(value > 0);
18738
18739 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
18740 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
18741 // decimal representations are not exactly "short".
18742 //
18743 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
18744 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
18745 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
18746 // does.
18747 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
18748 // representation using the corresponding std::from_chars function recovers value exactly". That
18749 // indicates that single precision floating-point numbers should be recovered using
18750 // 'std::strtof'.
18751 //
18752 // NB: If the neighbors are computed for single-precision numbers, there is a single float
18753 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
18754 // value is off by 1 ulp.
18755#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
18756 const boundaries w = compute_boundaries(static_cast<double>(value));
18757#else
18759#endif
18760
18761 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
18762}
18763
18771inline char* append_exponent(char* buf, int e)
18772{
18773 JSON_ASSERT(e > -1000);
18774 JSON_ASSERT(e < 1000);
18775
18776 if (e < 0)
18777 {
18778 e = -e;
18779 *buf++ = '-';
18780 }
18781 else
18782 {
18783 *buf++ = '+';
18784 }
18785
18786 auto k = static_cast<std::uint32_t>(e);
18787 if (k < 10)
18788 {
18789 // Always print at least two digits in the exponent.
18790 // This is for compatibility with printf("%g").
18791 *buf++ = '0';
18792 *buf++ = static_cast<char>('0' + k);
18793 }
18794 else if (k < 100)
18795 {
18796 *buf++ = static_cast<char>('0' + (k / 10));
18797 k %= 10;
18798 *buf++ = static_cast<char>('0' + k);
18799 }
18800 else
18801 {
18802 *buf++ = static_cast<char>('0' + (k / 100));
18803 k %= 100;
18804 *buf++ = static_cast<char>('0' + (k / 10));
18805 k %= 10;
18806 *buf++ = static_cast<char>('0' + k);
18807 }
18808
18809 return buf;
18810}
18811
18823inline char* format_buffer(char* buf, int len, int decimal_exponent,
18824 int min_exp, int max_exp)
18825{
18826 JSON_ASSERT(min_exp < 0);
18827 JSON_ASSERT(max_exp > 0);
18828
18829 const int k = len;
18830 const int n = len + decimal_exponent;
18831
18832 // v = buf * 10^(n-k)
18833 // k is the length of the buffer (number of decimal digits)
18834 // n is the position of the decimal point relative to the start of the buffer.
18835
18836 if (k <= n && n <= max_exp)
18837 {
18838 // digits[000]
18839 // len <= max_exp + 2
18840
18841 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
18842 // Make it look like a floating-point number (#362, #378)
18843 buf[n + 0] = '.';
18844 buf[n + 1] = '0';
18845 return buf + (static_cast<size_t>(n) + 2);
18846 }
18847
18848 if (0 < n && n <= max_exp)
18849 {
18850 // dig.its
18851 // len <= max_digits10 + 1
18852
18853 JSON_ASSERT(k > n);
18854
18855 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
18856 buf[n] = '.';
18857 return buf + (static_cast<size_t>(k) + 1U);
18858 }
18859
18860 if (min_exp < n && n <= 0)
18861 {
18862 // 0.[000]digits
18863 // len <= 2 + (-min_exp - 1) + max_digits10
18864
18865 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
18866 buf[0] = '0';
18867 buf[1] = '.';
18868 std::memset(buf + 2, '0', static_cast<size_t>(-n));
18869 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
18870 }
18871
18872 if (k == 1)
18873 {
18874 // dE+123
18875 // len <= 1 + 5
18876
18877 buf += 1;
18878 }
18879 else
18880 {
18881 // d.igitsE+123
18882 // len <= max_digits10 + 1 + 5
18883
18884 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
18885 buf[1] = '.';
18886 buf += 1 + static_cast<size_t>(k);
18887 }
18888
18889 *buf++ = 'e';
18890 return append_exponent(buf, n - 1);
18891}
18892
18893} // namespace dtoa_impl
18894
18905template<typename FloatType>
18908char* to_chars(char* first, const char* last, FloatType value)
18909{
18910 static_cast<void>(last); // maybe unused - fix warning
18911 JSON_ASSERT(std::isfinite(value));
18912
18913 // Use signbit(value) instead of (value < 0) since signbit works for -0.
18914 if (std::signbit(value))
18915 {
18916 value = -value;
18917 *first++ = '-';
18918 }
18919
18920#ifdef __GNUC__
18921#pragma GCC diagnostic push
18922#pragma GCC diagnostic ignored "-Wfloat-equal"
18923#endif
18924 if (value == 0) // +-0
18925 {
18926 *first++ = '0';
18927 // Make it look like a floating-point number (#362, #378)
18928 *first++ = '.';
18929 *first++ = '0';
18930 return first;
18931 }
18932#ifdef __GNUC__
18933#pragma GCC diagnostic pop
18934#endif
18935
18936 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18937
18938 // Compute v = buffer * 10^decimal_exponent.
18939 // The decimal digits are stored in the buffer, which needs to be interpreted
18940 // as an unsigned decimal integer.
18941 // len is the length of the buffer, i.e., the number of decimal digits.
18942 int len = 0;
18943 int decimal_exponent = 0;
18944 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18945
18946 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18947
18948 // Format the buffer like printf("%.*g", prec, value)
18949 constexpr int kMinExp = -4;
18950 // Use digits10 here to increase compatibility with version 2.
18951 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18952
18953 JSON_ASSERT(last - first >= kMaxExp + 2);
18954 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18955 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18956
18957 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18958}
18959
18960} // namespace detail
18962
18963// #include <nlohmann/detail/exceptions.hpp>
18964
18965// #include <nlohmann/detail/macro_scope.hpp>
18966
18967// #include <nlohmann/detail/meta/cpp_future.hpp>
18968
18969// #include <nlohmann/detail/output/binary_writer.hpp>
18970
18971// #include <nlohmann/detail/output/output_adapters.hpp>
18972
18973// #include <nlohmann/detail/string_concat.hpp>
18974
18975// #include <nlohmann/detail/value_t.hpp>
18976
18977
18979namespace detail
18980{
18981
18983// serialization //
18985
18988{
18989 strict,
18990 replace,
18991 ignore
18992};
18993
18994template<typename BasicJsonType>
18996{
18997 using string_t = typename BasicJsonType::string_t;
18998 using number_float_t = typename BasicJsonType::number_float_t;
18999 using number_integer_t = typename BasicJsonType::number_integer_t;
19000 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
19001 using binary_char_t = typename BasicJsonType::binary_t::value_type;
19002 static constexpr std::uint8_t UTF8_ACCEPT = 0;
19003 static constexpr std::uint8_t UTF8_REJECT = 1;
19004
19005 public:
19012 error_handler_t error_handler_ = error_handler_t::strict)
19013 : o(std::move(s))
19014 , loc(std::localeconv())
19015 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
19016 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
19017 , indent_char(ichar)
19018 , indent_string(512, indent_char)
19019 , error_handler(error_handler_)
19020 {}
19021
19022 // deleted because of pointer members
19023 serializer(const serializer&) = delete;
19027 ~serializer() = default;
19028
19051 void dump(const BasicJsonType& val,
19052 const bool pretty_print,
19053 const bool ensure_ascii,
19054 const unsigned int indent_step,
19055 const unsigned int current_indent = 0)
19056 {
19057 switch (val.m_data.m_type)
19058 {
19059 case value_t::object:
19060 {
19061 if (val.m_data.m_value.object->empty())
19062 {
19063 o->write_characters("{}", 2);
19064 return;
19065 }
19066
19067 if (pretty_print)
19068 {
19069 o->write_characters("{\n", 2);
19070
19071 // variable to hold indentation for recursive calls
19072 const auto new_indent = current_indent + indent_step;
19073 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
19074 {
19075 indent_string.resize(indent_string.size() * 2, ' ');
19076 }
19077
19078 // first n-1 elements
19079 auto i = val.m_data.m_value.object->cbegin();
19080 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
19081 {
19082 o->write_characters(indent_string.c_str(), new_indent);
19083 o->write_character('\"');
19084 dump_escaped(i->first, ensure_ascii);
19085 o->write_characters("\": ", 3);
19086 dump(i->second, true, ensure_ascii, indent_step, new_indent);
19087 o->write_characters(",\n", 2);
19088 }
19089
19090 // last element
19091 JSON_ASSERT(i != val.m_data.m_value.object->cend());
19092 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
19093 o->write_characters(indent_string.c_str(), new_indent);
19094 o->write_character('\"');
19095 dump_escaped(i->first, ensure_ascii);
19096 o->write_characters("\": ", 3);
19097 dump(i->second, true, ensure_ascii, indent_step, new_indent);
19098
19099 o->write_character('\n');
19100 o->write_characters(indent_string.c_str(), current_indent);
19101 o->write_character('}');
19102 }
19103 else
19104 {
19105 o->write_character('{');
19106
19107 // first n-1 elements
19108 auto i = val.m_data.m_value.object->cbegin();
19109 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
19110 {
19111 o->write_character('\"');
19112 dump_escaped(i->first, ensure_ascii);
19113 o->write_characters("\":", 2);
19114 dump(i->second, false, ensure_ascii, indent_step, current_indent);
19115 o->write_character(',');
19116 }
19117
19118 // last element
19119 JSON_ASSERT(i != val.m_data.m_value.object->cend());
19120 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
19121 o->write_character('\"');
19122 dump_escaped(i->first, ensure_ascii);
19123 o->write_characters("\":", 2);
19124 dump(i->second, false, ensure_ascii, indent_step, current_indent);
19125
19126 o->write_character('}');
19127 }
19128
19129 return;
19130 }
19131
19132 case value_t::array:
19133 {
19134 if (val.m_data.m_value.array->empty())
19135 {
19136 o->write_characters("[]", 2);
19137 return;
19138 }
19139
19140 if (pretty_print)
19141 {
19142 o->write_characters("[\n", 2);
19143
19144 // variable to hold indentation for recursive calls
19145 const auto new_indent = current_indent + indent_step;
19146 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
19147 {
19148 indent_string.resize(indent_string.size() * 2, ' ');
19149 }
19150
19151 // first n-1 elements
19152 for (auto i = val.m_data.m_value.array->cbegin();
19153 i != val.m_data.m_value.array->cend() - 1; ++i)
19154 {
19155 o->write_characters(indent_string.c_str(), new_indent);
19156 dump(*i, true, ensure_ascii, indent_step, new_indent);
19157 o->write_characters(",\n", 2);
19158 }
19159
19160 // last element
19161 JSON_ASSERT(!val.m_data.m_value.array->empty());
19162 o->write_characters(indent_string.c_str(), new_indent);
19163 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
19164
19165 o->write_character('\n');
19166 o->write_characters(indent_string.c_str(), current_indent);
19167 o->write_character(']');
19168 }
19169 else
19170 {
19171 o->write_character('[');
19172
19173 // first n-1 elements
19174 for (auto i = val.m_data.m_value.array->cbegin();
19175 i != val.m_data.m_value.array->cend() - 1; ++i)
19176 {
19177 dump(*i, false, ensure_ascii, indent_step, current_indent);
19178 o->write_character(',');
19179 }
19180
19181 // last element
19182 JSON_ASSERT(!val.m_data.m_value.array->empty());
19183 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
19184
19185 o->write_character(']');
19186 }
19187
19188 return;
19189 }
19190
19191 case value_t::string:
19192 {
19193 o->write_character('\"');
19194 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
19195 o->write_character('\"');
19196 return;
19197 }
19198
19199 case value_t::binary:
19200 {
19201 if (pretty_print)
19202 {
19203 o->write_characters("{\n", 2);
19204
19205 // variable to hold indentation for recursive calls
19206 const auto new_indent = current_indent + indent_step;
19207 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
19208 {
19209 indent_string.resize(indent_string.size() * 2, ' ');
19210 }
19211
19212 o->write_characters(indent_string.c_str(), new_indent);
19213
19214 o->write_characters("\"bytes\": [", 10);
19215
19216 if (!val.m_data.m_value.binary->empty())
19217 {
19218 for (auto i = val.m_data.m_value.binary->cbegin();
19219 i != val.m_data.m_value.binary->cend() - 1; ++i)
19220 {
19221 dump_integer(*i);
19222 o->write_characters(", ", 2);
19223 }
19224 dump_integer(val.m_data.m_value.binary->back());
19225 }
19226
19227 o->write_characters("],\n", 3);
19228 o->write_characters(indent_string.c_str(), new_indent);
19229
19230 o->write_characters("\"subtype\": ", 11);
19231 if (val.m_data.m_value.binary->has_subtype())
19232 {
19233 dump_integer(val.m_data.m_value.binary->subtype());
19234 }
19235 else
19236 {
19237 o->write_characters("null", 4);
19238 }
19239 o->write_character('\n');
19240 o->write_characters(indent_string.c_str(), current_indent);
19241 o->write_character('}');
19242 }
19243 else
19244 {
19245 o->write_characters("{\"bytes\":[", 10);
19246
19247 if (!val.m_data.m_value.binary->empty())
19248 {
19249 for (auto i = val.m_data.m_value.binary->cbegin();
19250 i != val.m_data.m_value.binary->cend() - 1; ++i)
19251 {
19252 dump_integer(*i);
19253 o->write_character(',');
19254 }
19255 dump_integer(val.m_data.m_value.binary->back());
19256 }
19257
19258 o->write_characters("],\"subtype\":", 12);
19259 if (val.m_data.m_value.binary->has_subtype())
19260 {
19261 dump_integer(val.m_data.m_value.binary->subtype());
19262 o->write_character('}');
19263 }
19264 else
19265 {
19266 o->write_characters("null}", 5);
19267 }
19268 }
19269 return;
19270 }
19271
19272 case value_t::boolean:
19273 {
19274 if (val.m_data.m_value.boolean)
19275 {
19276 o->write_characters("true", 4);
19277 }
19278 else
19279 {
19280 o->write_characters("false", 5);
19281 }
19282 return;
19283 }
19284
19285 case value_t::number_integer:
19286 {
19287 dump_integer(val.m_data.m_value.number_integer);
19288 return;
19289 }
19290
19291 case value_t::number_unsigned:
19292 {
19293 dump_integer(val.m_data.m_value.number_unsigned);
19294 return;
19295 }
19296
19297 case value_t::number_float:
19298 {
19299 dump_float(val.m_data.m_value.number_float);
19300 return;
19301 }
19302
19303 case value_t::discarded:
19304 {
19305 o->write_characters("<discarded>", 11);
19306 return;
19307 }
19308
19309 case value_t::null:
19310 {
19311 o->write_characters("null", 4);
19312 return;
19313 }
19314
19315 default: // LCOV_EXCL_LINE
19316 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19317 }
19318 }
19319
19335 void dump_escaped(const string_t& s, const bool ensure_ascii)
19336 {
19337 std::uint32_t codepoint{};
19338 std::uint8_t state = UTF8_ACCEPT;
19339 std::size_t bytes = 0; // number of bytes written to string_buffer
19340
19341 // number of bytes written at the point of the last valid byte
19342 std::size_t bytes_after_last_accept = 0;
19343 std::size_t undumped_chars = 0;
19344
19345 for (std::size_t i = 0; i < s.size(); ++i)
19346 {
19347 const auto byte = static_cast<std::uint8_t>(s[i]);
19348
19349 switch (decode(state, codepoint, byte))
19350 {
19351 case UTF8_ACCEPT: // decode found a new code point
19352 {
19353 switch (codepoint)
19354 {
19355 case 0x08: // backspace
19356 {
19357 string_buffer[bytes++] = '\\';
19358 string_buffer[bytes++] = 'b';
19359 break;
19360 }
19361
19362 case 0x09: // horizontal tab
19363 {
19364 string_buffer[bytes++] = '\\';
19365 string_buffer[bytes++] = 't';
19366 break;
19367 }
19368
19369 case 0x0A: // newline
19370 {
19371 string_buffer[bytes++] = '\\';
19372 string_buffer[bytes++] = 'n';
19373 break;
19374 }
19375
19376 case 0x0C: // formfeed
19377 {
19378 string_buffer[bytes++] = '\\';
19379 string_buffer[bytes++] = 'f';
19380 break;
19381 }
19382
19383 case 0x0D: // carriage return
19384 {
19385 string_buffer[bytes++] = '\\';
19386 string_buffer[bytes++] = 'r';
19387 break;
19388 }
19389
19390 case 0x22: // quotation mark
19391 {
19392 string_buffer[bytes++] = '\\';
19393 string_buffer[bytes++] = '\"';
19394 break;
19395 }
19396
19397 case 0x5C: // reverse solidus
19398 {
19399 string_buffer[bytes++] = '\\';
19400 string_buffer[bytes++] = '\\';
19401 break;
19402 }
19403
19404 default:
19405 {
19406 // escape control characters (0x00..0x1F) or, if
19407 // ensure_ascii parameter is used, non-ASCII characters
19408 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
19409 {
19410 if (codepoint <= 0xFFFF)
19411 {
19412 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19413 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
19414 static_cast<std::uint16_t>(codepoint)));
19415 bytes += 6;
19416 }
19417 else
19418 {
19419 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19420 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
19421 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
19422 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
19423 bytes += 12;
19424 }
19425 }
19426 else
19427 {
19428 // copy byte to buffer (all previous bytes
19429 // been copied have in default case above)
19430 string_buffer[bytes++] = s[i];
19431 }
19432 break;
19433 }
19434 }
19435
19436 // write buffer and reset index; there must be 13 bytes
19437 // left, as this is the maximal number of bytes to be
19438 // written ("\uxxxx\uxxxx\0") for one code point
19439 if (string_buffer.size() - bytes < 13)
19440 {
19441 o->write_characters(string_buffer.data(), bytes);
19442 bytes = 0;
19443 }
19444
19445 // remember the byte position of this accept
19446 bytes_after_last_accept = bytes;
19447 undumped_chars = 0;
19448 break;
19449 }
19450
19451 case UTF8_REJECT: // decode found invalid UTF-8 byte
19452 {
19453 switch (error_handler)
19454 {
19455 case error_handler_t::strict:
19456 {
19457 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
19458 }
19459
19460 case error_handler_t::ignore:
19461 case error_handler_t::replace:
19462 {
19463 // in case we saw this character the first time, we
19464 // would like to read it again, because the byte
19465 // may be OK for itself, but just not OK for the
19466 // previous sequence
19467 if (undumped_chars > 0)
19468 {
19469 --i;
19470 }
19471
19472 // reset length buffer to the last accepted index;
19473 // thus removing/ignoring the invalid characters
19474 bytes = bytes_after_last_accept;
19475
19476 if (error_handler == error_handler_t::replace)
19477 {
19478 // add a replacement character
19479 if (ensure_ascii)
19480 {
19481 string_buffer[bytes++] = '\\';
19482 string_buffer[bytes++] = 'u';
19483 string_buffer[bytes++] = 'f';
19484 string_buffer[bytes++] = 'f';
19485 string_buffer[bytes++] = 'f';
19486 string_buffer[bytes++] = 'd';
19487 }
19488 else
19489 {
19490 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
19491 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
19492 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
19493 }
19494
19495 // write buffer and reset index; there must be 13 bytes
19496 // left, as this is the maximal number of bytes to be
19497 // written ("\uxxxx\uxxxx\0") for one code point
19498 if (string_buffer.size() - bytes < 13)
19499 {
19500 o->write_characters(string_buffer.data(), bytes);
19501 bytes = 0;
19502 }
19503
19504 bytes_after_last_accept = bytes;
19505 }
19506
19507 undumped_chars = 0;
19508
19509 // continue processing the string
19510 state = UTF8_ACCEPT;
19511 break;
19512 }
19513
19514 default: // LCOV_EXCL_LINE
19515 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19516 }
19517 break;
19518 }
19519
19520 default: // decode found yet incomplete multibyte code point
19521 {
19522 if (!ensure_ascii)
19523 {
19524 // code point will not be escaped - copy byte to buffer
19525 string_buffer[bytes++] = s[i];
19526 }
19527 ++undumped_chars;
19528 break;
19529 }
19530 }
19531 }
19532
19533 // we finished processing the string
19534 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
19535 {
19536 // write buffer
19537 if (bytes > 0)
19538 {
19539 o->write_characters(string_buffer.data(), bytes);
19540 }
19541 }
19542 else
19543 {
19544 // we finish reading, but do not accept: string was incomplete
19545 switch (error_handler)
19546 {
19547 case error_handler_t::strict:
19548 {
19549 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));
19550 }
19551
19552 case error_handler_t::ignore:
19553 {
19554 // write all accepted bytes
19555 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19556 break;
19557 }
19558
19559 case error_handler_t::replace:
19560 {
19561 // write all accepted bytes
19562 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19563 // add a replacement character
19564 if (ensure_ascii)
19565 {
19566 o->write_characters("\\ufffd", 6);
19567 }
19568 else
19569 {
19570 o->write_characters("\xEF\xBF\xBD", 3);
19571 }
19572 break;
19573 }
19574
19575 default: // LCOV_EXCL_LINE
19576 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19577 }
19578 }
19579 }
19580
19581 private:
19590 unsigned int count_digits(number_unsigned_t x) noexcept
19591 {
19592 unsigned int n_digits = 1;
19593 for (;;)
19594 {
19595 if (x < 10)
19596 {
19597 return n_digits;
19598 }
19599 if (x < 100)
19600 {
19601 return n_digits + 1;
19602 }
19603 if (x < 1000)
19604 {
19605 return n_digits + 2;
19606 }
19607 if (x < 10000)
19608 {
19609 return n_digits + 3;
19610 }
19611 x = x / 10000u;
19612 n_digits += 4;
19613 }
19614 }
19615
19621 static std::string hex_bytes(std::uint8_t byte)
19622 {
19623 std::string result = "FF";
19624 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
19625 result[0] = nibble_to_hex[byte / 16];
19626 result[1] = nibble_to_hex[byte % 16];
19627 return result;
19628 }
19629
19630 // templates to avoid warnings about useless casts
19631 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
19632 bool is_negative_number(NumberType x)
19633 {
19634 return x < 0;
19635 }
19636
19637 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
19638 bool is_negative_number(NumberType /*unused*/)
19639 {
19640 return false;
19641 }
19642
19652 template < typename NumberType, detail::enable_if_t <
19653 std::is_integral<NumberType>::value ||
19654 std::is_same<NumberType, number_unsigned_t>::value ||
19655 std::is_same<NumberType, number_integer_t>::value ||
19656 std::is_same<NumberType, binary_char_t>::value,
19657 int > = 0 >
19658 void dump_integer(NumberType x)
19659 {
19660 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
19661 {
19662 {
19663 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
19664 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
19665 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
19666 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
19667 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
19668 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
19669 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
19670 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
19671 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
19672 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
19673 }
19674 };
19675
19676 // special case for "0"
19677 if (x == 0)
19678 {
19679 o->write_character('0');
19680 return;
19681 }
19682
19683 // use a pointer to fill the buffer
19684 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19685
19686 number_unsigned_t abs_value;
19687
19688 unsigned int n_chars{};
19689
19690 if (is_negative_number(x))
19691 {
19692 *buffer_ptr = '-';
19693 abs_value = remove_sign(static_cast<number_integer_t>(x));
19694
19695 // account one more byte for the minus sign
19696 n_chars = 1 + count_digits(abs_value);
19697 }
19698 else
19699 {
19700 abs_value = static_cast<number_unsigned_t>(x);
19701 n_chars = count_digits(abs_value);
19702 }
19703
19704 // spare 1 byte for '\0'
19705 JSON_ASSERT(n_chars < number_buffer.size() - 1);
19706
19707 // jump to the end to generate the string from backward,
19708 // so we later avoid reversing the result
19709 buffer_ptr += static_cast<typename decltype(number_buffer)::difference_type>(n_chars);
19710
19711 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
19712 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
19713 while (abs_value >= 100)
19714 {
19715 const auto digits_index = static_cast<unsigned>((abs_value % 100));
19716 abs_value /= 100;
19717 *(--buffer_ptr) = digits_to_99[digits_index][1];
19718 *(--buffer_ptr) = digits_to_99[digits_index][0];
19719 }
19720
19721 if (abs_value >= 10)
19722 {
19723 const auto digits_index = static_cast<unsigned>(abs_value);
19724 *(--buffer_ptr) = digits_to_99[digits_index][1];
19725 *(--buffer_ptr) = digits_to_99[digits_index][0];
19726 }
19727 else
19728 {
19729 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
19730 }
19731
19732 o->write_characters(number_buffer.data(), n_chars);
19733 }
19734
19743 void dump_float(number_float_t x)
19744 {
19745 // NaN / inf
19746 if (!std::isfinite(x))
19747 {
19748 o->write_characters("null", 4);
19749 return;
19750 }
19751
19752 // If number_float_t is an IEEE-754 single or double precision number,
19753 // use the Grisu2 algorithm to produce short numbers which are
19754 // guaranteed to round-trip, using strtof and strtod, resp.
19755 //
19756 // NB: The test below works if <long double> == <double>.
19757 static constexpr bool is_ieee_single_or_double
19758 = (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) ||
19759 (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);
19760
19761 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
19762 }
19763
19764 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
19765 {
19766 auto* begin = number_buffer.data();
19767 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
19768
19769 o->write_characters(begin, static_cast<size_t>(end - begin));
19770 }
19771
19772 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
19773 {
19774 // get the number of digits for a float -> text -> float round-trip
19775 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
19776
19777 // the actual conversion
19778 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19779 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
19780
19781 // negative value indicates an error
19782 JSON_ASSERT(len > 0);
19783 // check if the buffer was large enough
19784 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
19785
19786 // erase thousands separators
19787 if (thousands_sep != '\0')
19788 {
19789 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
19790 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
19791 std::fill(end, number_buffer.end(), '\0');
19792 JSON_ASSERT((end - number_buffer.begin()) <= len);
19793 len = (end - number_buffer.begin());
19794 }
19795
19796 // convert decimal point to '.'
19797 if (decimal_point != '\0' && decimal_point != '.')
19798 {
19799 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
19800 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
19801 if (dec_pos != number_buffer.end())
19802 {
19803 *dec_pos = '.';
19804 }
19805 }
19806
19807 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
19808
19809 // determine if we need to append ".0"
19810 const bool value_is_int_like =
19811 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
19812 [](char c)
19813 {
19814 return c == '.' || c == 'e';
19815 });
19816
19817 if (value_is_int_like)
19818 {
19819 o->write_characters(".0", 2);
19820 }
19821 }
19822
19844 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
19845 {
19846 static const std::array<std::uint8_t, 400> utf8d =
19847 {
19848 {
19849 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
19850 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
19851 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
19852 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
19853 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
19854 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
19855 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
19856 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
19857 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
19858 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
19859 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
19860 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
19861 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
19862 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
19863 }
19864 };
19865
19866 JSON_ASSERT(static_cast<std::size_t>(byte) < utf8d.size());
19867 const std::uint8_t type = utf8d[byte];
19868
19869 codep = (state != UTF8_ACCEPT)
19870 ? (byte & 0x3fu) | (codep << 6u)
19871 : (0xFFu >> type) & (byte);
19872
19873 const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
19874 JSON_ASSERT(index < utf8d.size());
19875 state = utf8d[index];
19876 return state;
19877 }
19878
19879 /*
19880 * Overload to make the compiler happy while it is instantiating
19881 * dump_integer for number_unsigned_t.
19882 * Must never be called.
19883 */
19884 number_unsigned_t remove_sign(number_unsigned_t x)
19885 {
19886 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19887 return x; // LCOV_EXCL_LINE
19888 }
19889
19890 /*
19891 * Helper function for dump_integer
19892 *
19893 * This function takes a negative signed integer and returns its absolute
19894 * value as an unsigned integer. The plus/minus shuffling is necessary as we
19895 * cannot directly remove the sign of an arbitrary signed integer as the
19896 * absolute values of INT_MIN and INT_MAX are usually not the same. See
19897 * #1708 for details.
19898 */
19899 number_unsigned_t remove_sign(number_integer_t x) noexcept
19900 {
19901 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
19902 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
19903 }
19904
19905 private:
19907 output_adapter_t<char> o = nullptr;
19908
19910 std::array<char, 64> number_buffer{{}};
19911
19913 const std::lconv* loc = nullptr;
19915 const char thousands_sep = '\0';
19917 const char decimal_point = '\0';
19918
19920 std::array<char, 512> string_buffer{{}};
19921
19923 const char indent_char;
19926
19929};
19930
19931} // namespace detail
19933
19934// #include <nlohmann/detail/value_t.hpp>
19935
19936// #include <nlohmann/json_fwd.hpp>
19937
19938// #include <nlohmann/ordered_map.hpp>
19939// __ _____ _____ _____
19940// __| | __| | | | JSON for Modern C++
19941// | | |__ | | | | | | version 3.12.0
19942// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19943//
19944// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
19945// SPDX-License-Identifier: MIT
19946
19947
19948
19949#include <functional> // equal_to, less
19950#include <initializer_list> // initializer_list
19951#include <iterator> // input_iterator_tag, iterator_traits
19952#include <memory> // allocator
19953#include <stdexcept> // for out_of_range
19954#include <type_traits> // enable_if, is_convertible
19955#include <utility> // pair
19956#include <vector> // vector
19957
19958// #include <nlohmann/detail/macro_scope.hpp>
19959
19960// #include <nlohmann/detail/meta/type_traits.hpp>
19961
19962
19964
19967template <class Key, class T, class IgnoredLess = std::less<Key>,
19968 class Allocator = std::allocator<std::pair<const Key, T>>>
19969 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19970{
19971 using key_type = Key;
19972 using mapped_type = T;
19973 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19974 using iterator = typename Container::iterator;
19975 using const_iterator = typename Container::const_iterator;
19976 using size_type = typename Container::size_type;
19977 using value_type = typename Container::value_type;
19978#ifdef JSON_HAS_CPP_14
19979 using key_compare = std::equal_to<>;
19980#else
19981 using key_compare = std::equal_to<Key>;
19982#endif
19983
19984 // Explicit constructors instead of `using Container::Container`
19985 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19986 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19987 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19988 template <class It>
19989 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19990 : Container{first, last, alloc} {}
19991 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19992 : Container{init, alloc} {}
19993
19994 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19995 {
19996 for (auto it = this->begin(); it != this->end(); ++it)
19997 {
19998 if (m_compare(it->first, key))
19999 {
20000 return {it, false};
20001 }
20002 }
20003 Container::emplace_back(key, std::forward<T>(t));
20004 return {std::prev(this->end()), true};
20005 }
20006
20007 template<class KeyType, detail::enable_if_t<
20009 std::pair<iterator, bool> emplace(KeyType && key, T && t)
20010 {
20011 for (auto it = this->begin(); it != this->end(); ++it)
20012 {
20013 if (m_compare(it->first, key))
20014 {
20015 return {it, false};
20016 }
20017 }
20018 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
20019 return {std::prev(this->end()), true};
20020 }
20021
20022 T& operator[](const key_type& key)
20023 {
20024 return emplace(key, T{}).first->second;
20025 }
20026
20027 template<class KeyType, detail::enable_if_t<
20029 T & operator[](KeyType && key)
20030 {
20031 return emplace(std::forward<KeyType>(key), T{}).first->second;
20032 }
20033
20034 const T& operator[](const key_type& key) const
20035 {
20036 return at(key);
20037 }
20038
20039 template<class KeyType, detail::enable_if_t<
20041 const T & operator[](KeyType && key) const
20042 {
20043 return at(std::forward<KeyType>(key));
20044 }
20045
20046 T& at(const key_type& key)
20047 {
20048 for (auto it = this->begin(); it != this->end(); ++it)
20049 {
20050 if (m_compare(it->first, key))
20051 {
20052 return it->second;
20053 }
20054 }
20055
20056 JSON_THROW(std::out_of_range("key not found"));
20057 }
20058
20059 template<class KeyType, detail::enable_if_t<
20061 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
20062 {
20063 for (auto it = this->begin(); it != this->end(); ++it)
20064 {
20065 if (m_compare(it->first, key))
20066 {
20067 return it->second;
20068 }
20069 }
20070
20071 JSON_THROW(std::out_of_range("key not found"));
20072 }
20073
20074 const T& at(const key_type& key) const
20075 {
20076 for (auto it = this->begin(); it != this->end(); ++it)
20077 {
20078 if (m_compare(it->first, key))
20079 {
20080 return it->second;
20081 }
20082 }
20083
20084 JSON_THROW(std::out_of_range("key not found"));
20085 }
20086
20087 template<class KeyType, detail::enable_if_t<
20089 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
20090 {
20091 for (auto it = this->begin(); it != this->end(); ++it)
20092 {
20093 if (m_compare(it->first, key))
20094 {
20095 return it->second;
20096 }
20097 }
20098
20099 JSON_THROW(std::out_of_range("key not found"));
20100 }
20101
20103 {
20104 for (auto it = this->begin(); it != this->end(); ++it)
20105 {
20106 if (m_compare(it->first, key))
20107 {
20108 // Since we cannot move const Keys, re-construct them in place
20109 for (auto next = it; ++next != this->end(); ++it)
20110 {
20111 it->~value_type(); // Destroy but keep allocation
20112 new (&*it) value_type{std::move(*next)};
20113 }
20114 Container::pop_back();
20115 return 1;
20116 }
20117 }
20118 return 0;
20119 }
20120
20121 template<class KeyType, detail::enable_if_t<
20123 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
20124 {
20125 for (auto it = this->begin(); it != this->end(); ++it)
20126 {
20127 if (m_compare(it->first, key))
20128 {
20129 // Since we cannot move const Keys, re-construct them in place
20130 for (auto next = it; ++next != this->end(); ++it)
20131 {
20132 it->~value_type(); // Destroy but keep allocation
20133 new (&*it) value_type{std::move(*next)};
20134 }
20135 Container::pop_back();
20136 return 1;
20137 }
20138 }
20139 return 0;
20140 }
20141
20143 {
20144 return erase(pos, std::next(pos));
20145 }
20146
20148 {
20149 if (first == last)
20150 {
20151 return first;
20152 }
20153
20154 const auto elements_affected = std::distance(first, last);
20155 const auto offset = std::distance(Container::begin(), first);
20156
20157 // This is the start situation. We need to delete elements_affected
20158 // elements (3 in this example: e, f, g), and need to return an
20159 // iterator past the last deleted element (h in this example).
20160 // Note that offset is the distance from the start of the vector
20161 // to first. We will need this later.
20162
20163 // [ a, b, c, d, e, f, g, h, i, j ]
20164 // ^ ^
20165 // first last
20166
20167 // Since we cannot move const Keys, we re-construct them in place.
20168 // We start at first and re-construct (viz. copy) the elements from
20169 // the back of the vector. Example for the first iteration:
20170
20171 // ,--------.
20172 // v | destroy e and re-construct with h
20173 // [ a, b, c, d, e, f, g, h, i, j ]
20174 // ^ ^
20175 // it it + elements_affected
20176
20177 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
20178 {
20179 it->~value_type(); // destroy but keep allocation
20180 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
20181 }
20182
20183 // [ a, b, c, d, h, i, j, h, i, j ]
20184 // ^ ^
20185 // first last
20186
20187 // remove the unneeded elements at the end of the vector
20188 Container::resize(this->size() - static_cast<size_type>(elements_affected));
20189
20190 // [ a, b, c, d, h, i, j ]
20191 // ^ ^
20192 // first last
20193
20194 // first is now pointing past the last deleted element, but we cannot
20195 // use this iterator, because it may have been invalidated by the
20196 // resize call. Instead, we can return begin() + offset.
20197 return Container::begin() + offset;
20198 }
20199
20200 size_type count(const key_type& key) const
20201 {
20202 for (auto it = this->begin(); it != this->end(); ++it)
20203 {
20204 if (m_compare(it->first, key))
20205 {
20206 return 1;
20207 }
20208 }
20209 return 0;
20210 }
20211
20212 template<class KeyType, detail::enable_if_t<
20214 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
20215 {
20216 for (auto it = this->begin(); it != this->end(); ++it)
20217 {
20218 if (m_compare(it->first, key))
20219 {
20220 return 1;
20221 }
20222 }
20223 return 0;
20224 }
20225
20227 {
20228 for (auto it = this->begin(); it != this->end(); ++it)
20229 {
20230 if (m_compare(it->first, key))
20231 {
20232 return it;
20233 }
20234 }
20235 return Container::end();
20236 }
20237
20238 template<class KeyType, detail::enable_if_t<
20240 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
20241 {
20242 for (auto it = this->begin(); it != this->end(); ++it)
20243 {
20244 if (m_compare(it->first, key))
20245 {
20246 return it;
20247 }
20248 }
20249 return Container::end();
20250 }
20251
20252 const_iterator find(const key_type& key) const
20253 {
20254 for (auto it = this->begin(); it != this->end(); ++it)
20255 {
20256 if (m_compare(it->first, key))
20257 {
20258 return it;
20259 }
20260 }
20261 return Container::end();
20262 }
20263
20264 std::pair<iterator, bool> insert( value_type&& value )
20265 {
20266 return emplace(value.first, std::move(value.second));
20267 }
20268
20269 std::pair<iterator, bool> insert( const value_type& value )
20270 {
20271 for (auto it = this->begin(); it != this->end(); ++it)
20272 {
20273 if (m_compare(it->first, value.first))
20274 {
20275 return {it, false};
20276 }
20277 }
20278 Container::push_back(value);
20279 return {--this->end(), true};
20280 }
20281
20282 template<typename InputIt>
20283 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
20284 std::input_iterator_tag>::value>::type;
20285
20286 template<typename InputIt, typename = require_input_iter<InputIt>>
20287 void insert(InputIt first, InputIt last)
20288 {
20289 for (auto it = first; it != last; ++it)
20290 {
20291 insert(*it);
20292 }
20293 }
20294
20295private:
20297};
20298
20300
20301
20302#if defined(JSON_HAS_CPP_17)
20303 #if JSON_HAS_STATIC_RTTI
20304 #include <any>
20305 #endif
20306 #include <string_view>
20307#endif
20308
20315
20335class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
20336 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
20337{
20338 private:
20339 template<detail::value_t> friend struct detail::external_constructor;
20340
20341 template<typename>
20342 friend class ::nlohmann::json_pointer;
20343 // can be restored when json_pointer backwards compatibility is removed
20344 // friend ::nlohmann::json_pointer<StringType>;
20345
20346 template<typename BasicJsonType, typename InputType>
20347 friend class ::nlohmann::detail::parser;
20348 friend ::nlohmann::detail::serializer<basic_json>;
20349 template<typename BasicJsonType>
20350 friend class ::nlohmann::detail::iter_impl;
20351 template<typename BasicJsonType, typename CharType>
20352 friend class ::nlohmann::detail::binary_writer;
20353 template<typename BasicJsonType, typename InputType, typename SAX>
20354 friend class ::nlohmann::detail::binary_reader;
20355 template<typename BasicJsonType, typename InputAdapterType>
20356 friend class ::nlohmann::detail::json_sax_dom_parser;
20357 template<typename BasicJsonType, typename InputAdapterType>
20358 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
20359 friend class ::nlohmann::detail::exception;
20360
20363 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
20364
20366 // convenience aliases for types residing in namespace detail;
20367 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
20368
20369 template<typename InputAdapterType>
20370 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
20371 InputAdapterType adapter,
20373 const bool allow_exceptions = true,
20374 const bool ignore_comments = false,
20375 const bool ignore_trailing_commas = false
20376 )
20377 {
20378 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
20379 std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
20380 }
20381
20382 private:
20383 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
20384 template<typename BasicJsonType>
20385 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
20386 template<typename BasicJsonType>
20387 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
20388 template<typename Iterator>
20389 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
20390 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
20391
20392 template<typename CharType>
20393 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
20394
20395 template<typename InputType>
20396 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
20397 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
20398
20400 using serializer = ::nlohmann::detail::serializer<basic_json>;
20401
20402 public:
20405 using json_pointer = ::nlohmann::json_pointer<StringType>;
20406 template<typename T, typename SFINAE>
20407 using json_serializer = JSONSerializer<T, SFINAE>;
20415 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
20416
20420
20422 // exceptions //
20424
20428
20435
20437
20439 // container types //
20441
20446
20449
20454
20456 using difference_type = std::ptrdiff_t;
20458 using size_type = std::size_t;
20459
20461 using allocator_type = AllocatorType<basic_json>;
20462
20464 using pointer = typename std::allocator_traits<allocator_type>::pointer;
20466 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
20467
20476
20478
20482 {
20483 return allocator_type();
20484 }
20485
20490 {
20491 basic_json result;
20492
20493 result["copyright"] = "(C) 2013-2026 Niels Lohmann";
20494 result["name"] = "JSON for Modern C++";
20495 result["url"] = "https://github.com/nlohmann/json";
20496 result["version"]["string"] =
20497 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
20498 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
20499 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
20500 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
20501 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
20502 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
20503
20504#ifdef _WIN32
20505 result["platform"] = "win32";
20506#elif defined __linux__
20507 result["platform"] = "linux";
20508#elif defined __APPLE__
20509 result["platform"] = "apple";
20510#elif defined __unix__
20511 result["platform"] = "unix";
20512#else
20513 result["platform"] = "unknown";
20514#endif
20515
20516#if defined(__ICC) || defined(__INTEL_COMPILER)
20517 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
20518#elif defined(__clang__)
20519 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
20520#elif defined(__GNUC__) || defined(__GNUG__)
20521 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
20522 std::to_string(__GNUC__), '.',
20523 std::to_string(__GNUC_MINOR__), '.',
20524 std::to_string(__GNUC_PATCHLEVEL__))
20525 }
20526 };
20527#elif defined(__HP_cc) || defined(__HP_aCC)
20528 result["compiler"] = "hp"
20529#elif defined(__IBMCPP__)
20530 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
20531#elif defined(_MSC_VER)
20532 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
20533#elif defined(__PGI)
20534 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
20535#elif defined(__SUNPRO_CC)
20536 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
20537#else
20538 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
20539#endif
20540
20541#if defined(_MSVC_LANG)
20542 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
20543#elif defined(__cplusplus)
20544 result["compiler"]["c++"] = std::to_string(__cplusplus);
20545#else
20546 result["compiler"]["c++"] = "unknown";
20547#endif
20548 return result;
20549 }
20550
20552 // JSON value data types //
20554
20559
20564#if defined(JSON_HAS_CPP_14)
20565 // use of transparent comparator avoids unnecessary repeated construction of temporaries
20566 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
20567 using default_object_comparator_t = std::less<>;
20568#else
20569 using default_object_comparator_t = std::less<StringType>;
20570#endif
20571
20574 using object_t = ObjectType<StringType,
20575 basic_json,
20577 AllocatorType<std::pair<const StringType,
20578 basic_json>>>;
20579
20582 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
20583
20586 using string_t = StringType;
20587
20590 using boolean_t = BooleanType;
20591
20594 using number_integer_t = NumberIntegerType;
20595
20598 using number_unsigned_t = NumberUnsignedType;
20599
20602 using number_float_t = NumberFloatType;
20603
20606 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
20607
20611
20613
20614 private:
20615
20617 template<typename T, typename... Args>
20619 static T* create(Args&& ... args)
20620 {
20621 AllocatorType<T> alloc;
20622 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
20623
20624 auto deleter = [&](T * obj)
20625 {
20626 AllocatorTraits::deallocate(alloc, obj, 1);
20627 };
20628 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
20629 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
20630 JSON_ASSERT(obj != nullptr);
20631 return obj.release();
20632 }
20633
20635 // JSON value storage //
20637
20664 union json_value
20665 {
20667 object_t* object;
20682
20684 json_value() = default;
20686 json_value(boolean_t v) noexcept : boolean(v) {}
20688 json_value(number_integer_t v) noexcept : number_integer(v) {}
20690 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
20692 json_value(number_float_t v) noexcept : number_float(v) {}
20695 {
20696 switch (t)
20697 {
20698 case value_t::object:
20699 {
20700 object = create<object_t>();
20701 break;
20702 }
20703
20704 case value_t::array:
20705 {
20706 array = create<array_t>();
20707 break;
20708 }
20709
20710 case value_t::string:
20711 {
20712 string = create<string_t>("");
20713 break;
20714 }
20715
20716 case value_t::binary:
20717 {
20718 binary = create<binary_t>();
20719 break;
20720 }
20721
20722 case value_t::boolean:
20723 {
20724 boolean = static_cast<boolean_t>(false);
20725 break;
20726 }
20727
20728 case value_t::number_integer:
20729 {
20730 number_integer = static_cast<number_integer_t>(0);
20731 break;
20732 }
20733
20734 case value_t::number_unsigned:
20735 {
20736 number_unsigned = static_cast<number_unsigned_t>(0);
20737 break;
20738 }
20739
20740 case value_t::number_float:
20741 {
20742 number_float = static_cast<number_float_t>(0.0);
20743 break;
20744 }
20745
20746 case value_t::null:
20747 {
20748 object = nullptr; // silence warning, see #821
20749 break;
20750 }
20751
20752 case value_t::discarded:
20753 default:
20754 {
20755 object = nullptr; // silence warning, see #821
20756 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
20757 {
20758 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.12.0", nullptr)); // LCOV_EXCL_LINE
20759 }
20760 break;
20761 }
20762 }
20763 }
20764
20766 json_value(const string_t& value) : string(create<string_t>(value)) {}
20767
20769 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
20770
20772 json_value(const object_t& value) : object(create<object_t>(value)) {}
20773
20775 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
20776
20778 json_value(const array_t& value) : array(create<array_t>(value)) {}
20779
20781 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
20782
20784 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
20785
20787 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
20788
20790 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
20791
20793 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
20794
20796 {
20797 if (
20798 (t == value_t::object && object == nullptr) ||
20799 (t == value_t::array && array == nullptr) ||
20800 (t == value_t::string && string == nullptr) ||
20801 (t == value_t::binary && binary == nullptr)
20802 )
20803 {
20804 // not initialized (e.g., due to exception in the ctor)
20805 return;
20806 }
20807 if (t == value_t::array || t == value_t::object)
20808 {
20809 // flatten the current json_value to a heap-allocated stack
20810 std::vector<basic_json> stack;
20811
20812 // move the top-level items to stack
20813 if (t == value_t::array)
20814 {
20815 stack.reserve(array->size());
20816 std::move(array->begin(), array->end(), std::back_inserter(stack));
20817 }
20818 else
20819 {
20820 stack.reserve(object->size());
20821 for (auto&& it : *object)
20822 {
20823 stack.push_back(std::move(it.second));
20824 }
20825 }
20826
20827 while (!stack.empty())
20828 {
20829 // move the last item to a local variable to be processed
20830 basic_json current_item(std::move(stack.back()));
20831 stack.pop_back();
20832
20833 // if current_item is array/object, move
20834 // its children to the stack to be processed later
20835 if (current_item.is_array())
20836 {
20837 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
20838
20839 current_item.m_data.m_value.array->clear();
20840 }
20841 else if (current_item.is_object())
20842 {
20843 for (auto&& it : *current_item.m_data.m_value.object)
20844 {
20845 stack.push_back(std::move(it.second));
20846 }
20847
20848 current_item.m_data.m_value.object->clear();
20849 }
20850
20851 // it's now safe that current_item gets destructed
20852 // since it doesn't have any children
20853 }
20854 }
20855
20856 switch (t)
20857 {
20858 case value_t::object:
20859 {
20860 AllocatorType<object_t> alloc;
20861 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
20862 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
20863 break;
20864 }
20865
20866 case value_t::array:
20867 {
20868 AllocatorType<array_t> alloc;
20869 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
20870 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
20871 break;
20872 }
20873
20874 case value_t::string:
20875 {
20876 AllocatorType<string_t> alloc;
20877 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
20878 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
20879 break;
20880 }
20881
20882 case value_t::binary:
20883 {
20884 AllocatorType<binary_t> alloc;
20885 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
20886 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
20887 break;
20888 }
20889
20890 case value_t::null:
20891 case value_t::boolean:
20892 case value_t::number_integer:
20893 case value_t::number_unsigned:
20894 case value_t::number_float:
20895 case value_t::discarded:
20896 default:
20897 {
20898 break;
20899 }
20900 }
20901 }
20902 };
20903
20904 private:
20923 void assert_invariant(bool check_parents = true) const noexcept
20924 {
20925 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20926 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20927 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20928 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20929
20930#if JSON_DIAGNOSTICS
20931 JSON_TRY
20932 {
20933 // cppcheck-suppress assertWithSideEffect
20934 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20935 {
20936 return j.m_parent == this;
20937 }));
20938 }
20939 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20940#endif
20941 static_cast<void>(check_parents);
20942 }
20943
20945 {
20946#if JSON_DIAGNOSTICS
20947 switch (m_data.m_type)
20948 {
20949 case value_t::array:
20950 {
20951 for (auto& element : *m_data.m_value.array)
20952 {
20953 element.m_parent = this;
20954 }
20955 break;
20956 }
20957
20958 case value_t::object:
20959 {
20960 for (auto& element : *m_data.m_value.object)
20961 {
20962 element.second.m_parent = this;
20963 }
20964 break;
20965 }
20966
20967 case value_t::null:
20968 case value_t::string:
20969 case value_t::boolean:
20970 case value_t::number_integer:
20971 case value_t::number_unsigned:
20972 case value_t::number_float:
20973 case value_t::binary:
20974 case value_t::discarded:
20975 default:
20976 break;
20977 }
20978#endif
20979 }
20980
20981 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20982 {
20983#if JSON_DIAGNOSTICS
20984 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20985 {
20986 (it + i)->m_parent = this;
20987 }
20988#else
20989 static_cast<void>(count_set_parents);
20990#endif
20991 return it;
20992 }
20993
20994 reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size())
20995 {
20996#if JSON_DIAGNOSTICS
20997 if (old_capacity != detail::unknown_size())
20998 {
20999 // see https://github.com/nlohmann/json/issues/2838
21000 JSON_ASSERT(type() == value_t::array);
21001 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
21002 {
21003 // capacity has changed: update all parents
21004 set_parents();
21005 return j;
21006 }
21007 }
21008
21009 // ordered_json uses a vector internally, so pointers could have
21010 // been invalidated; see https://github.com/nlohmann/json/issues/2962
21011#ifdef JSON_HEDLEY_MSVC_VERSION
21012#pragma warning(push )
21013#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
21014#endif
21016 {
21017 set_parents();
21018 return j;
21019 }
21020#ifdef JSON_HEDLEY_MSVC_VERSION
21021#pragma warning( pop )
21022#endif
21023
21024 j.m_parent = this;
21025#else
21026 static_cast<void>(j);
21027 static_cast<void>(old_capacity);
21028#endif
21029 return j;
21030 }
21031
21032 public:
21034 // JSON parser callback //
21036
21040
21044
21046 // constructors //
21048
21053
21057 : m_data(v)
21058 {
21059 assert_invariant();
21060 }
21061
21064 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
21065 : basic_json(value_t::null)
21066 {
21067 assert_invariant();
21068 }
21069
21072 template < typename CompatibleType,
21076 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
21077 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
21078 std::forward<CompatibleType>(val))))
21079 {
21080 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
21081 set_parents();
21082 assert_invariant();
21083 }
21084
21087 template < typename BasicJsonType,
21089 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
21090 basic_json(const BasicJsonType& val)
21091#if JSON_DIAGNOSTIC_POSITIONS
21092 : start_position(val.start_pos()),
21093 end_position(val.end_pos())
21094#endif
21095 {
21096 using other_boolean_t = typename BasicJsonType::boolean_t;
21097 using other_number_float_t = typename BasicJsonType::number_float_t;
21098 using other_number_integer_t = typename BasicJsonType::number_integer_t;
21099 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
21100 using other_string_t = typename BasicJsonType::string_t;
21101 using other_object_t = typename BasicJsonType::object_t;
21102 using other_array_t = typename BasicJsonType::array_t;
21103 using other_binary_t = typename BasicJsonType::binary_t;
21104
21105 switch (val.type())
21106 {
21107 case value_t::boolean:
21108 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
21109 break;
21110 case value_t::number_float:
21111 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
21112 break;
21113 case value_t::number_integer:
21114 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
21115 break;
21116 case value_t::number_unsigned:
21117 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
21118 break;
21119 case value_t::string:
21120 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
21121 break;
21122 case value_t::object:
21123 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
21124 break;
21125 case value_t::array:
21126 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
21127 break;
21128 case value_t::binary:
21129 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
21130 break;
21131 case value_t::null:
21132 *this = nullptr;
21133 break;
21134 case value_t::discarded:
21135 m_data.m_type = value_t::discarded;
21136 break;
21137 default: // LCOV_EXCL_LINE
21138 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
21139 }
21140 JSON_ASSERT(m_data.m_type == val.type());
21141
21142 set_parents();
21143 assert_invariant();
21144 }
21145
21149 bool type_deduction = true,
21150 value_t manual_type = value_t::array)
21151 {
21152 // check if each element is an array with two elements whose first
21153 // element is a string
21154 bool is_an_object = std::all_of(init.begin(), init.end(),
21155 [](const detail::json_ref<basic_json>& element_ref)
21156 {
21157 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
21158 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
21159 // broken call to op[key_type], the wrong semantics, and a 4804 warning on Windows)
21160 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
21161 });
21162
21163 // adjust type if type deduction is not wanted
21164 if (!type_deduction)
21165 {
21166 // if an array is wanted, do not create an object though possible
21167 if (manual_type == value_t::array)
21168 {
21169 is_an_object = false;
21170 }
21171
21172 // if an object is wanted but impossible, throw an exception
21173 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
21174 {
21175 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
21176 }
21177 }
21178
21179 if (is_an_object)
21180 {
21181 // the initializer list is a list of pairs -> create an object
21182 m_data.m_type = value_t::object;
21183 m_data.m_value = value_t::object;
21184
21185 for (auto& element_ref : init)
21186 {
21187 auto element = element_ref.moved_or_copied();
21188 m_data.m_value.object->emplace(
21189 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
21190 std::move((*element.m_data.m_value.array)[1]));
21191 }
21192 }
21193 else
21194 {
21195 // the initializer list describes an array -> create an array
21196 m_data.m_type = value_t::array;
21197 m_data.m_value.array = create<array_t>(init.begin(), init.end());
21198 }
21199
21200 set_parents();
21201 assert_invariant();
21202 }
21203
21207 static basic_json binary(const typename binary_t::container_type& init)
21208 {
21209 auto res = basic_json();
21210 res.m_data.m_type = value_t::binary;
21211 res.m_data.m_value = init;
21212 return res;
21213 }
21214
21218 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
21219 {
21220 auto res = basic_json();
21221 res.m_data.m_type = value_t::binary;
21222 res.m_data.m_value = binary_t(init, subtype);
21223 return res;
21224 }
21225
21229 static basic_json binary(typename binary_t::container_type&& init)
21230 {
21231 auto res = basic_json();
21232 res.m_data.m_type = value_t::binary;
21233 res.m_data.m_value = std::move(init);
21234 return res;
21235 }
21236
21240 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
21241 {
21242 auto res = basic_json();
21243 res.m_data.m_type = value_t::binary;
21244 res.m_data.m_value = binary_t(std::move(init), subtype);
21245 return res;
21246 }
21247
21252 {
21253 return basic_json(init, false, value_t::array);
21254 }
21255
21260 {
21261 return basic_json(init, false, value_t::object);
21262 }
21263
21267 m_data{cnt, val}
21268 {
21269 set_parents();
21270 assert_invariant();
21271 }
21272
21275 template < class InputIT, typename std::enable_if <
21276 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
21277 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
21278 basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
21279 {
21280 JSON_ASSERT(first.m_object != nullptr);
21281 JSON_ASSERT(last.m_object != nullptr);
21282
21283 // make sure the iterator fits the current value
21284 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
21285 {
21286 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
21287 }
21288
21289 // copy type from the first iterator
21290 m_data.m_type = first.m_object->m_data.m_type;
21291
21292 // check if the iterator range is complete for primitive values
21293 switch (m_data.m_type)
21294 {
21295 case value_t::boolean:
21296 case value_t::number_float:
21297 case value_t::number_integer:
21298 case value_t::number_unsigned:
21299 case value_t::string:
21300 {
21301 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
21302 || !last.m_it.primitive_iterator.is_end()))
21303 {
21304 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
21305 }
21306 break;
21307 }
21308
21309 case value_t::null:
21310 case value_t::object:
21311 case value_t::array:
21312 case value_t::binary:
21313 case value_t::discarded:
21314 default:
21315 break;
21316 }
21317
21318 switch (m_data.m_type)
21319 {
21320 case value_t::number_integer:
21321 {
21322 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
21323 break;
21324 }
21325
21326 case value_t::number_unsigned:
21327 {
21328 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
21329 break;
21330 }
21331
21332 case value_t::number_float:
21333 {
21334 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
21335 break;
21336 }
21337
21338 case value_t::boolean:
21339 {
21340 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
21341 break;
21342 }
21343
21344 case value_t::string:
21345 {
21346 m_data.m_value = *first.m_object->m_data.m_value.string;
21347 break;
21348 }
21349
21350 case value_t::object:
21351 {
21352 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
21353 last.m_it.object_iterator);
21354 break;
21355 }
21356
21357 case value_t::array:
21358 {
21359 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
21360 last.m_it.array_iterator);
21361 break;
21362 }
21363
21364 case value_t::binary:
21365 {
21366 m_data.m_value = *first.m_object->m_data.m_value.binary;
21367 break;
21368 }
21369
21370 case value_t::null:
21371 case value_t::discarded:
21372 default:
21373 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
21374 }
21375
21376 set_parents();
21377 assert_invariant();
21378 }
21379
21381 // other constructors and destructor //
21383
21384 template<typename JsonRef,
21386 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
21387 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
21388
21392 : json_base_class_t(other)
21394 , start_position(other.start_position)
21395 , end_position(other.end_position)
21396#endif
21397 {
21398 m_data.m_type = other.m_data.m_type;
21399 // check of passed value is valid
21400 other.assert_invariant();
21401
21402 switch (m_data.m_type)
21403 {
21404 case value_t::object:
21405 {
21406 m_data.m_value = *other.m_data.m_value.object;
21407 break;
21408 }
21409
21410 case value_t::array:
21411 {
21412 m_data.m_value = *other.m_data.m_value.array;
21413 break;
21414 }
21415
21416 case value_t::string:
21417 {
21418 m_data.m_value = *other.m_data.m_value.string;
21419 break;
21420 }
21421
21422 case value_t::boolean:
21423 {
21424 m_data.m_value = other.m_data.m_value.boolean;
21425 break;
21426 }
21427
21428 case value_t::number_integer:
21429 {
21430 m_data.m_value = other.m_data.m_value.number_integer;
21431 break;
21432 }
21433
21434 case value_t::number_unsigned:
21435 {
21436 m_data.m_value = other.m_data.m_value.number_unsigned;
21437 break;
21438 }
21439
21440 case value_t::number_float:
21441 {
21442 m_data.m_value = other.m_data.m_value.number_float;
21443 break;
21444 }
21445
21446 case value_t::binary:
21447 {
21448 m_data.m_value = *other.m_data.m_value.binary;
21449 break;
21450 }
21451
21452 case value_t::null:
21453 case value_t::discarded:
21454 default:
21455 break;
21456 }
21457
21458 set_parents();
21459 assert_invariant();
21460 }
21461
21464 basic_json(basic_json&& other) noexcept
21465 : json_base_class_t(std::forward<json_base_class_t>(other)),
21466 m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
21467#if JSON_DIAGNOSTIC_POSITIONS
21468 , start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
21469 , end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
21470#endif
21471 {
21472 // check that the passed value is valid
21473 other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
21474
21475 // invalidate payload
21476 other.m_data.m_type = value_t::null;
21477 other.m_data.m_value = {};
21478
21479#if JSON_DIAGNOSTIC_POSITIONS
21480 other.start_position = std::string::npos;
21481 other.end_position = std::string::npos;
21482#endif
21483
21484 set_parents();
21485 assert_invariant();
21486 }
21487
21490 basic_json& operator=(basic_json other) noexcept ( // NOLINT(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator)
21491 std::is_nothrow_move_constructible<value_t>::value&&
21492 std::is_nothrow_move_assignable<value_t>::value&&
21493 std::is_nothrow_move_constructible<json_value>::value&&
21494 std::is_nothrow_move_assignable<json_value>::value&&
21495 std::is_nothrow_move_assignable<json_base_class_t>::value
21496 )
21497 {
21498 // check that the passed value is valid
21499 other.assert_invariant();
21500
21501 using std::swap;
21502 swap(m_data.m_type, other.m_data.m_type);
21503 swap(m_data.m_value, other.m_data.m_value);
21504
21505#if JSON_DIAGNOSTIC_POSITIONS
21506 swap(start_position, other.start_position);
21507 swap(end_position, other.end_position);
21508#endif
21509
21510 json_base_class_t::operator=(std::move(other));
21511
21512 set_parents();
21513 assert_invariant();
21514 return *this;
21515 }
21516
21519 ~basic_json() noexcept
21520 {
21521 assert_invariant(false);
21522 }
21523
21525
21526 public:
21528 // object inspection //
21530
21534
21537 string_t dump(const int indent = -1,
21538 const char indent_char = ' ',
21539 const bool ensure_ascii = false,
21540 const error_handler_t error_handler = error_handler_t::strict) const
21541 {
21542 string_t result;
21543 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
21544
21545 if (indent >= 0)
21546 {
21547 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
21548 }
21549 else
21550 {
21551 s.dump(*this, false, ensure_ascii, 0);
21552 }
21553
21554 return result;
21555 }
21556
21559 constexpr value_t type() const noexcept
21560 {
21561 return m_data.m_type;
21562 }
21563
21566 constexpr bool is_primitive() const noexcept
21567 {
21568 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
21569 }
21570
21573 constexpr bool is_structured() const noexcept
21574 {
21575 return is_array() || is_object();
21576 }
21577
21580 constexpr bool is_null() const noexcept
21581 {
21582 return m_data.m_type == value_t::null;
21583 }
21584
21587 constexpr bool is_boolean() const noexcept
21588 {
21589 return m_data.m_type == value_t::boolean;
21590 }
21591
21594 constexpr bool is_number() const noexcept
21595 {
21596 return is_number_integer() || is_number_float();
21597 }
21598
21601 constexpr bool is_number_integer() const noexcept
21602 {
21603 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
21604 }
21605
21608 constexpr bool is_number_unsigned() const noexcept
21609 {
21610 return m_data.m_type == value_t::number_unsigned;
21611 }
21612
21615 constexpr bool is_number_float() const noexcept
21616 {
21617 return m_data.m_type == value_t::number_float;
21618 }
21619
21622 constexpr bool is_object() const noexcept
21623 {
21624 return m_data.m_type == value_t::object;
21625 }
21626
21629 constexpr bool is_array() const noexcept
21630 {
21631 return m_data.m_type == value_t::array;
21632 }
21633
21636 constexpr bool is_string() const noexcept
21637 {
21638 return m_data.m_type == value_t::string;
21639 }
21640
21643 constexpr bool is_binary() const noexcept
21644 {
21645 return m_data.m_type == value_t::binary;
21646 }
21647
21650 constexpr bool is_discarded() const noexcept
21651 {
21652 return m_data.m_type == value_t::discarded;
21653 }
21654
21657 constexpr operator value_t() const noexcept
21658 {
21659 return m_data.m_type;
21660 }
21661
21663
21664 private:
21666 // value access //
21668
21670 boolean_t get_impl(boolean_t* /*unused*/) const
21671 {
21672 if (JSON_HEDLEY_LIKELY(is_boolean()))
21673 {
21674 return m_data.m_value.boolean;
21675 }
21676
21677 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
21678 }
21679
21681 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
21682 {
21683 return is_object() ? m_data.m_value.object : nullptr;
21684 }
21685
21687 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
21688 {
21689 return is_object() ? m_data.m_value.object : nullptr;
21690 }
21691
21693 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
21694 {
21695 return is_array() ? m_data.m_value.array : nullptr;
21696 }
21697
21699 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
21700 {
21701 return is_array() ? m_data.m_value.array : nullptr;
21702 }
21703
21705 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
21706 {
21707 return is_string() ? m_data.m_value.string : nullptr;
21708 }
21709
21711 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
21712 {
21713 return is_string() ? m_data.m_value.string : nullptr;
21714 }
21715
21717 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
21718 {
21719 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21720 }
21721
21723 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
21724 {
21725 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21726 }
21727
21730 {
21731 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21732 }
21733
21735 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
21736 {
21737 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21738 }
21739
21742 {
21743 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21744 }
21745
21747 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
21748 {
21749 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21750 }
21751
21754 {
21755 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21756 }
21757
21759 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
21760 {
21761 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21762 }
21763
21765 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
21766 {
21767 return is_binary() ? m_data.m_value.binary : nullptr;
21768 }
21769
21771 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
21772 {
21773 return is_binary() ? m_data.m_value.binary : nullptr;
21774 }
21775
21787 template<typename ReferenceType, typename ThisType>
21788 static ReferenceType get_ref_impl(ThisType& obj)
21789 {
21790 // delegate the call to get_ptr<>()
21791 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
21792
21793 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
21794 {
21795 return *ptr;
21796 }
21797
21798 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
21799 }
21800
21801 public:
21805
21808 template<typename PointerType, typename std::enable_if<
21809 std::is_pointer<PointerType>::value, int>::type = 0>
21810 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21811 {
21812 // delegate the call to get_impl_ptr<>()
21813 return get_impl_ptr(static_cast<PointerType>(nullptr));
21814 }
21815
21818 template < typename PointerType, typename std::enable_if <
21819 std::is_pointer<PointerType>::value&&
21820 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
21821 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21822 {
21823 // delegate the call to get_impl_ptr<>() const
21824 return get_impl_ptr(static_cast<PointerType>(nullptr));
21825 }
21826
21827 private:
21866 template < typename ValueType,
21870 int > = 0 >
21871 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
21872 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
21873 {
21874 auto ret = ValueType();
21875 JSONSerializer<ValueType>::from_json(*this, ret);
21876 return ret;
21877 }
21878
21909 template < typename ValueType,
21912 int > = 0 >
21913 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
21914 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
21915 {
21916 return JSONSerializer<ValueType>::from_json(*this);
21917 }
21918
21934 template < typename BasicJsonType,
21937 int > = 0 >
21938 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
21939 {
21940 return *this;
21941 }
21942
21957 template<typename BasicJsonType,
21959 std::is_same<BasicJsonType, basic_json_t>::value,
21960 int> = 0>
21962 {
21963 return *this;
21964 }
21965
21970 template<typename PointerType,
21972 std::is_pointer<PointerType>::value,
21973 int> = 0>
21974 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21975 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21976 {
21977 // delegate the call to get_ptr
21978 return get_ptr<PointerType>();
21979 }
21980
21981 public:
22005 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
22006#if defined(JSON_HAS_CPP_14)
22007 constexpr
22008#endif
22009 auto get() const noexcept(
22010 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
22011 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
22012 {
22013 // we cannot static_assert on ValueTypeCV being non-const, because
22014 // there is support for get<const basic_json_t>(), which is why we
22015 // still need the uncvref
22016 static_assert(!std::is_reference<ValueTypeCV>::value,
22017 "get() cannot be used with reference types, you might want to use get_ref()");
22018 return get_impl<ValueType>(detail::priority_tag<4> {});
22019 }
22020
22048 template<typename PointerType, typename std::enable_if<
22049 std::is_pointer<PointerType>::value, int>::type = 0>
22050 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
22051 {
22052 // delegate the call to get_ptr
22053 return get_ptr<PointerType>();
22054 }
22055
22058 template < typename ValueType,
22062 int > = 0 >
22063 ValueType & get_to(ValueType& v) const noexcept(noexcept(
22064 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
22065 {
22066 JSONSerializer<ValueType>::from_json(*this, v);
22067 return v;
22068 }
22069
22070 // specialization to allow calling get_to with a basic_json value
22071 // see https://github.com/nlohmann/json/issues/2175
22072 template<typename ValueType,
22075 int> = 0>
22076 ValueType & get_to(ValueType& v) const
22077 {
22078 v = *this;
22079 return v;
22080 }
22081
22082 template <
22083 typename T, std::size_t N,
22084 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
22087 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
22088 noexcept(noexcept(JSONSerializer<Array>::from_json(
22089 std::declval<const basic_json_t&>(), v)))
22090 {
22091 JSONSerializer<Array>::from_json(*this, v);
22092 return v;
22093 }
22094
22097 template<typename ReferenceType, typename std::enable_if<
22098 std::is_reference<ReferenceType>::value, int>::type = 0>
22099 ReferenceType get_ref()
22100 {
22101 // delegate call to get_ref_impl
22102 return get_ref_impl<ReferenceType>(*this);
22103 }
22104
22107 template < typename ReferenceType, typename std::enable_if <
22108 std::is_reference<ReferenceType>::value&&
22109 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
22110 ReferenceType get_ref() const
22111 {
22112 // delegate call to get_ref_impl
22113 return get_ref_impl<ReferenceType>(*this);
22114 }
22115
22145 template < typename ValueType, typename std::enable_if <
22153#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
22155#endif
22156#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
22158#endif
22160 >::value, int >::type = 0 >
22161 JSON_EXPLICIT operator ValueType() const
22162 {
22163 // delegate the call to get<>() const
22164 return get<ValueType>();
22165 }
22166
22170 {
22171 if (!is_binary())
22172 {
22173 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
22174 }
22175
22176 return *get_ptr<binary_t*>();
22177 }
22178
22181 const binary_t& get_binary() const
22182 {
22183 if (!is_binary())
22184 {
22185 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
22186 }
22187
22188 return *get_ptr<const binary_t*>();
22189 }
22190
22192
22194 // element access //
22196
22200
22204 {
22205 // at only works for arrays
22206 if (JSON_HEDLEY_LIKELY(is_array()))
22207 {
22208 JSON_TRY
22209 {
22210 return set_parent(m_data.m_value.array->at(idx));
22211 }
22212 JSON_CATCH (std::out_of_range&)
22213 {
22214 // create a better exception explanation
22215 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22216 } // cppcheck-suppress[missingReturn]
22217 }
22218 else
22219 {
22220 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22221 }
22222 }
22223
22227 {
22228 // at only works for arrays
22229 if (JSON_HEDLEY_LIKELY(is_array()))
22230 {
22231 JSON_TRY
22232 {
22233 return m_data.m_value.array->at(idx);
22234 }
22235 JSON_CATCH (std::out_of_range&)
22236 {
22237 // create a better exception explanation
22238 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22239 } // cppcheck-suppress[missingReturn]
22240 }
22241 else
22242 {
22243 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22244 }
22245 }
22246
22249 reference at(const typename object_t::key_type& key)
22250 {
22251 // at only works for objects
22252 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22253 {
22254 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22255 }
22256
22257 auto it = m_data.m_value.object->find(key);
22258 if (it == m_data.m_value.object->end())
22259 {
22260 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22261 }
22262 return set_parent(it->second);
22263 }
22264
22267 template<class KeyType, detail::enable_if_t<
22269 reference at(KeyType && key)
22270 {
22271 // at only works for objects
22272 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22273 {
22274 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22275 }
22276
22277 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22278 if (it == m_data.m_value.object->end())
22279 {
22280 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22281 }
22282 return set_parent(it->second);
22283 }
22284
22287 const_reference at(const typename object_t::key_type& key) const
22288 {
22289 // at only works for objects
22290 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22291 {
22292 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22293 }
22294
22295 auto it = m_data.m_value.object->find(key);
22296 if (it == m_data.m_value.object->end())
22297 {
22298 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22299 }
22300 return it->second;
22301 }
22302
22305 template<class KeyType, detail::enable_if_t<
22307 const_reference at(KeyType && key) const
22308 {
22309 // at only works for objects
22310 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22311 {
22312 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22313 }
22314
22315 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22316 if (it == m_data.m_value.object->end())
22317 {
22318 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22319 }
22320 return it->second;
22321 }
22322
22326 {
22327 // implicitly convert a null value to an empty array
22328 if (is_null())
22329 {
22330 m_data.m_type = value_t::array;
22331 m_data.m_value.array = create<array_t>();
22332 assert_invariant();
22333 }
22334
22335 // operator[] only works for arrays
22336 if (JSON_HEDLEY_LIKELY(is_array()))
22337 {
22338 // fill up the array with null values if given idx is outside the range
22339 if (idx >= m_data.m_value.array->size())
22340 {
22341#if JSON_DIAGNOSTICS
22342 // remember array size & capacity before resizing
22343 const auto old_size = m_data.m_value.array->size();
22344 const auto old_capacity = m_data.m_value.array->capacity();
22345#endif
22346 m_data.m_value.array->resize(idx + 1);
22347
22348#if JSON_DIAGNOSTICS
22349 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
22350 {
22351 // capacity has changed: update all parents
22352 set_parents();
22353 }
22354 else
22355 {
22356 // set parent for values added above
22357 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
22358 }
22359#endif
22360 assert_invariant();
22361 }
22362
22363 return m_data.m_value.array->operator[](idx);
22364 }
22365
22366 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22367 }
22368
22372 {
22373 // const operator[] only works for arrays
22374 if (JSON_HEDLEY_LIKELY(is_array()))
22375 {
22376 return m_data.m_value.array->operator[](idx);
22377 }
22378
22379 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22380 }
22381
22384 reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
22385 {
22386 // implicitly convert a null value to an empty object
22387 if (is_null())
22388 {
22389 m_data.m_type = value_t::object;
22390 m_data.m_value.object = create<object_t>();
22391 assert_invariant();
22392 }
22393
22394 // operator[] only works for objects
22395 if (JSON_HEDLEY_LIKELY(is_object()))
22396 {
22397 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
22398 return set_parent(result.first->second);
22399 }
22400
22401 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22402 }
22403
22406 const_reference operator[](const typename object_t::key_type& key) const
22407 {
22408 // const operator[] only works for objects
22409 if (JSON_HEDLEY_LIKELY(is_object()))
22410 {
22411 auto it = m_data.m_value.object->find(key);
22412 JSON_ASSERT(it != m_data.m_value.object->end());
22413 return it->second;
22414 }
22415
22416 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22417 }
22418
22419 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
22420 // (they seemingly cannot be constrained to resolve the ambiguity)
22421 template<typename T>
22423 {
22424 return operator[](typename object_t::key_type(key));
22425 }
22426
22427 template<typename T>
22429 {
22430 return operator[](typename object_t::key_type(key));
22431 }
22432
22435 template<class KeyType, detail::enable_if_t<
22437 reference operator[](KeyType && key)
22438 {
22439 // implicitly convert a null value to an empty object
22440 if (is_null())
22441 {
22442 m_data.m_type = value_t::object;
22443 m_data.m_value.object = create<object_t>();
22444 assert_invariant();
22445 }
22446
22447 // operator[] only works for objects
22448 if (JSON_HEDLEY_LIKELY(is_object()))
22449 {
22450 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
22451 return set_parent(result.first->second);
22452 }
22453
22454 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22455 }
22456
22459 template<class KeyType, detail::enable_if_t<
22461 const_reference operator[](KeyType && key) const
22462 {
22463 // const operator[] only works for objects
22464 if (JSON_HEDLEY_LIKELY(is_object()))
22465 {
22466 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22467 JSON_ASSERT(it != m_data.m_value.object->end());
22468 return it->second;
22469 }
22470
22471 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22472 }
22473
22474 private:
22475 template<typename KeyType>
22477 object_comparator_t, const typename object_t::key_type&, KeyType >;
22478
22479 template<typename ValueType>
22480 using value_return_type = std::conditional <
22482 string_t, typename std::decay<ValueType>::type >;
22483
22484 public:
22487 template < class ValueType, detail::enable_if_t <
22490 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22491 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
22492 {
22493 // value only works for objects
22494 if (JSON_HEDLEY_LIKELY(is_object()))
22495 {
22496 // If 'key' is found, return its value. Otherwise, return `default_value'.
22497 const auto it = find(key);
22498 if (it != end())
22499 {
22500 return it->template get<ValueType>();
22501 }
22502
22503 return default_value;
22504 }
22505
22506 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22507 }
22508
22511 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22515 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22516 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
22517 {
22518 // value only works for objects
22519 if (JSON_HEDLEY_LIKELY(is_object()))
22520 {
22521 // If 'key' is found, return its value. Otherwise, return `default_value'.
22522 const auto it = find(key);
22523 if (it != end())
22524 {
22525 return it->template get<ReturnType>();
22526 }
22527
22528 return std::forward<ValueType>(default_value);
22529 }
22530
22531 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22532 }
22533
22536 template < class ValueType, class KeyType, detail::enable_if_t <
22539 && is_comparable_with_object_key<KeyType>::value
22541 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22542 ValueType value(KeyType && key, const ValueType& default_value) const
22543 {
22544 // value only works for objects
22545 if (JSON_HEDLEY_LIKELY(is_object()))
22546 {
22547 // If 'key' is found, return its value. Otherwise, return `default_value'.
22548 const auto it = find(std::forward<KeyType>(key));
22549 if (it != end())
22550 {
22551 return it->template get<ValueType>();
22552 }
22553
22554 return default_value;
22555 }
22556
22557 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22558 }
22559
22562 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
22566 && is_comparable_with_object_key<KeyType>::value
22568 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22569 ReturnType value(KeyType && key, ValueType && default_value) const
22570 {
22571 // value only works for objects
22572 if (JSON_HEDLEY_LIKELY(is_object()))
22573 {
22574 // If 'key' is found, return its value. Otherwise, return `default_value'.
22575 const auto it = find(std::forward<KeyType>(key));
22576 if (it != end())
22577 {
22578 return it->template get<ReturnType>();
22579 }
22580
22581 return std::forward<ValueType>(default_value);
22582 }
22583
22584 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22585 }
22586
22589 template < class ValueType, detail::enable_if_t <
22591 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22592 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
22593 {
22594 // value only works for objects
22595 if (JSON_HEDLEY_LIKELY(is_object()))
22596 {
22597 // If the pointer resolves to a value, return it. Otherwise, return
22598 // 'default_value'.
22599 JSON_TRY
22600 {
22601 return ptr.get_checked(this).template get<ValueType>();
22602 }
22604 {
22605 return default_value;
22606 }
22607 }
22608
22609 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22610 }
22611
22614 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22617 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22618 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
22619 {
22620 // value only works for objects
22621 if (JSON_HEDLEY_LIKELY(is_object()))
22622 {
22623 // If the pointer resolves to a value, return it. Otherwise, return
22624 // 'default_value'.
22625 JSON_TRY
22626 {
22627 return ptr.get_checked(this).template get<ReturnType>();
22628 }
22630 {
22631 return std::forward<ValueType>(default_value);
22632 }
22633 }
22634
22635 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22636 }
22637
22638 template < class ValueType, class BasicJsonType, detail::enable_if_t <
22641 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22642 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22643 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
22644 {
22645 return value(ptr.convert(), default_value);
22646 }
22647
22648 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
22652 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22653 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22654 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
22655 {
22656 return value(ptr.convert(), std::forward<ValueType>(default_value));
22657 }
22658
22662 {
22663 return *begin();
22664 }
22665
22669 {
22670 return *cbegin();
22671 }
22672
22676 {
22677 auto tmp = end();
22678 --tmp;
22679 return *tmp;
22680 }
22681
22685 {
22686 auto tmp = cend();
22687 --tmp;
22688 return *tmp;
22689 }
22690
22693 template < class IteratorType, detail::enable_if_t <
22694 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22695 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22696 IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
22697 {
22698 // make sure the iterator fits the current value
22699 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
22700 {
22701 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22702 }
22703
22704 IteratorType result = end();
22705
22706 switch (m_data.m_type)
22707 {
22708 case value_t::boolean:
22709 case value_t::number_float:
22710 case value_t::number_integer:
22711 case value_t::number_unsigned:
22712 case value_t::string:
22713 case value_t::binary:
22714 {
22715 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
22716 {
22717 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
22718 }
22719
22720 if (is_string())
22721 {
22722 AllocatorType<string_t> alloc;
22723 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22724 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22725 m_data.m_value.string = nullptr;
22726 }
22727 else if (is_binary())
22728 {
22729 AllocatorType<binary_t> alloc;
22730 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22731 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22732 m_data.m_value.binary = nullptr;
22733 }
22734
22735 m_data.m_type = value_t::null;
22736 assert_invariant();
22737 break;
22738 }
22739
22740 case value_t::object:
22741 {
22742 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
22743 break;
22744 }
22745
22746 case value_t::array:
22747 {
22748 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
22749 break;
22750 }
22751
22752 case value_t::null:
22753 case value_t::discarded:
22754 default:
22755 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22756 }
22757
22758 return result;
22759 }
22760
22763 template < class IteratorType, detail::enable_if_t <
22764 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22765 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22766 IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
22767 {
22768 // make sure the iterator fits the current value
22769 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
22770 {
22771 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
22772 }
22773
22774 IteratorType result = end();
22775
22776 switch (m_data.m_type)
22777 {
22778 case value_t::boolean:
22779 case value_t::number_float:
22780 case value_t::number_integer:
22781 case value_t::number_unsigned:
22782 case value_t::string:
22783 case value_t::binary:
22784 {
22785 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
22786 || !last.m_it.primitive_iterator.is_end()))
22787 {
22788 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
22789 }
22790
22791 if (is_string())
22792 {
22793 AllocatorType<string_t> alloc;
22794 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22795 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22796 m_data.m_value.string = nullptr;
22797 }
22798 else if (is_binary())
22799 {
22800 AllocatorType<binary_t> alloc;
22801 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22802 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22803 m_data.m_value.binary = nullptr;
22804 }
22805
22806 m_data.m_type = value_t::null;
22807 assert_invariant();
22808 break;
22809 }
22810
22811 case value_t::object:
22812 {
22813 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
22814 last.m_it.object_iterator);
22815 break;
22816 }
22817
22818 case value_t::array:
22819 {
22820 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
22821 last.m_it.array_iterator);
22822 break;
22823 }
22824
22825 case value_t::null:
22826 case value_t::discarded:
22827 default:
22828 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22829 }
22830
22831 return result;
22832 }
22833
22834 private:
22835 template < typename KeyType, detail::enable_if_t <
22838 {
22839 // this erase only works for objects
22840 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22841 {
22842 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22843 }
22844
22845 return m_data.m_value.object->erase(std::forward<KeyType>(key));
22846 }
22847
22848 template < typename KeyType, detail::enable_if_t <
22851 {
22852 // this erase only works for objects
22853 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22854 {
22855 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22856 }
22857
22858 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22859 if (it != m_data.m_value.object->end())
22860 {
22861 m_data.m_value.object->erase(it);
22862 return 1;
22863 }
22864 return 0;
22865 }
22866
22867 public:
22868
22871 size_type erase(const typename object_t::key_type& key)
22872 {
22873 // the indirection via erase_internal() is added to avoid making this
22874 // function a template and thus de-rank it during overload resolution
22875 return erase_internal(key);
22876 }
22877
22880 template<class KeyType, detail::enable_if_t<
22882 size_type erase(KeyType && key)
22883 {
22884 return erase_internal(std::forward<KeyType>(key));
22885 }
22886
22889 void erase(const size_type idx)
22890 {
22891 // this erase only works for arrays
22892 if (JSON_HEDLEY_LIKELY(is_array()))
22893 {
22894 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
22895 {
22896 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22897 }
22898
22899 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
22900 }
22901 else
22902 {
22903 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22904 }
22905 }
22906
22908
22910 // lookup //
22912
22915
22918 iterator find(const typename object_t::key_type& key)
22919 {
22920 auto result = end();
22921
22922 if (is_object())
22923 {
22924 result.m_it.object_iterator = m_data.m_value.object->find(key);
22925 }
22926
22927 return result;
22928 }
22929
22932 const_iterator find(const typename object_t::key_type& key) const
22933 {
22934 auto result = cend();
22935
22936 if (is_object())
22937 {
22938 result.m_it.object_iterator = m_data.m_value.object->find(key);
22939 }
22940
22941 return result;
22942 }
22943
22946 template<class KeyType, detail::enable_if_t<
22948 iterator find(KeyType && key)
22949 {
22950 auto result = end();
22951
22952 if (is_object())
22953 {
22954 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22955 }
22956
22957 return result;
22958 }
22959
22962 template<class KeyType, detail::enable_if_t<
22964 const_iterator find(KeyType && key) const
22965 {
22966 auto result = cend();
22967
22968 if (is_object())
22969 {
22970 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22971 }
22972
22973 return result;
22974 }
22975
22978 size_type count(const typename object_t::key_type& key) const
22979 {
22980 // return 0 for all nonobject types
22981 return is_object() ? m_data.m_value.object->count(key) : 0;
22982 }
22983
22986 template<class KeyType, detail::enable_if_t<
22988 size_type count(KeyType && key) const
22989 {
22990 // return 0 for all nonobject types
22991 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22992 }
22993
22996 bool contains(const typename object_t::key_type& key) const
22997 {
22998 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22999 }
23000
23003 template<class KeyType, detail::enable_if_t<
23005 bool contains(KeyType && key) const
23006 {
23007 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
23008 }
23009
23012 bool contains(const json_pointer& ptr) const
23013 {
23014 return ptr.contains(this);
23015 }
23016
23017 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23018 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23019 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23020 {
23021 return ptr.contains(this);
23022 }
23023
23025
23027 // iterators //
23029
23032
23035 iterator begin() noexcept
23036 {
23037 iterator result(this);
23038 result.set_begin();
23039 return result;
23040 }
23041
23044 const_iterator begin() const noexcept
23045 {
23046 return cbegin();
23047 }
23048
23051 const_iterator cbegin() const noexcept
23052 {
23053 const_iterator result(this);
23054 result.set_begin();
23055 return result;
23056 }
23057
23060 iterator end() noexcept
23061 {
23062 iterator result(this);
23063 result.set_end();
23064 return result;
23065 }
23066
23069 const_iterator end() const noexcept
23070 {
23071 return cend();
23072 }
23073
23076 const_iterator cend() const noexcept
23077 {
23078 const_iterator result(this);
23079 result.set_end();
23080 return result;
23081 }
23082
23086 {
23087 return reverse_iterator(end());
23088 }
23089
23093 {
23094 return crbegin();
23095 }
23096
23100 {
23101 return reverse_iterator(begin());
23102 }
23103
23107 {
23108 return crend();
23109 }
23110
23114 {
23115 return const_reverse_iterator(cend());
23116 }
23117
23121 {
23122 return const_reverse_iterator(cbegin());
23123 }
23124
23125 public:
23131 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
23132 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
23133 {
23134 return ref.items();
23135 }
23136
23142 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
23143 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
23144 {
23145 return ref.items();
23146 }
23147
23151 {
23152 return iteration_proxy<iterator>(*this);
23153 }
23154
23158 {
23159 return iteration_proxy<const_iterator>(*this);
23160 }
23161
23163
23165 // capacity //
23167
23170
23173 bool empty() const noexcept
23174 {
23175 switch (m_data.m_type)
23176 {
23177 case value_t::null:
23178 {
23179 // null values are empty
23180 return true;
23181 }
23182
23183 case value_t::array:
23184 {
23185 // delegate call to array_t::empty()
23186 return m_data.m_value.array->empty();
23187 }
23188
23189 case value_t::object:
23190 {
23191 // delegate call to object_t::empty()
23192 return m_data.m_value.object->empty();
23193 }
23194
23195 case value_t::string:
23196 case value_t::boolean:
23197 case value_t::number_integer:
23198 case value_t::number_unsigned:
23199 case value_t::number_float:
23200 case value_t::binary:
23201 case value_t::discarded:
23202 default:
23203 {
23204 // all other types are nonempty
23205 return false;
23206 }
23207 }
23208 }
23209
23212 size_type size() const noexcept
23213 {
23214 switch (m_data.m_type)
23215 {
23216 case value_t::null:
23217 {
23218 // null values are empty
23219 return 0;
23220 }
23221
23222 case value_t::array:
23223 {
23224 // delegate call to array_t::size()
23225 return m_data.m_value.array->size();
23226 }
23227
23228 case value_t::object:
23229 {
23230 // delegate call to object_t::size()
23231 return m_data.m_value.object->size();
23232 }
23233
23234 case value_t::string:
23235 case value_t::boolean:
23236 case value_t::number_integer:
23237 case value_t::number_unsigned:
23238 case value_t::number_float:
23239 case value_t::binary:
23240 case value_t::discarded:
23241 default:
23242 {
23243 // all other types have size 1
23244 return 1;
23245 }
23246 }
23247 }
23248
23251 size_type max_size() const noexcept
23252 {
23253 switch (m_data.m_type)
23254 {
23255 case value_t::array:
23256 {
23257 // delegate call to array_t::max_size()
23258 return m_data.m_value.array->max_size();
23259 }
23260
23261 case value_t::object:
23262 {
23263 // delegate call to object_t::max_size()
23264 return m_data.m_value.object->max_size();
23265 }
23266
23267 case value_t::null:
23268 case value_t::string:
23269 case value_t::boolean:
23270 case value_t::number_integer:
23271 case value_t::number_unsigned:
23272 case value_t::number_float:
23273 case value_t::binary:
23274 case value_t::discarded:
23275 default:
23276 {
23277 // all other types have max_size() == size()
23278 return size();
23279 }
23280 }
23281 }
23282
23284
23286 // modifiers //
23288
23291
23294 void clear() noexcept
23295 {
23296 switch (m_data.m_type)
23297 {
23298 case value_t::number_integer:
23299 {
23300 m_data.m_value.number_integer = 0;
23301 break;
23302 }
23303
23304 case value_t::number_unsigned:
23305 {
23306 m_data.m_value.number_unsigned = 0;
23307 break;
23308 }
23309
23310 case value_t::number_float:
23311 {
23312 m_data.m_value.number_float = 0.0;
23313 break;
23314 }
23315
23316 case value_t::boolean:
23317 {
23318 m_data.m_value.boolean = false;
23319 break;
23320 }
23321
23322 case value_t::string:
23323 {
23324 m_data.m_value.string->clear();
23325 break;
23326 }
23327
23328 case value_t::binary:
23329 {
23330 m_data.m_value.binary->clear();
23331 break;
23332 }
23333
23334 case value_t::array:
23335 {
23336 m_data.m_value.array->clear();
23337 break;
23338 }
23339
23340 case value_t::object:
23341 {
23342 m_data.m_value.object->clear();
23343 break;
23344 }
23345
23346 case value_t::null:
23347 case value_t::discarded:
23348 default:
23349 break;
23350 }
23351 }
23352
23356 {
23357 // push_back only works for null objects or arrays
23358 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23359 {
23360 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23361 }
23362
23363 // transform a null object into an array
23364 if (is_null())
23365 {
23366 m_data.m_type = value_t::array;
23367 m_data.m_value = value_t::array;
23368 assert_invariant();
23369 }
23370
23371 // add the element to the array (move semantics)
23372 const auto old_capacity = m_data.m_value.array->capacity();
23373 m_data.m_value.array->push_back(std::move(val));
23374 set_parent(m_data.m_value.array->back(), old_capacity);
23375 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
23376 }
23377
23381 {
23382 push_back(std::move(val));
23383 return *this;
23384 }
23385
23388 void push_back(const basic_json& val)
23389 {
23390 // push_back only works for null objects or arrays
23391 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23392 {
23393 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23394 }
23395
23396 // transform a null object into an array
23397 if (is_null())
23398 {
23399 m_data.m_type = value_t::array;
23400 m_data.m_value = value_t::array;
23401 assert_invariant();
23402 }
23403
23404 // add the element to the array
23405 const auto old_capacity = m_data.m_value.array->capacity();
23406 m_data.m_value.array->push_back(val);
23407 set_parent(m_data.m_value.array->back(), old_capacity);
23408 }
23409
23413 {
23414 push_back(val);
23415 return *this;
23416 }
23417
23420 void push_back(const typename object_t::value_type& val)
23421 {
23422 // push_back only works for null objects or objects
23423 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23424 {
23425 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23426 }
23427
23428 // transform a null object into an object
23429 if (is_null())
23430 {
23431 m_data.m_type = value_t::object;
23432 m_data.m_value = value_t::object;
23433 assert_invariant();
23434 }
23435
23436 // add the element to the object
23437 auto res = m_data.m_value.object->insert(val);
23438 set_parent(res.first->second);
23439 }
23440
23443 reference operator+=(const typename object_t::value_type& val)
23444 {
23445 push_back(val);
23446 return *this;
23447 }
23448
23452 {
23453 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
23454 {
23455 basic_json&& key = init.begin()->moved_or_copied();
23456 push_back(typename object_t::value_type(
23457 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
23458 }
23459 else
23460 {
23461 push_back(basic_json(init));
23462 }
23463 }
23464
23468 {
23469 push_back(init);
23470 return *this;
23471 }
23472
23475 template<class... Args>
23476 reference emplace_back(Args&& ... args)
23477 {
23478 // emplace_back only works for null objects or arrays
23479 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23480 {
23481 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
23482 }
23483
23484 // transform a null object into an array
23485 if (is_null())
23486 {
23487 m_data.m_type = value_t::array;
23488 m_data.m_value = value_t::array;
23489 assert_invariant();
23490 }
23491
23492 // add the element to the array (perfect forwarding)
23493 const auto old_capacity = m_data.m_value.array->capacity();
23494 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
23495 return set_parent(m_data.m_value.array->back(), old_capacity);
23496 }
23497
23500 template<class... Args>
23501 std::pair<iterator, bool> emplace(Args&& ... args)
23502 {
23503 // emplace only works for null objects or arrays
23504 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23505 {
23506 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
23507 }
23508
23509 // transform a null object into an object
23510 if (is_null())
23511 {
23512 m_data.m_type = value_t::object;
23513 m_data.m_value = value_t::object;
23514 assert_invariant();
23515 }
23516
23517 // add the element to the array (perfect forwarding)
23518 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
23519 set_parent(res.first->second);
23520
23521 // create a result iterator and set iterator to the result of emplace
23522 auto it = begin();
23523 it.m_it.object_iterator = res.first;
23524
23525 // return pair of iterator and boolean
23526 return {it, res.second};
23527 }
23528
23532 template<typename... Args>
23533 iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
23534 {
23535 iterator result(this);
23536 JSON_ASSERT(m_data.m_value.array != nullptr);
23537
23538 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
23539 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
23540 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
23541
23542 // This could have been written as:
23543 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
23544 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
23545
23546 set_parents();
23547 return result;
23548 }
23549
23552 iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23553 {
23554 // insert only works for arrays
23555 if (JSON_HEDLEY_LIKELY(is_array()))
23556 {
23557 // check if iterator pos fits to this JSON value
23558 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23559 {
23560 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23561 }
23562
23563 // insert to array and return iterator
23564 return insert_iterator(pos, val);
23565 }
23566
23567 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23568 }
23569
23572 iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
23573 {
23574 return insert(pos, val);
23575 }
23576
23579 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23580 {
23581 // insert only works for arrays
23582 if (JSON_HEDLEY_LIKELY(is_array()))
23583 {
23584 // check if iterator pos fits to this JSON value
23585 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23586 {
23587 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23588 }
23589
23590 // insert to array and return iterator
23591 return insert_iterator(pos, cnt, val);
23592 }
23593
23594 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23595 }
23596
23599 iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23600 {
23601 // insert only works for arrays
23602 if (JSON_HEDLEY_UNLIKELY(!is_array()))
23603 {
23604 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23605 }
23606
23607 // check if iterator pos fits to this JSON value
23608 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23609 {
23610 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23611 }
23612
23613 // check if range iterators belong to the same JSON object
23614 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23615 {
23616 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23617 }
23618
23619 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
23620 {
23621 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
23622 }
23623
23624 // insert to array and return iterator
23625 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
23626 }
23627
23630 iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
23631 {
23632 // insert only works for arrays
23633 if (JSON_HEDLEY_UNLIKELY(!is_array()))
23634 {
23635 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23636 }
23637
23638 // check if iterator pos fits to this JSON value
23639 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23640 {
23641 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23642 }
23643
23644 // insert to array and return iterator
23645 return insert_iterator(pos, ilist.begin(), ilist.end());
23646 }
23647
23650 void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23651 {
23652 // insert only works for objects
23653 if (JSON_HEDLEY_UNLIKELY(!is_object()))
23654 {
23655 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23656 }
23657
23658 // check if range iterators belong to the same JSON object
23659 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23660 {
23661 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23662 }
23663
23664 // passed iterators must belong to objects
23665 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23666 {
23667 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
23668 }
23669
23670 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
23671 set_parents();
23672 }
23673
23676 void update(const_reference j, bool merge_objects = false)
23677 {
23678 update(j.begin(), j.end(), merge_objects);
23679 }
23680
23683 void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
23684 {
23685 // implicitly convert a null value to an empty object
23686 if (is_null())
23687 {
23688 m_data.m_type = value_t::object;
23689 m_data.m_value.object = create<object_t>();
23690 assert_invariant();
23691 }
23692
23693 if (JSON_HEDLEY_UNLIKELY(!is_object()))
23694 {
23695 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
23696 }
23697
23698 // check if range iterators belong to the same JSON object
23699 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23700 {
23701 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23702 }
23703
23704 // passed iterators must belong to objects
23705 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23706 {
23707 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
23708 }
23709
23710 for (auto it = first; it != last; ++it)
23711 {
23712 if (merge_objects && it.value().is_object())
23713 {
23714 auto it2 = m_data.m_value.object->find(it.key());
23715 if (it2 != m_data.m_value.object->end())
23716 {
23717 it2->second.update(it.value(), true);
23718 continue;
23719 }
23720 }
23721 m_data.m_value.object->operator[](it.key()) = it.value();
23722#if JSON_DIAGNOSTICS
23723 m_data.m_value.object->operator[](it.key()).m_parent = this;
23724#endif
23725 }
23726 }
23727
23730 void swap(reference other) noexcept (
23731 std::is_nothrow_move_constructible<value_t>::value&&
23732 std::is_nothrow_move_assignable<value_t>::value&&
23733 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23734 std::is_nothrow_move_assignable<json_value>::value
23735 )
23736 {
23737 std::swap(m_data.m_type, other.m_data.m_type);
23738 std::swap(m_data.m_value, other.m_data.m_value);
23739
23740 set_parents();
23741 other.set_parents();
23742 assert_invariant();
23743 }
23744
23747 friend void swap(reference left, reference right) noexcept (
23748 std::is_nothrow_move_constructible<value_t>::value&&
23749 std::is_nothrow_move_assignable<value_t>::value&&
23750 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23751 std::is_nothrow_move_assignable<json_value>::value
23752 )
23753 {
23754 left.swap(right);
23755 }
23756
23759 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23760 {
23761 // swap only works for arrays
23762 if (JSON_HEDLEY_LIKELY(is_array()))
23763 {
23764 using std::swap;
23765 swap(*(m_data.m_value.array), other);
23766 }
23767 else
23768 {
23769 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
23770 }
23771 }
23772
23775 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23776 {
23777 // swap only works for objects
23778 if (JSON_HEDLEY_LIKELY(is_object()))
23779 {
23780 using std::swap;
23781 swap(*(m_data.m_value.object), other);
23782 }
23783 else
23784 {
23785 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
23786 }
23787 }
23788
23791 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23792 {
23793 // swap only works for strings
23794 if (JSON_HEDLEY_LIKELY(is_string()))
23795 {
23796 using std::swap;
23797 swap(*(m_data.m_value.string), other);
23798 }
23799 else
23800 {
23801 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
23802 }
23803 }
23804
23807 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23808 {
23809 // swap only works for strings
23810 if (JSON_HEDLEY_LIKELY(is_binary()))
23811 {
23812 using std::swap;
23813 swap(*(m_data.m_value.binary), other);
23814 }
23815 else
23816 {
23817 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
23818 }
23819 }
23820
23823 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
23824 {
23825 // swap only works for strings
23826 if (JSON_HEDLEY_LIKELY(is_binary()))
23827 {
23828 using std::swap;
23829 swap(*(m_data.m_value.binary), other);
23830 }
23831 else
23832 {
23833 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
23834 }
23835 }
23836
23838
23840 // lexicographical comparison operators //
23842
23845
23846 // note parentheses around operands are necessary; see
23847 // https://github.com/nlohmann/json/issues/1530
23848#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
23849 const auto lhs_type = lhs.type(); \
23850 const auto rhs_type = rhs.type(); \
23851 \
23852 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
23853 { \
23854 switch (lhs_type) \
23855 { \
23856 case value_t::array: \
23857 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
23858 \
23859 case value_t::object: \
23860 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
23861 \
23862 case value_t::null: \
23863 return (null_result); \
23864 \
23865 case value_t::string: \
23866 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
23867 \
23868 case value_t::boolean: \
23869 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
23870 \
23871 case value_t::number_integer: \
23872 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
23873 \
23874 case value_t::number_unsigned: \
23875 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
23876 \
23877 case value_t::number_float: \
23878 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
23879 \
23880 case value_t::binary: \
23881 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
23882 \
23883 case value_t::discarded: \
23884 default: \
23885 return (unordered_result); \
23886 } \
23887 } \
23888 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
23889 { \
23890 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
23891 } \
23892 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
23893 { \
23894 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
23895 } \
23896 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
23897 { \
23898 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
23899 } \
23900 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
23901 { \
23902 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
23903 } \
23904 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
23905 { \
23906 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
23907 } \
23908 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
23909 { \
23910 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
23911 } \
23912 else if(compares_unordered(lhs, rhs))\
23913 {\
23914 return (unordered_result);\
23915 }\
23916 \
23917 return (default_result);
23918
23920 // returns true if:
23921 // - any operand is NaN and the other operand is of number type
23922 // - any operand is discarded
23923 // in legacy mode, discarded values are considered ordered if
23924 // an operation is computed as an odd number of inverses of others
23925 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
23926 {
23927 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
23928 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
23929 {
23930 return true;
23931 }
23932#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23933 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
23934#else
23935 static_cast<void>(inverse);
23936 return lhs.is_discarded() || rhs.is_discarded();
23937#endif
23938 }
23939
23940 private:
23941 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
23942 {
23943 return compares_unordered(*this, rhs, inverse);
23944 }
23945
23946 public:
23947#if JSON_HAS_THREE_WAY_COMPARISON
23950 bool operator==(const_reference rhs) const noexcept
23951 {
23952#ifdef __GNUC__
23953#pragma GCC diagnostic push
23954#pragma GCC diagnostic ignored "-Wfloat-equal"
23955#endif
23956 const_reference lhs = *this;
23957 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23958#ifdef __GNUC__
23959#pragma GCC diagnostic pop
23960#endif
23961 }
23962
23965 template<typename ScalarType>
23966 requires std::is_scalar_v<ScalarType>
23967 bool operator==(ScalarType rhs) const noexcept
23968 {
23969 return *this == basic_json(rhs);
23970 }
23971
23974 bool operator!=(const_reference rhs) const noexcept
23975 {
23976 if (compares_unordered(rhs, true))
23977 {
23978 return false;
23979 }
23980 return !operator==(rhs);
23981 }
23982
23985 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23986 {
23987 const_reference lhs = *this;
23988 // default_result is used if we cannot compare values. In that case,
23989 // we compare types.
23990 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23991 std::partial_ordering::equivalent,
23992 std::partial_ordering::unordered,
23993 lhs_type <=> rhs_type) // *NOPAD*
23994 }
23995
23998 template<typename ScalarType>
23999 requires std::is_scalar_v<ScalarType>
24000 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
24001 {
24002 return *this <=> basic_json(rhs); // *NOPAD*
24003 }
24004
24005#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
24006 // all operators that are computed as an odd number of inverses of others
24007 // need to be overloaded to emulate the legacy comparison behavior
24008
24012 bool operator<=(const_reference rhs) const noexcept
24013 {
24014 if (compares_unordered(rhs, true))
24015 {
24016 return false;
24017 }
24018 return !(rhs < *this);
24019 }
24020
24023 template<typename ScalarType>
24024 requires std::is_scalar_v<ScalarType>
24025 bool operator<=(ScalarType rhs) const noexcept
24026 {
24027 return *this <= basic_json(rhs);
24028 }
24029
24033 bool operator>=(const_reference rhs) const noexcept
24034 {
24035 if (compares_unordered(rhs, true))
24036 {
24037 return false;
24038 }
24039 return !(*this < rhs);
24040 }
24041
24044 template<typename ScalarType>
24045 requires std::is_scalar_v<ScalarType>
24046 bool operator>=(ScalarType rhs) const noexcept
24047 {
24048 return *this >= basic_json(rhs);
24049 }
24050#endif
24051#else
24054 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
24055 {
24056#ifdef __GNUC__
24057#pragma GCC diagnostic push
24058#pragma GCC diagnostic ignored "-Wfloat-equal"
24059#endif
24060 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
24061#ifdef __GNUC__
24062#pragma GCC diagnostic pop
24063#endif
24064 }
24065
24068 template<typename ScalarType, typename std::enable_if<
24069 std::is_scalar<ScalarType>::value, int>::type = 0>
24070 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
24071 {
24072 return lhs == basic_json(rhs);
24073 }
24074
24077 template<typename ScalarType, typename std::enable_if<
24078 std::is_scalar<ScalarType>::value, int>::type = 0>
24079 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
24080 {
24081 return basic_json(lhs) == rhs;
24082 }
24083
24086 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
24087 {
24088 if (compares_unordered(lhs, rhs, true))
24089 {
24090 return false;
24091 }
24092 return !(lhs == rhs);
24093 }
24094
24097 template<typename ScalarType, typename std::enable_if<
24098 std::is_scalar<ScalarType>::value, int>::type = 0>
24099 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
24100 {
24101 return lhs != basic_json(rhs);
24102 }
24103
24106 template<typename ScalarType, typename std::enable_if<
24107 std::is_scalar<ScalarType>::value, int>::type = 0>
24108 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
24109 {
24110 return basic_json(lhs) != rhs;
24111 }
24112
24115 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
24116 {
24117 // default_result is used if we cannot compare values. In that case,
24118 // we compare types. Note we have to call the operator explicitly,
24119 // because MSVC has problems otherwise.
24120 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
24121 }
24122
24125 template<typename ScalarType, typename std::enable_if<
24126 std::is_scalar<ScalarType>::value, int>::type = 0>
24127 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
24128 {
24129 return lhs < basic_json(rhs);
24130 }
24131
24134 template<typename ScalarType, typename std::enable_if<
24135 std::is_scalar<ScalarType>::value, int>::type = 0>
24136 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
24137 {
24138 return basic_json(lhs) < rhs;
24139 }
24140
24143 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
24144 {
24145 if (compares_unordered(lhs, rhs, true))
24146 {
24147 return false;
24148 }
24149 return !(rhs < lhs);
24150 }
24151
24154 template<typename ScalarType, typename std::enable_if<
24155 std::is_scalar<ScalarType>::value, int>::type = 0>
24156 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
24157 {
24158 return lhs <= basic_json(rhs);
24159 }
24160
24163 template<typename ScalarType, typename std::enable_if<
24164 std::is_scalar<ScalarType>::value, int>::type = 0>
24165 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
24166 {
24167 return basic_json(lhs) <= rhs;
24168 }
24169
24172 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
24173 {
24174 // double inverse
24175 if (compares_unordered(lhs, rhs))
24176 {
24177 return false;
24178 }
24179 return !(lhs <= rhs);
24180 }
24181
24184 template<typename ScalarType, typename std::enable_if<
24185 std::is_scalar<ScalarType>::value, int>::type = 0>
24186 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
24187 {
24188 return lhs > basic_json(rhs);
24189 }
24190
24193 template<typename ScalarType, typename std::enable_if<
24194 std::is_scalar<ScalarType>::value, int>::type = 0>
24195 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
24196 {
24197 return basic_json(lhs) > rhs;
24198 }
24199
24202 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
24203 {
24204 if (compares_unordered(lhs, rhs, true))
24205 {
24206 return false;
24207 }
24208 return !(lhs < rhs);
24209 }
24210
24213 template<typename ScalarType, typename std::enable_if<
24214 std::is_scalar<ScalarType>::value, int>::type = 0>
24215 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
24216 {
24217 return lhs >= basic_json(rhs);
24218 }
24219
24222 template<typename ScalarType, typename std::enable_if<
24223 std::is_scalar<ScalarType>::value, int>::type = 0>
24224 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
24225 {
24226 return basic_json(lhs) >= rhs;
24227 }
24228#endif
24229
24230#undef JSON_IMPLEMENT_OPERATOR
24231
24233
24235 // serialization //
24237
24240#ifndef JSON_NO_IO
24243 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
24244 {
24245 // read width member and use it as the indentation parameter if nonzero
24246 const bool pretty_print = o.width() > 0;
24247 const auto indentation = pretty_print ? o.width() : 0;
24248
24249 // reset width to 0 for subsequent calls to this stream
24250 o.width(0);
24251
24252 // do the actual serialization
24253 serializer s(detail::output_adapter<char>(o), o.fill());
24254 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
24255 return o;
24256 }
24257
24264 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
24265 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
24266 {
24267 return o << j;
24268 }
24269#endif // JSON_NO_IO
24271
24273 // deserialization //
24275
24278
24281 template<typename InputType>
24283 static basic_json parse(InputType&& i,
24284 parser_callback_t cb = nullptr,
24285 const bool allow_exceptions = true,
24286 const bool ignore_comments = false,
24287 const bool ignore_trailing_commas = false)
24288 {
24289 basic_json result;
24290 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]
24291 return result;
24292 }
24293
24296 template<typename IteratorType>
24298 static basic_json parse(IteratorType first,
24299 IteratorType last,
24300 parser_callback_t cb = nullptr,
24301 const bool allow_exceptions = true,
24302 const bool ignore_comments = false,
24303 const bool ignore_trailing_commas = false)
24304 {
24305 basic_json result;
24306 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]
24307 return result;
24308 }
24309
24311 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
24312 static basic_json parse(detail::span_input_adapter&& i,
24313 parser_callback_t cb = nullptr,
24314 const bool allow_exceptions = true,
24315 const bool ignore_comments = false,
24316 const bool ignore_trailing_commas = false)
24317 {
24318 basic_json result;
24319 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
24320 return result;
24321 }
24322
24325 template<typename InputType>
24326 static bool accept(InputType&& i,
24327 const bool ignore_comments = false,
24328 const bool ignore_trailing_commas = false)
24329 {
24330 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24331 }
24332
24335 template<typename IteratorType>
24336 static bool accept(IteratorType first, IteratorType last,
24337 const bool ignore_comments = false,
24338 const bool ignore_trailing_commas = false)
24339 {
24340 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24341 }
24342
24344 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
24345 static bool accept(detail::span_input_adapter&& i,
24346 const bool ignore_comments = false,
24347 const bool ignore_trailing_commas = false)
24348 {
24349 return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24350 }
24351
24354 template <typename InputType, typename SAX>
24356 static bool sax_parse(InputType&& i, SAX* sax,
24358 const bool strict = true,
24359 const bool ignore_comments = false,
24360 const bool ignore_trailing_commas = false)
24361 {
24362#if defined(__clang__)
24363#pragma clang diagnostic push
24364#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
24365#elif defined(__GNUC__)
24366#pragma GCC diagnostic push
24367#pragma GCC diagnostic ignored "-Wnonnull-compare"
24368#endif
24369 if (sax == nullptr)
24370 {
24371 JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
24372 }
24373#if defined(__clang__)
24374#pragma clang diagnostic pop
24375#elif defined(__GNUC__)
24376#pragma GCC diagnostic pop
24377#endif
24378 auto ia = detail::input_adapter(std::forward<InputType>(i));
24379 return format == input_format_t::json
24380 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24381 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24382 }
24383
24386 template<class IteratorType, class SAX>
24388 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
24390 const bool strict = true,
24391 const bool ignore_comments = false,
24392 const bool ignore_trailing_commas = false)
24393 {
24394#if defined(__clang__)
24395#pragma clang diagnostic push
24396#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
24397#elif defined(__GNUC__)
24398#pragma GCC diagnostic push
24399#pragma GCC diagnostic ignored "-Wnonnull-compare"
24400#endif
24401 if (sax == nullptr)
24402 {
24403 JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
24404 }
24405#if defined(__clang__)
24406#pragma clang diagnostic pop
24407#elif defined(__GNUC__)
24408#pragma GCC diagnostic pop
24409#endif
24410 auto ia = detail::input_adapter(std::move(first), std::move(last));
24411 return format == input_format_t::json
24412 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24413 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24414 }
24415
24421 template <typename SAX>
24422 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
24424 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
24426 const bool strict = true,
24427 const bool ignore_comments = false,
24428 const bool ignore_trailing_commas = false)
24429 {
24430#if defined(__clang__)
24431#pragma clang diagnostic push
24432#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
24433#elif defined(__GNUC__)
24434#pragma GCC diagnostic push
24435#pragma GCC diagnostic ignored "-Wnonnull-compare"
24436#endif
24437 if (sax == nullptr)
24438 {
24439 JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
24440 }
24441#if defined(__clang__)
24442#pragma clang diagnostic pop
24443#elif defined(__GNUC__)
24444#pragma GCC diagnostic pop
24445#endif
24446 auto ia = i.get();
24447 return format == input_format_t::json
24448 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24449 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24450 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24451 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24452 }
24453#ifndef JSON_NO_IO
24460 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
24461 friend std::istream& operator<<(basic_json& j, std::istream& i)
24462 {
24463 return operator>>(i, j);
24464 }
24465
24468 friend std::istream& operator>>(std::istream& i, basic_json& j)
24469 {
24470 parser(detail::input_adapter(i)).parse(false, j);
24471 return i;
24472 }
24473#endif // JSON_NO_IO
24475
24477 // convenience functions //
24479
24483 const char* type_name() const noexcept
24484 {
24485 switch (m_data.m_type)
24486 {
24487 case value_t::null:
24488 return "null";
24489 case value_t::object:
24490 return "object";
24491 case value_t::array:
24492 return "array";
24493 case value_t::string:
24494 return "string";
24495 case value_t::boolean:
24496 return "boolean";
24497 case value_t::binary:
24498 return "binary";
24499 case value_t::discarded:
24500 return "discarded";
24501 case value_t::number_integer:
24502 case value_t::number_unsigned:
24503 case value_t::number_float:
24504 return "number";
24505 default:
24506 return "invalid";
24507 }
24508 }
24509
24512 // member variables //
24514
24515 struct data
24516 {
24518 value_t m_type = value_t::null;
24519
24521 json_value m_value = {};
24522
24523 data(const value_t v)
24524 : m_type(v), m_value(v)
24525 {
24526 }
24527
24528 data(size_type cnt, const basic_json& val)
24529 : m_type(value_t::array)
24530 {
24531 m_value.array = create<array_t>(cnt, val);
24532 }
24533
24534 data() noexcept = default;
24535 data(data&&) noexcept = default;
24536 data(const data&) noexcept = delete;
24537 data& operator=(data&&) noexcept = delete;
24538 data& operator=(const data&) noexcept = delete;
24539
24540 ~data() noexcept
24541 {
24542 m_value.destroy(m_type);
24543 }
24544 };
24545
24546 data m_data = {};
24547
24548#if JSON_DIAGNOSTICS
24550 basic_json* m_parent = nullptr;
24551#endif
24552
24553#if JSON_DIAGNOSTIC_POSITIONS
24555 std::size_t start_position = std::string::npos;
24557 std::size_t end_position = std::string::npos;
24558 public:
24559 constexpr std::size_t start_pos() const noexcept
24560 {
24561 return start_position;
24562 }
24563
24564 constexpr std::size_t end_pos() const noexcept
24565 {
24566 return end_position;
24567 }
24568#endif
24569
24571 // binary serialization/deserialization //
24573
24576
24577 public:
24580 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
24581 {
24582 std::vector<std::uint8_t> result;
24583 to_cbor(j, result);
24584 return result;
24585 }
24586
24590 {
24591 binary_writer<std::uint8_t>(o).write_cbor(j);
24592 }
24593
24597 {
24598 binary_writer<char>(o).write_cbor(j);
24599 }
24600
24603 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
24604 {
24605 std::vector<std::uint8_t> result;
24606 to_msgpack(j, result);
24607 return result;
24608 }
24609
24613 {
24614 binary_writer<std::uint8_t>(o).write_msgpack(j);
24615 }
24616
24620 {
24621 binary_writer<char>(o).write_msgpack(j);
24622 }
24623
24626 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
24627 const bool use_size = false,
24628 const bool use_type = false)
24629 {
24630 std::vector<std::uint8_t> result;
24631 to_ubjson(j, result, use_size, use_type);
24632 return result;
24633 }
24634
24638 const bool use_size = false, const bool use_type = false)
24639 {
24640 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
24641 }
24642
24646 const bool use_size = false, const bool use_type = false)
24647 {
24648 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
24649 }
24650
24653 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
24654 const bool use_size = false,
24655 const bool use_type = false,
24656 const bjdata_version_t version = bjdata_version_t::draft2)
24657 {
24658 std::vector<std::uint8_t> result;
24659 to_bjdata(j, result, use_size, use_type, version);
24660 return result;
24661 }
24662
24666 const bool use_size = false, const bool use_type = false,
24667 const bjdata_version_t version = bjdata_version_t::draft2)
24668 {
24669 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true, version);
24670 }
24671
24675 const bool use_size = false, const bool use_type = false,
24676 const bjdata_version_t version = bjdata_version_t::draft2)
24677 {
24678 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true, version);
24679 }
24680
24683 static std::vector<std::uint8_t> to_bson(const basic_json& j)
24684 {
24685 std::vector<std::uint8_t> result;
24686 to_bson(j, result);
24687 return result;
24688 }
24689
24693 {
24694 binary_writer<std::uint8_t>(o).write_bson(j);
24695 }
24696
24700 {
24701 binary_writer<char>(o).write_bson(j);
24702 }
24703
24706 template<typename InputType>
24708 static basic_json from_cbor(InputType&& i,
24709 const bool strict = true,
24710 const bool allow_exceptions = true,
24711 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24712 {
24713 basic_json result;
24714 auto ia = detail::input_adapter(std::forward<InputType>(i));
24715 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24716 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]
24717 return res ? result : basic_json(value_t::discarded);
24718 }
24719
24722 template<typename IteratorType>
24724 static basic_json from_cbor(IteratorType first, IteratorType last,
24725 const bool strict = true,
24726 const bool allow_exceptions = true,
24727 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24728 {
24729 basic_json result;
24730 auto ia = detail::input_adapter(std::move(first), std::move(last));
24731 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24732 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]
24733 return res ? result : basic_json(value_t::discarded);
24734 }
24735
24736 template<typename T>
24738 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24739 static basic_json from_cbor(const T* ptr, std::size_t len,
24740 const bool strict = true,
24741 const bool allow_exceptions = true,
24742 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24743 {
24744 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
24745 }
24746
24748 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24749 static basic_json from_cbor(detail::span_input_adapter&& i,
24750 const bool strict = true,
24751 const bool allow_exceptions = true,
24752 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24753 {
24754 basic_json result;
24755 auto ia = i.get();
24756 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24757 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24758 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]
24759 return res ? result : basic_json(value_t::discarded);
24760 }
24761
24764 template<typename InputType>
24766 static basic_json from_msgpack(InputType&& i,
24767 const bool strict = true,
24768 const bool allow_exceptions = true)
24769 {
24770 basic_json result;
24771 auto ia = detail::input_adapter(std::forward<InputType>(i));
24772 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24773 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]
24774 return res ? result : basic_json(value_t::discarded);
24775 }
24776
24779 template<typename IteratorType>
24781 static basic_json from_msgpack(IteratorType first, IteratorType last,
24782 const bool strict = true,
24783 const bool allow_exceptions = true)
24784 {
24785 basic_json result;
24786 auto ia = detail::input_adapter(std::move(first), std::move(last));
24787 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24788 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]
24789 return res ? result : basic_json(value_t::discarded);
24790 }
24791
24792 template<typename T>
24794 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24795 static basic_json from_msgpack(const T* ptr, std::size_t len,
24796 const bool strict = true,
24797 const bool allow_exceptions = true)
24798 {
24799 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
24800 }
24801
24803 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24804 static basic_json from_msgpack(detail::span_input_adapter&& i,
24805 const bool strict = true,
24806 const bool allow_exceptions = true)
24807 {
24808 basic_json result;
24809 auto ia = i.get();
24810 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24811 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24812 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]
24813 return res ? result : basic_json(value_t::discarded);
24814 }
24815
24818 template<typename InputType>
24820 static basic_json from_ubjson(InputType&& i,
24821 const bool strict = true,
24822 const bool allow_exceptions = true)
24823 {
24824 basic_json result;
24825 auto ia = detail::input_adapter(std::forward<InputType>(i));
24826 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24827 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]
24828 return res ? result : basic_json(value_t::discarded);
24829 }
24830
24833 template<typename IteratorType>
24835 static basic_json from_ubjson(IteratorType first, IteratorType last,
24836 const bool strict = true,
24837 const bool allow_exceptions = true)
24838 {
24839 basic_json result;
24840 auto ia = detail::input_adapter(std::move(first), std::move(last));
24841 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24842 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]
24843 return res ? result : basic_json(value_t::discarded);
24844 }
24845
24846 template<typename T>
24848 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24849 static basic_json from_ubjson(const T* ptr, std::size_t len,
24850 const bool strict = true,
24851 const bool allow_exceptions = true)
24852 {
24853 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24854 }
24855
24857 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24858 static basic_json from_ubjson(detail::span_input_adapter&& i,
24859 const bool strict = true,
24860 const bool allow_exceptions = true)
24861 {
24862 basic_json result;
24863 auto ia = i.get();
24864 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24865 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24866 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]
24867 return res ? result : basic_json(value_t::discarded);
24868 }
24869
24872 template<typename InputType>
24874 static basic_json from_bjdata(InputType&& i,
24875 const bool strict = true,
24876 const bool allow_exceptions = true)
24877 {
24878 basic_json result;
24879 auto ia = detail::input_adapter(std::forward<InputType>(i));
24880 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24881 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]
24882 return res ? result : basic_json(value_t::discarded);
24883 }
24884
24887 template<typename IteratorType>
24889 static basic_json from_bjdata(IteratorType first, IteratorType last,
24890 const bool strict = true,
24891 const bool allow_exceptions = true)
24892 {
24893 basic_json result;
24894 auto ia = detail::input_adapter(std::move(first), std::move(last));
24895 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24896 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]
24897 return res ? result : basic_json(value_t::discarded);
24898 }
24899
24902 template<typename InputType>
24904 static basic_json from_bson(InputType&& i,
24905 const bool strict = true,
24906 const bool allow_exceptions = true)
24907 {
24908 basic_json result;
24909 auto ia = detail::input_adapter(std::forward<InputType>(i));
24910 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24911 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]
24912 return res ? result : basic_json(value_t::discarded);
24913 }
24914
24917 template<typename IteratorType>
24919 static basic_json from_bson(IteratorType first, IteratorType last,
24920 const bool strict = true,
24921 const bool allow_exceptions = true)
24922 {
24923 basic_json result;
24924 auto ia = detail::input_adapter(std::move(first), std::move(last));
24925 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24926 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]
24927 return res ? result : basic_json(value_t::discarded);
24928 }
24929
24930 template<typename T>
24932 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24933 static basic_json from_bson(const T* ptr, std::size_t len,
24934 const bool strict = true,
24935 const bool allow_exceptions = true)
24936 {
24937 return from_bson(ptr, ptr + len, strict, allow_exceptions);
24938 }
24939
24941 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24942 static basic_json from_bson(detail::span_input_adapter&& i,
24943 const bool strict = true,
24944 const bool allow_exceptions = true)
24945 {
24946 basic_json result;
24947 auto ia = i.get();
24948 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24949 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24950 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]
24951 return res ? result : basic_json(value_t::discarded);
24952 }
24954
24956 // JSON Pointer support //
24958
24961
24965 {
24966 return ptr.get_unchecked(this);
24967 }
24968
24969 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24970 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24971 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24972 {
24973 return ptr.get_unchecked(this);
24974 }
24975
24979 {
24980 return ptr.get_unchecked(this);
24981 }
24982
24983 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24984 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24985 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24986 {
24987 return ptr.get_unchecked(this);
24988 }
24989
24993 {
24994 return ptr.get_checked(this);
24995 }
24996
24997 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24998 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24999 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
25000 {
25001 return ptr.get_checked(this);
25002 }
25003
25007 {
25008 return ptr.get_checked(this);
25009 }
25010
25011 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
25012 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
25013 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
25014 {
25015 return ptr.get_checked(this);
25016 }
25017
25021 {
25022 basic_json result(value_t::object);
25023 json_pointer::flatten("", *this, result);
25024 return result;
25025 }
25026
25030 {
25031 return json_pointer::unflatten(*this);
25032 }
25033
25035
25037 // JSON Patch functions //
25039
25042
25045 void patch_inplace(const basic_json& json_patch)
25046 {
25047 basic_json& result = *this;
25048 // the valid JSON Patch operations
25049 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
25050
25051 const auto get_op = [](const string_t& op)
25052 {
25053 if (op == "add")
25054 {
25055 return patch_operations::add;
25056 }
25057 if (op == "remove")
25058 {
25059 return patch_operations::remove;
25060 }
25061 if (op == "replace")
25062 {
25063 return patch_operations::replace;
25064 }
25065 if (op == "move")
25066 {
25067 return patch_operations::move;
25068 }
25069 if (op == "copy")
25070 {
25071 return patch_operations::copy;
25072 }
25073 if (op == "test")
25074 {
25075 return patch_operations::test;
25076 }
25077
25078 return patch_operations::invalid;
25079 };
25080
25081 // wrapper for "add" operation; add value at ptr
25082 const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
25083 {
25084 // adding to the root of the target document means replacing it
25085 if (ptr.empty())
25086 {
25087 result = val;
25088 return;
25089 }
25090
25091 // make sure the top element of the pointer exists
25092 json_pointer const top_pointer = ptr.top();
25093 if (top_pointer != ptr)
25094 {
25095 result.at(top_pointer);
25096 }
25097
25098 // get reference to the parent of the JSON pointer ptr
25099 const auto last_path = ptr.back();
25100 ptr.pop_back();
25101 // parent must exist when performing patch add per RFC6902 specs
25102 basic_json& parent = result.at(ptr);
25103
25104 switch (parent.m_data.m_type)
25105 {
25106 case value_t::null:
25107 case value_t::object:
25108 {
25109 // use operator[] to add value
25110 parent[last_path] = val;
25111 break;
25112 }
25113
25114 case value_t::array:
25115 {
25116 if (last_path == "-")
25117 {
25118 // special case: append to back
25119 parent.push_back(val);
25120 }
25121 else
25122 {
25123 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
25124 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
25125 {
25126 // avoid undefined behavior
25127 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
25128 }
25129
25130 // default case: insert add offset
25131 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
25132 }
25133 break;
25134 }
25135
25136 // if there exists a parent, it cannot be primitive
25137 case value_t::string: // LCOV_EXCL_LINE
25138 case value_t::boolean: // LCOV_EXCL_LINE
25139 case value_t::number_integer: // LCOV_EXCL_LINE
25140 case value_t::number_unsigned: // LCOV_EXCL_LINE
25141 case value_t::number_float: // LCOV_EXCL_LINE
25142 case value_t::binary: // LCOV_EXCL_LINE
25143 case value_t::discarded: // LCOV_EXCL_LINE
25144 default: // LCOV_EXCL_LINE
25145 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
25146 }
25147 };
25148
25149 // wrapper for "remove" operation; remove value at ptr
25150 const auto operation_remove = [this, & result](json_pointer & ptr)
25151 {
25152 // get reference to the parent of the JSON pointer ptr
25153 const auto last_path = ptr.back();
25154 ptr.pop_back();
25155 basic_json& parent = result.at(ptr);
25156
25157 // remove child
25158 if (parent.is_object())
25159 {
25160 // perform range check
25161 auto it = parent.find(last_path);
25162 if (JSON_HEDLEY_LIKELY(it != parent.end()))
25163 {
25164 parent.erase(it);
25165 }
25166 else
25167 {
25168 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
25169 }
25170 }
25171 else if (parent.is_array())
25172 {
25173 // note erase performs range check
25174 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
25175 }
25176 };
25177
25178 // type check: top level value must be an array
25179 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
25180 {
25181 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
25182 }
25183
25184 // iterate and apply the operations
25185 for (const auto& val : json_patch)
25186 {
25187 // wrapper to get a value for an operation
25188 const auto get_value = [&val](const string_t& op,
25189 const string_t& member,
25190 bool string_type) -> basic_json &
25191 {
25192 // find value
25193 auto it = val.m_data.m_value.object->find(member);
25194
25195 // context-sensitive error message
25196 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
25197
25198 // check if the desired value is present
25199 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
25200 {
25201 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
25202 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
25203 }
25204
25205 // check if the result is of type string
25206 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
25207 {
25208 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
25209 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
25210 }
25211
25212 // no error: return value
25213 return it->second;
25214 };
25215
25216 // type check: every element of the array must be an object
25217 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
25218 {
25219 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
25220 }
25221
25222 // collect mandatory members
25223 const auto op = get_value("op", "op", true).template get<string_t>();
25224 const auto path = get_value(op, "path", true).template get<string_t>();
25225 json_pointer ptr(path);
25226
25227 switch (get_op(op))
25228 {
25229 case patch_operations::add:
25230 {
25231 operation_add(ptr, get_value("add", "value", false));
25232 break;
25233 }
25234
25235 case patch_operations::remove:
25236 {
25237 operation_remove(ptr);
25238 break;
25239 }
25240
25241 case patch_operations::replace:
25242 {
25243 // the "path" location must exist - use at()
25244 result.at(ptr) = get_value("replace", "value", false);
25245 break;
25246 }
25247
25248 case patch_operations::move:
25249 {
25250 const auto from_path = get_value("move", "from", true).template get<string_t>();
25251 json_pointer from_ptr(from_path);
25252
25253 // the "from" location must exist - use at()
25254 basic_json const v = result.at(from_ptr);
25255
25256 // The move operation is functionally identical to a
25257 // "remove" operation on the "from" location, followed
25258 // immediately by an "add" operation at the target
25259 // location with the value that was just removed.
25260 operation_remove(from_ptr);
25261 operation_add(ptr, v);
25262 break;
25263 }
25264
25265 case patch_operations::copy:
25266 {
25267 const auto from_path = get_value("copy", "from", true).template get<string_t>();
25268 const json_pointer from_ptr(from_path);
25269
25270 // the "from" location must exist - use at()
25271 basic_json const v = result.at(from_ptr);
25272
25273 // The copy is functionally identical to an "add"
25274 // operation at the target location using the value
25275 // specified in the "from" member.
25276 operation_add(ptr, v);
25277 break;
25278 }
25279
25280 case patch_operations::test:
25281 {
25282 bool success = false;
25283 JSON_TRY
25284 {
25285 // check if "value" matches the one at "path"
25286 // the "path" location must exist - use at()
25287 success = (result.at(ptr) == get_value("test", "value", false));
25288 }
25290 {
25291 // ignore out of range errors: success remains false
25292 }
25293
25294 // throw an exception if the test fails
25295 if (JSON_HEDLEY_UNLIKELY(!success))
25296 {
25297 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
25298 }
25299
25300 break;
25301 }
25302
25303 case patch_operations::invalid:
25304 default:
25305 {
25306 // op must be "add", "remove", "replace", "move", "copy", or
25307 // "test"
25308 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
25309 }
25310 }
25311 }
25312 }
25313
25316 basic_json patch(const basic_json& json_patch) const
25317 {
25318 basic_json result = *this;
25319 result.patch_inplace(json_patch);
25320 return result;
25321 }
25322
25326 static basic_json diff(const basic_json& source, const basic_json& target,
25327 const string_t& path = "")
25328 {
25329 // the patch
25330 basic_json result(value_t::array);
25331
25332 // if the values are the same, return an empty patch
25333 if (source == target)
25334 {
25335 return result;
25336 }
25337
25338 if (source.type() != target.type())
25339 {
25340 // different types: replace value
25341 result.push_back(
25342 {
25343 {"op", "replace"}, {"path", path}, {"value", target}
25344 });
25345 return result;
25346 }
25347
25348 switch (source.type())
25349 {
25350 case value_t::array:
25351 {
25352 // first pass: traverse common elements
25353 std::size_t i = 0;
25354 while (i < source.size() && i < target.size())
25355 {
25356 // recursive call to compare array values at index i
25357 auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
25358 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25359 ++i;
25360 }
25361
25362 // We now reached the end of at least one array
25363 // in a second pass, traverse the remaining elements
25364
25365 // remove my remaining elements
25366 const auto end_index = static_cast<difference_type>(result.size());
25367 while (i < source.size())
25368 {
25369 // add operations in reverse order to avoid invalid
25370 // indices
25371 result.insert(result.begin() + end_index, object(
25372 {
25373 {"op", "remove"},
25374 {"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
25375 }));
25376 ++i;
25377 }
25378
25379 // add other remaining elements
25380 while (i < target.size())
25381 {
25382 result.push_back(
25383 {
25384 {"op", "add"},
25385 {"path", detail::concat<string_t>(path, "/-")},
25386 {"value", target[i]}
25387 });
25388 ++i;
25389 }
25390
25391 break;
25392 }
25393
25394 case value_t::object:
25395 {
25396 // first pass: traverse this object's elements
25397 for (auto it = source.cbegin(); it != source.cend(); ++it)
25398 {
25399 // escape the key name to be used in a JSON patch
25400 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25401
25402 if (target.find(it.key()) != target.end())
25403 {
25404 // recursive call to compare object values at key it
25405 auto temp_diff = diff(it.value(), target[it.key()], path_key);
25406 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25407 }
25408 else
25409 {
25410 // found a key that is not in o -> remove it
25411 result.push_back(object(
25412 {
25413 {"op", "remove"}, {"path", path_key}
25414 }));
25415 }
25416 }
25417
25418 // second pass: traverse other object's elements
25419 for (auto it = target.cbegin(); it != target.cend(); ++it)
25420 {
25421 if (source.find(it.key()) == source.end())
25422 {
25423 // found a key that is not in this -> add it
25424 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25425 result.push_back(
25426 {
25427 {"op", "add"}, {"path", path_key},
25428 {"value", it.value()}
25429 });
25430 }
25431 }
25432
25433 break;
25434 }
25435
25436 case value_t::null:
25437 case value_t::string:
25438 case value_t::boolean:
25439 case value_t::number_integer:
25440 case value_t::number_unsigned:
25441 case value_t::number_float:
25442 case value_t::binary:
25443 case value_t::discarded:
25444 default:
25445 {
25446 // both primitive types: replace value
25447 result.push_back(
25448 {
25449 {"op", "replace"}, {"path", path}, {"value", target}
25450 });
25451 break;
25452 }
25453 }
25454
25455 return result;
25456 }
25458
25460 // JSON Merge Patch functions //
25462
25465
25468 void merge_patch(const basic_json& apply_patch)
25469 {
25470 if (apply_patch.is_object())
25471 {
25472 if (!is_object())
25473 {
25474 *this = object();
25475 }
25476 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
25477 {
25478 if (it.value().is_null())
25479 {
25480 erase(it.key());
25481 }
25482 else
25483 {
25484 operator[](it.key()).merge_patch(it.value());
25485 }
25486 }
25487 }
25488 else
25489 {
25490 *this = apply_patch;
25491 }
25492 }
25493
25495};
25496
25501{
25502 return j.dump();
25503}
25504
25505inline namespace literals
25506{
25507inline namespace json_literals
25508{
25509
25513#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25514 inline nlohmann::json operator""_json(const char* s, std::size_t n)
25515#else
25516 // GCC 4.8 requires a space between "" and suffix
25517 inline nlohmann::json operator"" _json(const char* s, std::size_t n)
25518#endif
25519{
25520 return nlohmann::json::parse(s, s + n);
25521}
25522
25523#if defined(__cpp_char8_t)
25525inline nlohmann::json operator""_json(const char8_t* s, std::size_t n)
25526{
25527 return nlohmann::json::parse(reinterpret_cast<const char*>(s),
25528 reinterpret_cast<const char*>(s) + n);
25529}
25530#endif
25531
25535#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25536 inline nlohmann::json::json_pointer operator""_json_pointer(const char* s, std::size_t n)
25537#else
25538 // GCC 4.8 requires a space between "" and suffix
25539 inline nlohmann::json::json_pointer operator"" _json_pointer(const char* s, std::size_t n)
25540#endif
25541{
25542 return nlohmann::json::json_pointer(std::string(s, n));
25543}
25544
25545#if defined(__cpp_char8_t)
25546inline nlohmann::json::json_pointer operator""_json_pointer(const char8_t* s, std::size_t n)
25547{
25548 return nlohmann::json::json_pointer(std::string(reinterpret_cast<const char*>(s), n));
25549}
25550#endif
25551
25552} // namespace json_literals
25553} // namespace literals
25555
25557// nonmember support //
25559
25560namespace std // NOLINT(cert-dcl58-cpp)
25561{
25562
25566struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
25567{
25568 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
25569 {
25570 return nlohmann::detail::hash(j);
25571 }
25572};
25573
25574// specialization for std::less<value_t>
25575template<>
25576struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
25577{
25582 bool operator()(::nlohmann::detail::value_t lhs,
25583 ::nlohmann::detail::value_t rhs) const noexcept
25584 {
25585#if JSON_HAS_THREE_WAY_COMPARISON
25586 return std::is_lt(lhs <=> rhs); // *NOPAD*
25587#else
25588 return ::nlohmann::detail::operator<(lhs, rhs);
25589#endif
25590 }
25591};
25592
25593// C++20 prohibit function specialization in the std namespace.
25594#ifndef JSON_HAS_CPP_20
25595
25599inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
25600 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
25601 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
25602{
25603 j1.swap(j2);
25604}
25605
25606#endif
25607
25608} // namespace std
25609
25610#if JSON_USE_GLOBAL_UDLS
25611 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25612 using nlohmann::literals::json_literals::operator""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25613 using nlohmann::literals::json_literals::operator""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25614 #else
25615 // GCC 4.8 requires a space between "" and suffix
25616 using nlohmann::literals::json_literals::operator"" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25617 using nlohmann::literals::json_literals::operator"" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25618 #endif
25619#endif
25620
25621// #include <nlohmann/detail/macro_unscope.hpp>
25622// __ _____ _____ _____
25623// __| | __| | | | JSON for Modern C++
25624// | | |__ | | | | | | version 3.12.0
25625// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25626//
25627// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
25628// SPDX-License-Identifier: MIT
25629
25630
25631
25632// restore clang diagnostic settings
25633#if defined(__clang__)
25634 #pragma clang diagnostic pop
25635#endif
25636
25637// clean up
25638#undef JSON_ASSERT
25639#undef JSON_INTERNAL_CATCH
25640#undef JSON_THROW
25641#undef JSON_PRIVATE_UNLESS_TESTED
25642#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
25643#undef NLOHMANN_BASIC_JSON_TPL
25644#undef JSON_EXPLICIT
25645#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
25646#undef JSON_INLINE_VARIABLE
25647#undef JSON_NO_UNIQUE_ADDRESS
25648#undef JSON_DISABLE_ENUM_SERIALIZATION
25649#undef JSON_USE_GLOBAL_UDLS
25650
25651#ifndef JSON_TEST_KEEP_MACROS
25652 #undef JSON_CATCH
25653 #undef JSON_TRY
25654 #undef JSON_HAS_CPP_11
25655 #undef JSON_HAS_CPP_14
25656 #undef JSON_HAS_CPP_17
25657 #undef JSON_HAS_CPP_20
25658 #undef JSON_HAS_CPP_23
25659 #undef JSON_HAS_CPP_26
25660 #undef JSON_HAS_FILESYSTEM
25661 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
25662 #undef JSON_HAS_THREE_WAY_COMPARISON
25663 #undef JSON_HAS_RANGES
25664 #undef JSON_HAS_STATIC_RTTI
25665 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
25666#endif
25667
25668// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
25669// __ _____ _____ _____
25670// __| | __| | | | JSON for Modern C++
25671// | | |__ | | | | | | version 3.12.0
25672// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25673//
25674// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
25675// SPDX-License-Identifier: MIT
25676
25677
25678
25679#undef JSON_HEDLEY_ALWAYS_INLINE
25680#undef JSON_HEDLEY_ARM_VERSION
25681#undef JSON_HEDLEY_ARM_VERSION_CHECK
25682#undef JSON_HEDLEY_ARRAY_PARAM
25683#undef JSON_HEDLEY_ASSUME
25684#undef JSON_HEDLEY_BEGIN_C_DECLS
25685#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
25686#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
25687#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
25688#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
25689#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
25690#undef JSON_HEDLEY_CLANG_HAS_FEATURE
25691#undef JSON_HEDLEY_CLANG_HAS_WARNING
25692#undef JSON_HEDLEY_COMPCERT_VERSION
25693#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
25694#undef JSON_HEDLEY_CONCAT
25695#undef JSON_HEDLEY_CONCAT3
25696#undef JSON_HEDLEY_CONCAT3_EX
25697#undef JSON_HEDLEY_CONCAT_EX
25698#undef JSON_HEDLEY_CONST
25699#undef JSON_HEDLEY_CONSTEXPR
25700#undef JSON_HEDLEY_CONST_CAST
25701#undef JSON_HEDLEY_CPP_CAST
25702#undef JSON_HEDLEY_CRAY_VERSION
25703#undef JSON_HEDLEY_CRAY_VERSION_CHECK
25704#undef JSON_HEDLEY_C_DECL
25705#undef JSON_HEDLEY_DEPRECATED
25706#undef JSON_HEDLEY_DEPRECATED_FOR
25707#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
25708#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
25709#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
25710#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
25711#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
25712#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
25713#undef JSON_HEDLEY_DIAGNOSTIC_POP
25714#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
25715#undef JSON_HEDLEY_DMC_VERSION
25716#undef JSON_HEDLEY_DMC_VERSION_CHECK
25717#undef JSON_HEDLEY_EMPTY_BASES
25718#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
25719#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
25720#undef JSON_HEDLEY_END_C_DECLS
25721#undef JSON_HEDLEY_FLAGS
25722#undef JSON_HEDLEY_FLAGS_CAST
25723#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
25724#undef JSON_HEDLEY_GCC_HAS_BUILTIN
25725#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
25726#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
25727#undef JSON_HEDLEY_GCC_HAS_EXTENSION
25728#undef JSON_HEDLEY_GCC_HAS_FEATURE
25729#undef JSON_HEDLEY_GCC_HAS_WARNING
25730#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
25731#undef JSON_HEDLEY_GCC_VERSION
25732#undef JSON_HEDLEY_GCC_VERSION_CHECK
25733#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
25734#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
25735#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
25736#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
25737#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
25738#undef JSON_HEDLEY_GNUC_HAS_FEATURE
25739#undef JSON_HEDLEY_GNUC_HAS_WARNING
25740#undef JSON_HEDLEY_GNUC_VERSION
25741#undef JSON_HEDLEY_GNUC_VERSION_CHECK
25742#undef JSON_HEDLEY_HAS_ATTRIBUTE
25743#undef JSON_HEDLEY_HAS_BUILTIN
25744#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
25745#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
25746#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
25747#undef JSON_HEDLEY_HAS_EXTENSION
25748#undef JSON_HEDLEY_HAS_FEATURE
25749#undef JSON_HEDLEY_HAS_WARNING
25750#undef JSON_HEDLEY_IAR_VERSION
25751#undef JSON_HEDLEY_IAR_VERSION_CHECK
25752#undef JSON_HEDLEY_IBM_VERSION
25753#undef JSON_HEDLEY_IBM_VERSION_CHECK
25754#undef JSON_HEDLEY_IMPORT
25755#undef JSON_HEDLEY_INLINE
25756#undef JSON_HEDLEY_INTEL_CL_VERSION
25757#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
25758#undef JSON_HEDLEY_INTEL_VERSION
25759#undef JSON_HEDLEY_INTEL_VERSION_CHECK
25760#undef JSON_HEDLEY_IS_CONSTANT
25761#undef JSON_HEDLEY_IS_CONSTEXPR_
25762#undef JSON_HEDLEY_LIKELY
25763#undef JSON_HEDLEY_MALLOC
25764#undef JSON_HEDLEY_MCST_LCC_VERSION
25765#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
25766#undef JSON_HEDLEY_MESSAGE
25767#undef JSON_HEDLEY_MSVC_VERSION
25768#undef JSON_HEDLEY_MSVC_VERSION_CHECK
25769#undef JSON_HEDLEY_NEVER_INLINE
25770#undef JSON_HEDLEY_NON_NULL
25771#undef JSON_HEDLEY_NO_ESCAPE
25772#undef JSON_HEDLEY_NO_RETURN
25773#undef JSON_HEDLEY_NO_THROW
25774#undef JSON_HEDLEY_NULL
25775#undef JSON_HEDLEY_PELLES_VERSION
25776#undef JSON_HEDLEY_PELLES_VERSION_CHECK
25777#undef JSON_HEDLEY_PGI_VERSION
25778#undef JSON_HEDLEY_PGI_VERSION_CHECK
25779#undef JSON_HEDLEY_PREDICT
25780#undef JSON_HEDLEY_PRINTF_FORMAT
25781#undef JSON_HEDLEY_PRIVATE
25782#undef JSON_HEDLEY_PUBLIC
25783#undef JSON_HEDLEY_PURE
25784#undef JSON_HEDLEY_REINTERPRET_CAST
25785#undef JSON_HEDLEY_REQUIRE
25786#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
25787#undef JSON_HEDLEY_REQUIRE_MSG
25788#undef JSON_HEDLEY_RESTRICT
25789#undef JSON_HEDLEY_RETURNS_NON_NULL
25790#undef JSON_HEDLEY_SENTINEL
25791#undef JSON_HEDLEY_STATIC_ASSERT
25792#undef JSON_HEDLEY_STATIC_CAST
25793#undef JSON_HEDLEY_STRINGIFY
25794#undef JSON_HEDLEY_STRINGIFY_EX
25795#undef JSON_HEDLEY_SUNPRO_VERSION
25796#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
25797#undef JSON_HEDLEY_TINYC_VERSION
25798#undef JSON_HEDLEY_TINYC_VERSION_CHECK
25799#undef JSON_HEDLEY_TI_ARMCL_VERSION
25800#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
25801#undef JSON_HEDLEY_TI_CL2000_VERSION
25802#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
25803#undef JSON_HEDLEY_TI_CL430_VERSION
25804#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
25805#undef JSON_HEDLEY_TI_CL6X_VERSION
25806#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
25807#undef JSON_HEDLEY_TI_CL7X_VERSION
25808#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
25809#undef JSON_HEDLEY_TI_CLPRU_VERSION
25810#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
25811#undef JSON_HEDLEY_TI_VERSION
25812#undef JSON_HEDLEY_TI_VERSION_CHECK
25813#undef JSON_HEDLEY_UNAVAILABLE
25814#undef JSON_HEDLEY_UNLIKELY
25815#undef JSON_HEDLEY_UNPREDICTABLE
25816#undef JSON_HEDLEY_UNREACHABLE
25817#undef JSON_HEDLEY_UNREACHABLE_RETURN
25818#undef JSON_HEDLEY_VERSION
25819#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
25820#undef JSON_HEDLEY_VERSION_DECODE_MINOR
25821#undef JSON_HEDLEY_VERSION_DECODE_REVISION
25822#undef JSON_HEDLEY_VERSION_ENCODE
25823#undef JSON_HEDLEY_WARNING
25824#undef JSON_HEDLEY_WARN_UNUSED_RESULT
25825#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
25826#undef JSON_HEDLEY_FALL_THROUGH
25827
25828
25829
25830#endif // INCLUDE_NLOHMANN_JSON_HPP_
std::ostream & operator<<(std::ostream &out, smf::MidiFile &aMidiFile)
Definition MidiFile.cpp:3501
namespace for Niels Lohmann
Definition json.hpp:20337
constexpr bool is_string() const noexcept
return whether value is a string
Definition json.hpp:21636
number_integer_t * get_impl_ptr(number_integer_t *) noexcept
get a pointer to the value (integer number)
Definition json.hpp:21729
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:22871
reference operator[](KeyType &&key)
access specified object element
Definition json.hpp:22437
json_value(object_t &&value)
constructor for rvalue objects
Definition json.hpp:20775
size_type size() const noexcept
returns the number of elements
Definition json.hpp:23212
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:24724
json_value(typename binary_t::container_type &&value)
constructor for rvalue binary arrays
Definition json.hpp:20787
number_unsigned_t number_unsigned
number (unsigned integer)
Definition json.hpp:20679
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 > {}))
get a (pointer) value (explicit)
Definition json.hpp:22009
::nlohmann::detail::iteration_proxy< Iterator > iteration_proxy
Definition json.hpp:20389
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition json.hpp:23069
reference back()
access the last element
Definition json.hpp:22675
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:21076
number_float_t number_float
number (floating-point)
Definition json.hpp:20681
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:23085
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition json.hpp:25316
json_value(const array_t &value)
constructor for arrays
Definition json.hpp:20778
array_t * get_impl_ptr(array_t *) noexcept
get a pointer to the value (array)
Definition json.hpp:21693
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
Definition json.hpp:24483
const_reference front() const
access the first element
Definition json.hpp:22668
constexpr bool is_array() const noexcept
return whether value is an array
Definition json.hpp:21629
number_float_t * get_impl_ptr(number_float_t *) noexcept
get a pointer to the value (floating-point number)
Definition json.hpp:21753
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)
exchanges the values
Definition json.hpp:23730
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22618
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22988
constexpr const number_integer_t * get_impl_ptr(const number_integer_t *) const noexcept
get a pointer to the value (integer number)
Definition json.hpp:21735
iter_impl< const basic_json > const_iterator
a const iterator for a basic_json container
Definition json.hpp:20471
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition json.hpp:20415
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition json.hpp:21601
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition json.hpp:20475
data(size_type cnt, const basic_json &val)
Definition json.hpp:24528
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:24919
::nlohmann::detail::json_base_class< CustomBaseClass > json_base_class_t
Definition json.hpp:20363
basic_json get_impl(detail::priority_tag< 3 >) const
get special-case overload
Definition json.hpp:21961
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24964
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition json.hpp:20466
static JSON_HEDLEY_RETURNS_NON_NULL T * create(Args &&... args)
helper for exception-safe object creation
Definition json.hpp:20619
std::size_t size_type
a type to represent container sizes
Definition json.hpp:20458
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.hpp:21573
json_value(boolean_t v) noexcept
constructor for booleans
Definition json.hpp:20686
const_reference operator[](KeyType &&key) const
access specified object element
Definition json.hpp:22461
boolean_t get_impl(boolean_t *) const
get a boolean (explicit)
Definition json.hpp:21670
void swap(binary_t &other)
exchanges the values
Definition json.hpp:23807
ReferenceType get_ref()
get a reference value (implicit)
Definition json.hpp:22099
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.hpp:23251
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:23676
::nlohmann::detail::iter_impl< BasicJsonType > iter_impl
Definition json.hpp:20387
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:22110
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:21650
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.hpp:23467
::nlohmann::detail::output_adapter_t< CharType > output_adapter_t
Definition json.hpp:20393
void push_back(basic_json &&val)
add an object to an array
Definition json.hpp:23355
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition json.hpp:22406
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:23157
json_value(number_integer_t v) noexcept
constructor for numbers (integer)
Definition json.hpp:20688
static ReferenceType get_ref_impl(ThisType &obj)
helper function to implement get_ref()
Definition json.hpp:21788
::nlohmann::detail::json_reverse_iterator< Base > json_reverse_iterator
Definition json.hpp:20390
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:21490
const_reference back() const
access the last element
Definition json.hpp:22684
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:22766
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:23412
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:23747
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:24820
constexpr const string_t * get_impl_ptr(const string_t *) const noexcept
get a pointer to the value (string)
Definition json.hpp:21711
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:21218
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition json.hpp:23579
object_t * get_impl_ptr(object_t *) noexcept
get a pointer to the value (object)
Definition json.hpp:21681
static ::nlohmann::detail::parser< basic_json, InputAdapterType > parser(InputAdapterType adapter, detail::parser_callback_t< basic_json >cb=nullptr, const bool allow_exceptions=true, const bool ignore_comments=false, const bool ignore_trailing_commas=false)
Definition json.hpp:20370
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:24904
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:20481
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
Definition json.hpp:20606
reference at(KeyType &&key)
access specified object element with bounds checking
Definition json.hpp:22269
iterator end() noexcept
returns an iterator to one past the last element
Definition json.hpp:23060
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:21608
json_value(array_t &&value)
constructor for rvalue arrays
Definition json.hpp:20781
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:23683
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition json.hpp:24683
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:23092
data m_data
Definition json.hpp:24546
void push_back(initializer_list_t init)
add an object to an object
Definition json.hpp:23451
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
Definition json.hpp:21043
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.hpp:21259
ValueType & get_to(ValueType &v) const
Definition json.hpp:22076
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:24619
iterator begin() noexcept
returns an iterator to the first element
Definition json.hpp:23035
array_t * array
array (stored with pointer to save storage)
Definition json.hpp:20669
void assert_invariant(bool check_parents=true) const noexcept
checks the class invariants
Definition json.hpp:20923
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition json.hpp:22516
void destroy(value_t t)
Definition json.hpp:20795
ValueType get_impl(detail::priority_tag< 0 >) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), std::declval< ValueType & >())))
get a value (explicit)
Definition json.hpp:21871
json_value(string_t &&value)
constructor for rvalue strings
Definition json.hpp:20769
const_iterator cend() const noexcept
returns an iterator to one past the last element
Definition json.hpp:23076
constexpr const binary_t * get_impl_ptr(const binary_t *) const noexcept
get a pointer to the value (binary)
Definition json.hpp:21771
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:24874
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:25006
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition json.hpp:21229
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:21064
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:24708
constexpr const number_unsigned_t * get_impl_ptr(const number_unsigned_t *) const noexcept
get a pointer to the value (unsigned number)
Definition json.hpp:21747
constexpr const boolean_t * get_impl_ptr(const boolean_t *) const noexcept
get a pointer to the value (boolean)
Definition json.hpp:21723
basic_json flatten() const
return flattened JSON value
Definition json.hpp:25020
constexpr const array_t * get_impl_ptr(const array_t *) const noexcept
get a pointer to the value (array)
Definition json.hpp:21699
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:24835
json_value(number_unsigned_t v) noexcept
constructor for numbers (unsigned)
Definition json.hpp:20690
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition json.hpp:22882
JSON_PRIVATE_UNLESS_TESTED const_reference bool static SAX bool sax_parse(InputType &&i, SAX *sax, input_format_t format=input_format_t::json, const bool strict=true, const bool ignore_comments=false, const bool ignore_trailing_commas=false)
Definition json.hpp:24356
::nlohmann::detail::primitive_iterator_t primitive_iterator_t
Definition json.hpp:20383
json_value(const string_t &value)
constructor for strings
Definition json.hpp:20766
const binary_t & get_binary() const
get a binary value
Definition json.hpp:22181
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition json.hpp:23599
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition json.hpp:25045
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22569
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24978
json_value(number_float_t v) noexcept
constructor for numbers (floating-point)
Definition json.hpp:20692
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition json.hpp:20582
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition json.hpp:23005
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:24589
::nlohmann::detail::binary_reader< basic_json, InputType > binary_reader
Definition json.hpp:20396
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:24699
iterator find(const typename object_t::key_type &key)
find an element in a JSON object
Definition json.hpp:22918
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:21207
BasicJsonType get_impl(detail::priority_tag< 2 >) const
get special-case overload
Definition json.hpp:21938
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:24653
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition json.hpp:22307
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.hpp:20489
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:21266
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition json.hpp:22932
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.hpp:24580
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:22696
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition json.hpp:23552
NumberFloatType number_float_t
a type for a number (floating-point)
Definition json.hpp:20602
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:22491
string_t * string
string (stored with pointer to save storage)
Definition json.hpp:20671
AllocatorType< basic_json > allocator_type
the allocator type
Definition json.hpp:20461
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition json.hpp:20464
reference set_parent(reference j, std::size_t old_capacity=detail::unknown_size())
Definition json.hpp:20994
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:21537
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.hpp:25468
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:22063
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:24665
reference operator[](T *key)
Definition json.hpp:22422
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:22203
iterator find(KeyType &&key)
find an element in a JSON object
Definition json.hpp:22948
binary_t * binary
binary (stored with pointer to save storage)
Definition json.hpp:20673
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition json.hpp:21615
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.hpp:23099
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:24626
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24992
BooleanType boolean_t
a type for a boolean
Definition json.hpp:20590
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:25326
::nlohmann::detail::internal_iterator< BasicJsonType > internal_iterator
Definition json.hpp:20385
void set_parents()
Definition json.hpp:20944
std::conditional< detail::is_c_string_uncvref< ValueType >::value, string_t, typename std::decay< ValueType >::type > value_return_type
Definition json.hpp:22482
size_type erase_internal(KeyType &&key)
Definition json.hpp:22837
std::less< StringType > default_object_comparator_t
default object key comparator type The actual object key comparator type (object_comparator_t) may be...
Definition json.hpp:20569
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:23443
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition json.hpp:23051
constexpr const number_float_t * get_impl_ptr(const number_float_t *) const noexcept
get a pointer to the value (floating-point number)
Definition json.hpp:21759
reference operator[](typename object_t::key_type key)
access specified object element
Definition json.hpp:22384
string_t * get_impl_ptr(string_t *) noexcept
get a pointer to the value (string)
Definition json.hpp:21705
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:21821
~basic_json() noexcept
destructor
Definition json.hpp:21519
json_value(binary_t &&value)
constructor for rvalue binary arrays (internal type)
Definition json.hpp:20793
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition json.hpp:23120
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:21148
json_value(const object_t &value)
constructor for objects
Definition json.hpp:20772
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.hpp:23823
binary_t & get_binary()
get a binary value
Definition json.hpp:22169
const_iterator begin() const noexcept
returns an iterator to the first element
Definition json.hpp:23044
constexpr bool is_number() const noexcept
return whether value is a number
Definition json.hpp:21594
number_unsigned_t * get_impl_ptr(number_unsigned_t *) noexcept
get a pointer to the value (unsigned number)
Definition json.hpp:21741
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition json.hpp:23650
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:24766
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:22050
const_reference operator[](T *key) const
Definition json.hpp:22428
data(const value_t v)
Definition json.hpp:24523
reference operator[](size_type idx)
access specified array element
Definition json.hpp:22325
basic_json(const JsonRef &ref)
Definition json.hpp:21387
JSONSerializer< T, SFINAE > json_serializer
Definition json.hpp:20407
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:24645
Array get_to(T(&v)[N]) const noexcept(noexcept(JSONSerializer< Array >::from_json(std::declval< const basic_json_t & >(), v)))
Definition json.hpp:22087
NumberIntegerType number_integer_t
a type for a number (integer)
Definition json.hpp:20594
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:21810
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:22287
binary_t * get_impl_ptr(binary_t *) noexcept
get a pointer to the value (binary)
Definition json.hpp:21765
constexpr bool is_binary() const noexcept
return whether value is a binary array
Definition json.hpp:21643
void swap(object_t &other)
exchanges the values
Definition json.hpp:23775
iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
Definition json.hpp:20981
constexpr auto get_impl(detail::priority_tag< 4 >) const noexcept -> decltype(std::declval< const basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:21974
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.hpp:25029
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition json.hpp:23630
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:24674
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:21240
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:23150
bool empty() const noexcept
checks whether the container is empty.
Definition json.hpp:23173
void swap(array_t &other)
exchanges the values
Definition json.hpp:23759
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:22889
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:23380
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.hpp:23012
ValueType get_impl(detail::priority_tag< 1 >) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >())))
get a value (explicit); special case
Definition json.hpp:21913
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.hpp:21559
reference emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:23476
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22592
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.hpp:21251
data() noexcept=default
StringType string_t
a type for a string
Definition json.hpp:20586
ObjectType< StringType, basic_json, default_object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
Definition json.hpp:20578
void push_back(const basic_json &val)
add an object to an array
Definition json.hpp:23388
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:22542
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:22249
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:24889
json_value m_value
the value of the current element
Definition json.hpp:24521
number_integer_t number_integer
number (integer)
Definition json.hpp:20677
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.hpp:23113
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition json.hpp:21587
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:22978
reference front()
access the first element
Definition json.hpp:22661
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:21566
constexpr bool is_null() const noexcept
return whether value is null
Definition json.hpp:21580
void clear() noexcept
clears the contents
Definition json.hpp:23294
constexpr const object_t * get_impl_ptr(const object_t *) const noexcept
get a pointer to the value (object)
Definition json.hpp:21687
json_value(value_t t)
constructor for empty values of a given type
Definition json.hpp:20694
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:24637
json_value()=default
default constructor (for null values)
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:21464
iter_impl< basic_json > iterator
an iterator for a basic_json container
Definition json.hpp:20469
basic_json(const value_t v)
create an empty value with a given type
Definition json.hpp:21056
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:22371
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition json.hpp:20456
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition json.hpp:23572
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition json.hpp:23106
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition json.hpp:20598
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition json.hpp:24468
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:24603
void swap(string_t &other)
exchanges the values
Definition json.hpp:23791
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.hpp:21090
NLOHMANN_BASIC_JSON_TPL basic_json_t
workaround type for MSVC
Definition json.hpp:20362
boolean_t * get_impl_ptr(boolean_t *) noexcept
get a pointer to the value (boolean)
Definition json.hpp:21717
::nlohmann::detail::binary_writer< basic_json, CharType > binary_writer
Definition json.hpp:20397
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition json.hpp:20473
json_value(const binary_t &value)
constructor for binary arrays (internal type)
Definition json.hpp:20790
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:22226
detail::actual_object_comparator_t< basic_json > object_comparator_t
object key comparator type
Definition json.hpp:20610
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:21391
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:23420
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:23501
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:24596
constexpr bool is_object() const noexcept
return whether value is an object
Definition json.hpp:21622
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:24612
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:24781
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition json.hpp:23533
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:21278
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition json.hpp:22996
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:24692
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition json.hpp:22964
boolean_t boolean
boolean
Definition json.hpp:20675
json_value(const typename binary_t::container_type &value)
constructor for binary arrays
Definition json.hpp:20784
::nlohmann::json_pointer< StringType > json_pointer
JSON Pointer, see nlohmann::json_pointer.
Definition json.hpp:20405
an internal type for a backed binary type
Definition json.hpp:6363
bool operator!=(const byte_container_with_subtype &rhs) const
Definition json.hpp:6403
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.hpp:6369
std::uint64_t subtype_type
Definition json.hpp:6366
bool operator==(const byte_container_with_subtype &rhs) const
Definition json.hpp:6397
BinaryType container_type
Definition json.hpp:6365
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6391
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6379
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.hpp:6418
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.hpp:6384
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.hpp:6425
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.hpp:6374
subtype_type m_subtype
Definition json.hpp:6439
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.hpp:6410
bool m_has_subtype
Definition json.hpp:6440
void clear_subtype() noexcept
clears the binary subtype
Definition json.hpp:6432
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:10020
bool get_string(const input_format_t format, const NumberType len, string_t &result)
create a string by reading characters from the input
Definition json.hpp:12857
bool get_ubjson_size_type(std::pair< std::size_t, char_int_type > &result, bool inside_ndarray=false)
determine the type and size for a container
Definition json.hpp:12204
binary_reader(const binary_reader &)=delete
bool parse_bson_array()
Reads an array from the BSON input and passes it to the SAX-parser.
Definition json.hpp:10348
typename BasicJsonType::string_t string_t
Definition json.hpp:10024
bool get_cbor_negative_integer()
Definition json.hpp:10380
std::pair< char_int_type, string_t > bjd_type
Definition json.hpp:13022
bool parse_bson_element_list(const bool is_array)
Read a BSON element list (as specified in the BSON-spec)
Definition json.hpp:10310
typename InputAdapterType::char_type char_type
Definition json.hpp:10027
bool parse_msgpack_internal()
Definition json.hpp:11160
std::string get_token_string() const
Definition json.hpp:12927
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:10022
bool get_msgpack_string(string_t &result)
reads a MessagePack string
Definition json.hpp:11541
std::string exception_message(const input_format_t format, const std::string &detail, const std::string &context) const
Definition json.hpp:12940
InputAdapterType ia
input adapter
Definition json.hpp:12980
bool get_ubjson_high_precision_number()
Definition json.hpp:12662
bool get_binary(const input_format_t format, const NumberType len, binary_t &result)
create a byte array by reading bytes from the input
Definition json.hpp:12890
binary_reader(binary_reader &&)=default
static void byte_swap(NumberType &number)
Definition json.hpp:12785
char_int_type get_ignore_noop()
Definition json.hpp:12773
bool get_ubjson_value(const char_int_type prefix)
Definition json.hpp:12271
bool get_ubjson_ndarray_size(std::vector< size_t > &dim)
Definition json.hpp:11908
bool parse_bson_element_internal(const char_int_type element_type, const std::size_t element_type_parse_position)
Read a BSON document element of the given element_type.
Definition json.hpp:10224
bool get_msgpack_object(const std::size_t len)
Definition json.hpp:11757
typename char_traits< char_type >::int_type char_int_type
Definition json.hpp:10028
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.hpp:10036
typename BasicJsonType::binary_t binary_t
Definition json.hpp:10025
bool parse_bson_internal()
Reads in a BSON-object and passes it to the SAX-parser.
Definition json.hpp:10120
binary_reader & operator=(const binary_reader &)=delete
bool get_cbor_object(const std::size_t len, const cbor_tag_handler_t tag_handler)
Definition json.hpp:11104
bool get_cbor_binary(binary_t &result)
reads a CBOR byte array
Definition json.hpp:10971
bool get_number(const input_format_t format, NumberType &result)
Definition json.hpp:12827
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:10021
bool get_ubjson_array()
Definition json.hpp:12464
bool get_bson_cstr(string_t &result)
Parses a C-style string from the BSON input.
Definition json.hpp:10145
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:10057
bool get_cbor_array(const std::size_t len, const cbor_tag_handler_t tag_handler)
Definition json.hpp:11066
bool get_msgpack_array(const std::size_t len)
Definition json.hpp:11735
char_int_type get()
get next character from the input
Definition json.hpp:12741
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:10023
bool get_msgpack_binary(binary_t &result)
reads a MessagePack byte array
Definition json.hpp:11624
bool parse_ubjson_internal(const bool get_char=true)
Definition json.hpp:11794
SAX json_sax_t
Definition json.hpp:10026
bool get_ubjson_size_value(std::size_t &result, bool &is_ndarray, char_int_type prefix=0)
Definition json.hpp:11973
bool parse_cbor_internal(const bool get_char, const cbor_tag_handler_t tag_handler)
Definition json.hpp:10397
bool get_ubjson_object()
Definition json.hpp:12579
bool get_bson_string(const NumberType len, string_t &result)
Parses a zero-terminated string of length len from the BSON input.
Definition json.hpp:10175
bool get_ubjson_string(string_t &result, const bool get_char=true)
reads a UBJSON string
Definition json.hpp:11813
bool get_to(T &dest, const input_format_t format, const char *context)
get_to read into a primitive type
Definition json.hpp:12756
bool get_cbor_string(string_t &result)
reads a CBOR string
Definition json.hpp:10875
bool get_bson_binary(const NumberType len, binary_t &result)
Parses a byte array input of length len from the BSON input.
Definition json.hpp:10197
binary_reader & operator=(binary_reader &&)=default
serialization to CBOR and MessagePack values
Definition json.hpp:15997
void write_bson_binary(const string_t &name, const binary_t &value)
Writes a BSON element with key name and binary value value.
Definition json.hpp:17110
void write_bson_boolean(const string_t &name, const bool value)
Writes a BSON element with key name and boolean value value.
Definition json.hpp:16947
void write_bson(const BasicJsonType &j)
Definition json.hpp:16017
typename BasicJsonType::binary_t binary_t
Definition json.hpp:15999
void write_bson_integer(const string_t &name, const std::int64_t value)
Writes a BSON element with key name and integer value.
Definition json.hpp:17007
typename BasicJsonType::string_t string_t
Definition json.hpp:15998
static constexpr CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:17757
static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
Definition json.hpp:17025
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:16697
void write_bson_array(const string_t &name, const typename BasicJsonType::array_t &value)
Writes a BSON element with key name and array value.
Definition json.hpp:17091
static CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:17764
static constexpr CharType get_cbor_float_prefix(double)
Definition json.hpp:17256
void write_bson_string(const string_t &name, const string_t &value)
Writes a BSON element with key name and string value value.
Definition json.hpp:16975
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition json.hpp:16008
static constexpr CharType get_ubjson_float_prefix(double)
Definition json.hpp:17571
void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix, const bool use_bjdata)
Definition json.hpp:17282
static constexpr CharType get_msgpack_float_prefix(double)
Definition json.hpp:17270
void write_bson_element(const string_t &name, const BasicJsonType &j)
Serializes the JSON value j to BSON and associates it with the key name.
Definition json.hpp:17173
static constexpr CharType to_char_type(InputCharType x) noexcept
Definition json.hpp:17799
void write_bson_object(const typename BasicJsonType::object_t &value)
Definition json.hpp:17235
void write_bson_double(const string_t &name, const double value)
Writes a BSON element with key name and double value value.
Definition json.hpp:16957
static std::size_t calc_bson_string_size(const string_t &value)
Definition json.hpp:16967
void write_number(const NumberType n, const bool OutputIsLittleEndian=false)
Definition json.hpp:17707
static std::size_t calc_bson_entry_header_size(const string_t &name, const BasicJsonType &j)
Definition json.hpp:16920
void write_bson_null(const string_t &name)
Writes a BSON element with key name and null value.
Definition json.hpp:16989
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:16000
CharType ubjson_prefix(const BasicJsonType &j, const bool use_bjdata) const noexcept
determine the type prefix of container values
Definition json.hpp:17465
void write_bson_unsigned(const string_t &name, const BasicJsonType &j)
Writes a BSON element with key name and unsigned value.
Definition json.hpp:17035
static constexpr CharType get_ubjson_float_prefix(float)
Definition json.hpp:17566
static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t &value)
Definition json.hpp:17083
bool write_bjdata_ndarray(const typename BasicJsonType::object_t &value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
Definition json.hpp:17579
static std::size_t calc_bson_element_size(const string_t &name, const BasicJsonType &j)
Calculates the size necessary to serialize the JSON value j with its name.
Definition json.hpp:17125
void write_msgpack(const BasicJsonType &j)
Definition json.hpp:16370
static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t &value)
Calculates the size of the BSON serialization of the given JSON-object j.
Definition json.hpp:17220
void write_compact_float(const number_float_t n, detail::input_format_t format)
Definition json.hpp:17723
void write_cbor(const BasicJsonType &j)
Definition json.hpp:16046
static constexpr CharType get_cbor_float_prefix(float)
Definition json.hpp:17251
void write_bson_entry_header(const string_t &name, const std::uint8_t element_type)
Writes the given element_type and name to the output adapter.
Definition json.hpp:16935
void write_bson_object_entry(const string_t &name, const typename BasicJsonType::object_t &value)
Writes a BSON element with key name and object value.
Definition json.hpp:17058
static constexpr CharType get_msgpack_float_prefix(float)
Definition json.hpp:17265
static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t &value)
Definition json.hpp:17068
static std::size_t calc_bson_integer_size(const std::int64_t value)
Definition json.hpp:16997
general exception of the basic_json class
Definition json.hpp:4581
static std::string get_byte_positions(const BasicJsonType *leaf_element)
Definition json.hpp:4686
const int id
the id of the exception
Definition json.hpp:4590
static std::string diagnostics(std::nullptr_t)
Definition json.hpp:4601
std::runtime_error m
an exception object as storage for error messages
Definition json.hpp:4673
static std::string name(const std::string &ename, int id_)
Definition json.hpp:4596
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:4584
static std::string diagnostics(const BasicJsonType *leaf_element)
Definition json.hpp:4607
Definition json.hpp:6666
char char_type
Definition json.hpp:6668
file_input_adapter(const file_input_adapter &)=delete
std::FILE * m_file
the file pointer to read from
Definition json.hpp:6698
std::char_traits< char >::int_type get_character() noexcept
Definition json.hpp:6684
file_input_adapter(file_input_adapter &&) noexcept=default
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6691
Definition json.hpp:6711
input_stream_adapter & operator=(input_stream_adapter &&)=delete
std::istream * is
the associated input stream
Definition json.hpp:6768
input_stream_adapter(input_stream_adapter &&rhs) noexcept
Definition json.hpp:6734
~input_stream_adapter()
Definition json.hpp:6715
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6756
std::char_traits< char >::int_type get_character()
Definition json.hpp:6744
char char_type
Definition json.hpp:6713
input_stream_adapter(const input_stream_adapter &)=delete
std::streambuf * sb
Definition json.hpp:6769
input_stream_adapter & operator=(input_stream_adapter &)=delete
input_stream_adapter(std::istream &i)
Definition json.hpp:6725
exception indicating errors with iterators
Definition json.hpp:4750
static invalid_iterator create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4753
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition json.hpp:13816
~iter_impl()=default
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:14399
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:13953
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:14344
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:13943
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:14286
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:14326
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:14390
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:14196
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:14499
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.hpp:14237
iter_impl operator++(int) &
post-increment (it++)
Definition json.hpp:14134
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:14353
reference operator[](difference_type n) const
access to successor
Definition json.hpp:14461
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition json.hpp:13846
pointer operator->() const
dereference the iterator
Definition json.hpp:14092
friend other_iter_impl
allow basic_json to access private members
Definition json.hpp:13820
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
Definition json.hpp:14524
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:14432
iter_impl(iter_impl &&) noexcept=default
std::bidirectional_iterator_tag iterator_category
Definition json.hpp:13841
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:14410
reference value() const
return the value of an iterator
Definition json.hpp:14515
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:14335
typename BasicJsonType::array_t array_t
Definition json.hpp:13826
typename BasicJsonType::object_t object_t
Definition json.hpp:13825
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition json.hpp:13850
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:14145
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition json.hpp:13844
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:14048
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:14421
iter_impl()=default
friend BasicJsonType
Definition json.hpp:13821
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.hpp:13928
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition json.hpp:14277
iter_impl operator--(int) &
post-decrement (it–)
Definition json.hpp:14185
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition json.hpp:13855
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.hpp:13918
void set_end() noexcept
set the iterator past the last value
Definition json.hpp:14009
Definition json.hpp:5625
iteration_proxy_value operator++(int) &
Definition json.hpp:5681
iteration_proxy_value(iteration_proxy_value const &)=default
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.hpp:5690
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.hpp:5696
std::ptrdiff_t difference_type
Definition json.hpp:5627
string_type empty_str
an empty string (to return a reference for primitive values)
Definition json.hpp:5644
iteration_proxy_value(IteratorType it, std::size_t array_index_=0) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_default_constructible< string_type >::value)
Definition json.hpp:5648
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:5673
std::forward_iterator_tag iterator_category
Definition json.hpp:5631
std::size_t array_index_last
last stringified array index
Definition json.hpp:5640
std::size_t array_index
an index for arrays (used to create key names)
Definition json.hpp:5638
iteration_proxy_value(iteration_proxy_value &&) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_move_constructible< string_type >::value)=default
IteratorType::reference value() const
return value of the iterator
Definition json.hpp:5738
const string_type & key() const
return key of the iterator
Definition json.hpp:5702
iteration_proxy_value & operator=(iteration_proxy_value const &)=default
string_type array_index_str
a string representation of the array index
Definition json.hpp:5642
typename std::remove_cv< typename std::remove_reference< decltype(std::declval< IteratorType >().key()) >::type >::type string_type
Definition json.hpp:5632
IteratorType anchor
the iterator
Definition json.hpp:5636
proxy class for the items() function
Definition json.hpp:5746
IteratorType::pointer container
the container to iterate
Definition json.hpp:5749
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.hpp:5771
iteration_proxy(iteration_proxy const &)=default
iteration_proxy(iteration_proxy &&) noexcept=default
iteration_proxy_value< IteratorType > begin() const noexcept
return iterator begin (needed for range-based for)
Definition json.hpp:5765
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:5755
iteration_proxy & operator=(iteration_proxy const &)=default
Definition json.hpp:6777
IteratorType end
Definition json.hpp:6819
bool empty() const
Definition json.hpp:6824
char_traits< char_type >::int_type get_character()
Definition json.hpp:6785
iterator_input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:6781
typename std::iterator_traits< IteratorType >::value_type char_type
Definition json.hpp:6779
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6799
IteratorType current
Definition json.hpp:6818
Definition json.hpp:15729
json_ref(json_ref &&) noexcept=default
json_ref(const value_type &value)
Definition json.hpp:15737
json_ref(value_type &&value)
Definition json.hpp:15733
value_type const & operator*() const
Definition json.hpp:15768
value_type const * operator->() const
Definition json.hpp:15773
json_ref(std::initializer_list< json_ref > init)
Definition json.hpp:15741
json_ref(Args &&... args)
Definition json.hpp:15748
value_type moved_or_copied() const
Definition json.hpp:15759
BasicJsonType value_type
Definition json.hpp:15731
a template for a reverse iterator class
Definition json.hpp:14578
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition json.hpp:14594
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition json.hpp:14606
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.hpp:14600
std::ptrdiff_t difference_type
Definition json.hpp:14580
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.hpp:14618
reference operator[](difference_type n) const
access to successor
Definition json.hpp:14642
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.hpp:14648
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.hpp:14636
typename Base::reference reference
the reference type for the pointed-to element
Definition json.hpp:14584
reference value() const
return the value of an iterator
Definition json.hpp:14655
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.hpp:14591
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.hpp:14612
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.hpp:14582
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.hpp:14630
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.hpp:14587
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.hpp:14624
Definition json.hpp:9735
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9738
bool end_object()
Definition json.hpp:9788
bool binary(binary_t &)
Definition json.hpp:9773
bool number_integer(number_integer_t)
Definition json.hpp:9753
bool start_array(std::size_t=detail::unknown_size())
Definition json.hpp:9793
bool boolean(bool)
Definition json.hpp:9748
bool null()
Definition json.hpp:9743
bool end_array()
Definition json.hpp:9798
bool number_unsigned(number_unsigned_t)
Definition json.hpp:9758
bool start_object(std::size_t=detail::unknown_size())
Definition json.hpp:9778
bool string(string_t &)
Definition json.hpp:9768
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9741
bool number_float(number_float_t, const string_t &)
Definition json.hpp:9763
bool parse_error(std::size_t, const std::string &, const detail::exception &)
Definition json.hpp:9803
bool key(string_t &)
Definition json.hpp:9783
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9737
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9739
typename BasicJsonType::string_t string_t
Definition json.hpp:9740
Definition json.hpp:9298
bool start_array(std::size_t len)
Definition json.hpp:9466
typename BasicJsonType::parser_callback_t parser_callback_t
Definition json.hpp:9305
bool null()
Definition json.hpp:9325
typename BasicJsonType::parse_event_t parse_event_t
Definition json.hpp:9306
json_sax_dom_callback_parser & operator=(json_sax_dom_callback_parser &&)=default
bool number_integer(number_integer_t val)
Definition json.hpp:9337
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:9545
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9302
json_sax_dom_callback_parser & operator=(const json_sax_dom_callback_parser &)=delete
bool end_object()
Definition json.hpp:9416
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:9343
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:9349
constexpr bool is_errored() const
Definition json.hpp:9557
json_sax_dom_callback_parser(BasicJsonType &r, parser_callback_t cb, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.hpp:9309
bool binary(binary_t &val)
Definition json.hpp:9361
typename BasicJsonType::string_t string_t
Definition json.hpp:9303
bool boolean(bool val)
Definition json.hpp:9331
bool key(string_t &val)
Definition json.hpp:9399
bool string(string_t &val)
Definition json.hpp:9355
json_sax_dom_callback_parser(json_sax_dom_callback_parser &&)=default
BasicJsonType & root
the parsed JSON value
Definition json.hpp:9712
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9301
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9300
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9304
bool end_array()
Definition json.hpp:9498
bool start_object(std::size_t len)
Definition json.hpp:9367
std::pair< bool, BasicJsonType * > handle_value(Value &&v, const bool skip_callback=false)
Definition json.hpp:9644
json_sax_dom_callback_parser(const json_sax_dom_callback_parser &)=delete
SAX implementation to create a JSON value from SAX events.
Definition json.hpp:8992
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:9041
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:9035
json_sax_dom_parser(const json_sax_dom_parser &)=delete
json_sax_dom_parser & operator=(const json_sax_dom_parser &)=delete
bool binary(binary_t &val)
Definition json.hpp:9053
typename BasicJsonType::binary_t binary_t
Definition json.hpp:8998
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.hpp:9006
bool start_object(std::size_t len)
Definition json.hpp:9059
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:8994
bool key(string_t &val)
Definition json.hpp:9082
bool end_object()
Definition json.hpp:9092
typename BasicJsonType::string_t string_t
Definition json.hpp:8997
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:8995
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:9150
bool boolean(bool val)
Definition json.hpp:9023
bool start_array(std::size_t len)
Definition json.hpp:9110
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:8996
JSON_HEDLEY_RETURNS_NON_NULL BasicJsonType * handle_value(Value &&v)
Definition json.hpp:9245
BasicJsonType & root
the parsed JSON value
Definition json.hpp:9283
bool end_array()
Definition json.hpp:9131
json_sax_dom_parser(json_sax_dom_parser &&)=default
constexpr bool is_errored() const
Definition json.hpp:9162
bool null()
Definition json.hpp:9017
bool string(string_t &val)
Definition json.hpp:9047
json_sax_dom_parser & operator=(json_sax_dom_parser &&)=default
bool number_integer(number_integer_t val)
Definition json.hpp:9029
Definition json.hpp:7228
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:7255
token_type
token types for the parser
Definition json.hpp:7232
@ value_float
an floating point number – use get_number_float() for actual value
@ begin_array
the character for array begin [
@ value_string
a string – use get_string() for actual value
@ end_array
the character for array end ]
@ uninitialized
indicating the scanner is uninitialized
@ parse_error
indicating a parse error
@ value_integer
a signed integer – use get_number_integer() for actual value
@ value_separator
the value separator ,
@ end_object
the character for object end }
@ literal_true
the true literal
@ begin_object
the character for object begin {
@ value_unsigned
an unsigned integer – use get_number_unsigned() for actual value
@ literal_null
the null literal
@ end_of_input
indicating the end of the input buffer
@ name_separator
the name separator :
@ literal_or_value
a literal or the begin of a value (only for diagnostics)
@ literal_false
the false literal
lexical analysis
Definition json.hpp:7305
void reset() noexcept
reset token_buffer; current character is beginning of token
Definition json.hpp:8519
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.hpp:8691
string_t token_buffer
buffer for variable-length tokens (numbers, strings)
Definition json.hpp:8822
int get_codepoint()
get codepoint from 4 hex characters following \u
Definition json.hpp:7362
token_type scan_string()
scan a string literal
Definition json.hpp:7447
number_integer_t value_integer
Definition json.hpp:8828
void skip_whitespace()
Definition json.hpp:8705
const bool ignore_comments
whether comments should be ignored (true) or signaled as errors (false)
Definition json.hpp:8807
lexer(InputAdapterType &&adapter, bool ignore_comments_=false) noexcept
Definition json.hpp:7316
char_int_type current
the current character
Definition json.hpp:8810
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.hpp:8678
std::string get_token_string() const
Definition json.hpp:8653
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:7308
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.hpp:8612
typename BasicJsonType::string_t string_t
Definition json.hpp:7309
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:7307
bool next_byte_in_range(std::initializer_list< char_int_type > ranges)
check if the next byte(s) are inside a given range
Definition json.hpp:7410
char_int_type get()
Definition json.hpp:8537
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.hpp:8645
static void strtof(float &f, const char *str, char **endptr) noexcept
Definition json.hpp:8109
const char_int_type decimal_point_char
the decimal point
Definition json.hpp:8833
number_unsigned_t value_unsigned
Definition json.hpp:8829
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:7306
token_type scan()
Definition json.hpp:8714
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.hpp:8618
typename char_traits< char_type >::int_type char_int_type
Definition json.hpp:7311
bool scan_comment()
scan a comment
Definition json.hpp:8037
typename lexer_base< BasicJsonType >::token_type token_type
Definition json.hpp:7314
lexer(lexer &&)=default
~lexer()=default
const char * error_message
a description of occurred lexer errors
Definition json.hpp:8825
lexer & operator=(lexer &&)=default
bool next_unget
whether the next get() call should just return current
Definition json.hpp:8813
lexer(const lexer &)=delete
std::size_t decimal_point_position
the position of the decimal point in the input
Definition json.hpp:8835
typename InputAdapterType::char_type char_type
Definition json.hpp:7310
InputAdapterType ia
input adapter
Definition json.hpp:8804
lexer & operator=(lexer &)=delete
token_type scan_number()
scan a number literal
Definition json.hpp:8166
number_float_t value_float
Definition json.hpp:8830
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.hpp:8630
token_type scan_literal(const char_type *literal_text, const std::size_t length, token_type return_type)
Definition json.hpp:8499
std::vector< char_type > token_string
raw input token string (for error messages)
Definition json.hpp:8819
void add(char_int_type c)
add a character to token_buffer
Definition json.hpp:8601
position_t position
the start position of the current token
Definition json.hpp:8816
void unget()
unget current character (read it again on next get)
Definition json.hpp:8574
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.hpp:8624
static JSON_HEDLEY_PURE char get_decimal_point() noexcept
return the locale-dependent decimal point
Definition json.hpp:7336
exception indicating other library errors
Definition json.hpp:4802
static other_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4805
exception indicating access out of the defined range
Definition json.hpp:4785
static out_of_range create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4788
Definition json.hpp:15948
output_adapter(StringType &s)
Definition json.hpp:15959
output_adapter(std::basic_ostream< CharType > &s)
Definition json.hpp:15955
output_adapter(std::vector< CharType, AllocatorType > &vec)
Definition json.hpp:15951
output adapter for output streams
Definition json.hpp:15900
output_stream_adapter(std::basic_ostream< CharType > &s) noexcept
Definition json.hpp:15902
void write_character(CharType c) override
Definition json.hpp:15906
std::basic_ostream< CharType > & stream
Definition json.hpp:15918
output adapter for basic_string
Definition json.hpp:15925
void write_character(CharType c) override
Definition json.hpp:15931
output_string_adapter(StringType &s) noexcept
Definition json.hpp:15927
StringType & str
Definition json.hpp:15943
output adapter for byte vectors
Definition json.hpp:15875
std::vector< CharType, AllocatorType > & v
Definition json.hpp:15893
output_vector_adapter(std::vector< CharType, AllocatorType > &vec) noexcept
Definition json.hpp:15877
void write_character(CharType c) override
Definition json.hpp:15881
exception indicating a parse error
Definition json.hpp:4697
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:4709
static std::string position_string(const position_t &pos)
Definition json.hpp:4740
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4717
const std::size_t byte
byte index of the parse error
Definition json.hpp:4734
parse_error(int id_, std::size_t byte_, const char *what_arg)
Definition json.hpp:4737
syntax analysis
Definition json.hpp:13112
std::string exception_message(const token_type expected, const std::string &context)
Definition json.hpp:13544
typename lexer_t::token_type token_type
Definition json.hpp:13118
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.hpp:13146
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:13114
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:13113
typename BasicJsonType::string_t string_t
Definition json.hpp:13116
lexer_t m_lexer
the lexer
Definition json.hpp:13579
bool accept(const bool strict=true)
public accept interface
Definition json.hpp:13206
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:13115
token_type get_token()
get next token from lexer
Definition json.hpp:13539
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:13122
Definition json.hpp:13633
primitive_iterator_t & operator++() noexcept
Definition json.hpp:13695
primitive_iterator_t & operator-=(difference_type n) noexcept
Definition json.hpp:13727
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition json.hpp:13662
primitive_iterator_t & operator--() noexcept
Definition json.hpp:13708
void set_end() noexcept
set iterator to a defined past the end
Definition json.hpp:13656
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13678
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition json.hpp:13668
primitive_iterator_t operator++(int) &noexcept
Definition json.hpp:13701
primitive_iterator_t & operator+=(difference_type n) noexcept
Definition json.hpp:13721
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13673
constexpr difference_type get_value() const noexcept
Definition json.hpp:13644
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13690
primitive_iterator_t operator+(difference_type n) noexcept
Definition json.hpp:13683
void set_begin() noexcept
set iterator to a defined beginning
Definition json.hpp:13650
primitive_iterator_t operator--(int) &noexcept
Definition json.hpp:13714
std::ptrdiff_t difference_type
Definition json.hpp:13635
Definition json.hpp:18996
typename BasicJsonType::binary_t::value_type binary_char_t
Definition json.hpp:19001
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:19000
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:19011
serializer & operator=(const serializer &)=delete
~serializer()=default
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition json.hpp:19928
string_t indent_string
the indentation string
Definition json.hpp:19925
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:18999
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:18998
serializer & operator=(serializer &&)=delete
typename BasicJsonType::string_t string_t
Definition json.hpp:18997
const char indent_char
the indentation character
Definition json.hpp:19923
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:19051
serializer(const serializer &)=delete
serializer(serializer &&)=delete
Definition json.hpp:7139
span_input_adapter(CharT b, std::size_t l)
Definition json.hpp:7147
contiguous_bytes_input_adapter ia
Definition json.hpp:7163
span_input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:7154
contiguous_bytes_input_adapter && get()
Definition json.hpp:7157
exception indicating executing a member function with a wrong type
Definition json.hpp:4768
static type_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4771
Definition json.hpp:6956
std::size_t get_elements(T *, std::size_t=1)
Definition json.hpp:6982
std::char_traits< char >::int_type get_character() noexcept
Definition json.hpp:6963
std::array< std::char_traits< char >::int_type, 4 > utf8_bytes
a buffer for UTF-8 bytes
Definition json.hpp:6997
std::size_t utf8_bytes_filled
number of valid bytes in the utf8_codes array
Definition json.hpp:7002
BaseInputAdapter base_adapter
Definition json.hpp:6988
wide_string_input_adapter(BaseInputAdapter base)
Definition json.hpp:6960
char char_type
Definition json.hpp:6958
std::size_t utf8_bytes_index
index to the utf8_codes array for the next valid byte
Definition json.hpp:7000
void fill_buffer()
Definition json.hpp:6991
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition json.hpp:14750
BasicJsonType & get_checked(BasicJsonType *ptr) const
Definition json.hpp:15136
json_pointer< string_t > convert() const &
Definition json.hpp:15549
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:14845
static BasicJsonType::size_type array_index(const string_t &s)
Definition json.hpp:14928
typename string_t_helper< RefStringType >::type string_t
Definition json.hpp:14772
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:14852
result reference_tokens
Definition json.hpp:14974
json_pointer(const string_t &s="")
create JSON pointer
Definition json.hpp:14776
static std::vector< string_t > split(const string_t &reference_string)
split the string input to reference tokens
Definition json.hpp:15380
bool empty() const noexcept
return whether pointer points to the root document
Definition json.hpp:14911
BasicJsonType & get_and_create(BasicJsonType &j) const
create and return a reference to the pointed to value
Definition json.hpp:14988
void pop_back()
remove last reference token
Definition json.hpp:14873
string_t to_string() const
return a string representation of the JSON pointer
Definition json.hpp:14782
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition json.hpp:14830
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14904
json_pointer< string_t > convert() &&
Definition json.hpp:15556
std::vector< string_t > reference_tokens
the reference tokens
Definition json.hpp:15639
return result
Definition json.hpp:14975
static void flatten(const string_t &reference_string, const BasicJsonType &value, BasicJsonType &result)
Definition json.hpp:15449
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition json.hpp:14812
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:14837
BasicJsonType & get_unchecked(BasicJsonType *ptr) const
return a reference to the pointed to value
Definition json.hpp:15068
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition json.hpp:14859
static BasicJsonType unflatten(const BasicJsonType &value)
Definition json.hpp:15521
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition json.hpp:14822
const string_t & back() const
return last reference token
Definition json.hpp:14885
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition json.hpp:14803
const BasicJsonType & get_unchecked(const BasicJsonType *ptr) const
return a const reference to the pointed to value
Definition json.hpp:15194
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14897
const BasicJsonType & get_checked(const BasicJsonType *ptr) const
Definition json.hpp:15243
bool contains(const BasicJsonType *ptr) const
Definition json.hpp:15292
decltype(get< N >(std::declval< ::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
Definition json.hpp:5819
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
Definition json.hpp:2623
#define JSON_HEDLEY_CONST
Definition json.hpp:1830
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
Definition json.hpp:1114
#define JSON_INLINE_VARIABLE
Definition json.hpp:2522
#define JSON_HEDLEY_WARN_UNUSED_RESULT
Definition json.hpp:1460
#define JSON_PRIVATE_UNLESS_TESTED
Definition json.hpp:2582
#define JSON_HEDLEY_UNREACHABLE()
Definition json.hpp:1591
#define NLOHMANN_JSON_VERSION_PATCH
Definition json.hpp:70
#define JSON_HEDLEY_LIKELY(expr)
Definition json.hpp:1725
#define JSON_HEDLEY_NON_NULL(...)
Definition json.hpp:1618
#define JSON_INTERNAL_CATCH(exception)
Definition json.hpp:2549
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition json.hpp:25500
#define JSON_HEDLEY_RETURNS_NON_NULL
Definition json.hpp:2059
bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15645
#define JSON_CATCH(exception)
Definition json.hpp:2548
#define JSON_ASSERT(x)
Definition json.hpp:2575
#define JSON_THROW(exception)
Definition json.hpp:2546
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
Definition json.hpp:81
#define NLOHMANN_JSON_VERSION_MAJOR
Definition json.hpp:68
#define NLOHMANN_BASIC_JSON_TPL
Definition json.hpp:2633
#define JSON_HEDLEY_UNLIKELY(expr)
Definition json.hpp:1726
#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
Definition json.hpp:13001
#define JSON_TRY
Definition json.hpp:2547
#define NLOHMANN_JSON_NAMESPACE_END
Definition json.hpp:155
#define JSON_NO_UNIQUE_ADDRESS
Definition json.hpp:2528
bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15670
#define NLOHMANN_JSON_VERSION_MINOR
Definition json.hpp:69
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)
Definition json.hpp:2917
#define NLOHMANN_JSON_NAMESPACE_BEGIN
Definition json.hpp:145
#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
Definition json.hpp:12998
#define JSON_HEDLEY_DIAGNOSTIC_POP
Definition json.hpp:1115
#define JSON_EXPLICIT
Definition json.hpp:2954
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
Definition json.hpp:1408
#define JSON_HEDLEY_PURE
Definition json.hpp:1799
bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15695
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)
Definition json.hpp:23848
#define JSON_DIAGNOSTIC_POSITIONS
Definition json.hpp:77
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
Definition json.hpp:18335
cached_power get_cached_power_for_binary_exponent(int e)
Definition json.hpp:18171
Target reinterpret_bits(const Source source)
Definition json.hpp:17891
boundaries compute_boundaries(FloatType value)
Definition json.hpp:18032
void grisu2_round(char *buf, int len, std::uint64_t dist, std::uint64_t delta, std::uint64_t rest, std::uint64_t ten_k)
Definition json.hpp:18389
constexpr int kAlpha
Definition json.hpp:18154
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition json.hpp:18671
constexpr int kGamma
Definition json.hpp:18155
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition json.hpp:18430
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition json.hpp:18771
constexpr bool is_transparent()
Definition json.hpp:4391
constexpr bool is_c_string()
Definition json.hpp:4363
detail namespace with internal helper functions
Definition json.hpp:260
std::tuple< decltype(from_json_tuple_get_impl(std::declval< BasicJsonType >(), detail::identity_tag< Types > {}, detail::priority_tag< PTagValue > {}))... > tuple_type
Definition json.hpp:5385
input_format_t
the supported input formats
Definition json.hpp:6654
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
Definition json.hpp:6234
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
Definition json.hpp:320
typename make_void< Ts... >::type void_t
Definition json.hpp:266
decltype(std::declval< T & >().start_array(std::declval< std::size_t >())) start_array_function_t
Definition json.hpp:9882
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition json.hpp:15870
decltype(std::declval< StringType & >()+=std::declval< Arg && >()) string_can_append_op
Definition json.hpp:4472
decltype(std::declval< T & >().parse_error(std::declval< std::size_t >(), std::declval< const std::string & >(), std::declval< const Exception & >())) parse_error_function_t
Definition json.hpp:9890
std::function< bool(int, parse_event_t, BasicJsonType &)> parser_callback_t
Definition json.hpp:13103
OutStringType concat(Args &&... args)
Definition json.hpp:4546
is_detected< string_can_append_iter, StringType, Arg > detect_string_can_append_iter
Definition json.hpp:4481
decltype(T::to_json(std::declval< Args >()...)) to_json_function
Definition json.hpp:3650
constexpr std::array< T, sizeof...(Args)> make_array(Args &&... args)
Definition json.hpp:3353
decltype(std::declval< T >().template get< U >()) get_template_function
Definition json.hpp:3656
typename T::pointer pointer_t
Definition json.hpp:3641
parse_event_t
Definition json.hpp:13086
@ value
the parser finished reading a JSON value
@ key
the parser read a key of a value in an object
@ array_end
the parser read ] and finished processing a JSON array
@ array_start
the parser read [ and started to process a JSON array
@ object_start
the parser read { and started to process a JSON object
@ object_end
the parser read } and finished processing a JSON object
is_detected< string_can_append_op, StringType, Arg > detect_string_can_append_op
Definition json.hpp:4475
std::pair< A1, A2 > from_json_tuple_impl(BasicJsonType &&j, identity_tag< std::pair< A1, A2 > >, priority_tag< 0 >)
Definition json.hpp:5400
void from_json_array_impl(const BasicJsonType &j, typename BasicJsonType::array_t &arr, priority_tag< 3 >)
Definition json.hpp:5182
typename utility_internal::Gen< T, N >::type make_integer_sequence
Definition json.hpp:3314
typename T::value_type value_type_t
Definition json.hpp:3635
tuple_type< PTagValue, BasicJsonType, Args... > from_json_tuple_impl_base(BasicJsonType &&j, index_sequence< Idx... >)
Definition json.hpp:5388
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
Definition json.hpp:324
void int_to_string(StringType &target, std::size_t value)
Definition json.hpp:5599
T conditional_static_cast(U value)
Definition json.hpp:4247
is_detected< string_can_append_data, StringType, Arg > detect_string_can_append_data
Definition json.hpp:4487
typename std::enable_if< B, T >::type enable_if_t
Definition json.hpp:3226
decltype(std::declval< T & >().number_integer(std::declval< Integer >())) number_integer_function_t
Definition json.hpp:9851
typename T::mapped_type mapped_type_t
Definition json.hpp:3629
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.hpp:3102
decltype(std::declval< T & >().number_float(std::declval< Float >(), std::declval< const String & >())) number_float_function_t
Definition json.hpp:9859
enable_if_t< is_range< R >::value, result_of_begin< decltype(std::declval< R & >())> > iterator_t
Definition json.hpp:3901
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition json.hpp:5781
bool little_endianness(int num=1) noexcept
determine system byte order
Definition json.hpp:10006
cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:9993
@ store
store tags as binary type
@ error
throw a parse_error exception in case of a tag
typename detected_or< Default, Op, Args... >::type detected_or_t
Definition json.hpp:317
decltype(T::from_json(std::declval< Args >()...)) from_json_function
Definition json.hpp:3653
decltype(input_adapter(std::declval< const char * >(), std::declval< const char * >())) contiguous_bytes_input_adapter
Definition json.hpp:7108
make_integer_sequence< size_t, N > make_index_sequence
Definition json.hpp:3322
std::integral_constant< bool, Value > bool_constant
Definition json.hpp:4353
void concat_into(OutStringType &)
Definition json.hpp:4462
typename T::key_type key_type_t
Definition json.hpp:3632
constexpr bool value_in_range_of(T val)
Definition json.hpp:4347
value_t
the JSON type enumeration
Definition json.hpp:3004
@ null
null value
@ number_integer
number value (signed integer)
@ boolean
boolean value
@ discarded
discarded by the parser callback function
@ binary
binary array (ordered collection of bytes)
@ object
object (unordered set of name/value pairs)
@ string
string value
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
std::integral_constant< bool, all_signed< Types... >::value||all_unsigned< Types... >::value > same_sign
Definition json.hpp:4270
constexpr std::size_t unknown_size()
Definition json.hpp:8972
decltype(std::declval< T & >().binary(std::declval< Binary & >())) binary_function_t
Definition json.hpp:9867
std::array< T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType &&j, identity_tag< std::array< T, sizeof...(Idx)> >, index_sequence< Idx... >)
Definition json.hpp:5265
StringType to_string(std::size_t value)
Definition json.hpp:5607
typename detector< nonesuch, void, Op, Args... >::type detected_t
Definition json.hpp:311
typename std::conditional< is_comparable< Comparator, ObjectKeyType, KeyTypeCVRef >::value &&!(ExcludeObjectKeyType &&std::is_same< KeyType, ObjectKeyType >::value) &&(!RequireTransparentComparator||is_detected< detect_is_transparent, Comparator >::value) &&!is_json_pointer< KeyType >::value, std::true_type, std::false_type >::type is_usable_as_key_type
Definition json.hpp:4194
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition json.hpp:6494
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().begin(), std::declval< const Arg & >().end())) string_can_append_iter
Definition json.hpp:4478
typename T::iterator_category iterator_category_t
Definition json.hpp:3647
void unescape(StringType &s)
string unescaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3136
decltype(input_adapter(std::declval< std::string >())) string_input_adapter_type
Definition json.hpp:7084
std::size_t combine(std::size_t seed, std::size_t h) noexcept
Definition json.hpp:6476
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:3033
typename std::conditional<(is_usable_as_key_type< typename BasicJsonType::object_comparator_t, typename BasicJsonType::object_t::key_type, KeyTypeCVRef, RequireTransparentComparator, ExcludeObjectKeyType >::value &&!is_json_iterator_of< BasicJsonType, KeyType >::value), std::true_type, std::false_type >::type is_usable_as_basic_json_key_type
Definition json.hpp:4213
iterator_input_adapter_factory< IteratorType >::adapter_type input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:7044
decltype(std::declval< T & >().end_array()) end_array_function_t
Definition json.hpp:9885
typename std::conditional< is_detected< detect_erase_with_key_type, typename BasicJsonType::object_t, KeyType >::value, std::true_type, std::false_type >::type has_erase_with_key_type
Definition json.hpp:4225
error_handler_t
how to treat decoding errors
Definition json.hpp:18988
@ strict
throw a type_error exception in case of invalid UTF-8
@ replace
replace invalid UTF-8 sequences with U+FFFD
std::size_t concat_length()
Definition json.hpp:4431
value_type_t< iterator_traits< iterator_t< T > > > range_value_t
Definition json.hpp:3904
void from_json(const BasicJsonType &j, typename std::nullptr_t &n)
Definition json.hpp:4961
typename actual_object_comparator< BasicJsonType >::type actual_object_comparator_t
Definition json.hpp:3729
decltype(std::declval< StringType & >().append(std::declval< Arg && >())) string_can_append
Definition json.hpp:4466
void to_json(BasicJsonType &j, T b) noexcept
Definition json.hpp:6095
void get_arithmetic_value(const BasicJsonType &j, ArithmeticType &val)
Definition json.hpp:4991
decltype(std::declval< T & >().null()) null_function_t
Definition json.hpp:9843
make_index_sequence< sizeof...(Ts)> index_sequence_for
Definition json.hpp:3330
typename T::difference_type difference_type_t
Definition json.hpp:3638
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition json.hpp:3212
typename T::is_transparent detect_is_transparent
Definition json.hpp:4180
detail::uncvref_t< Type > from_json_tuple_get_impl(BasicJsonType &&j, detail::identity_tag< Type >, detail::priority_tag< 0 >)
Definition json.hpp:5365
decltype(std::declval< T & >().string(std::declval< String & >())) string_function_t
Definition json.hpp:9863
typename std::conditional< std::is_same< T, void >::value, json_default_base, T >::type json_base_class
Definition json.hpp:14704
typename T::reference reference_t
Definition json.hpp:3644
decltype(std::declval< T & >().boolean(std::declval< bool >())) boolean_function_t
Definition json.hpp:9847
decltype(std::declval< T & >().end_object()) end_object_function_t
Definition json.hpp:9878
bjdata_version_t
how to encode BJData
Definition json.hpp:15983
decltype(std::declval< ObjectType & >().erase(std::declval< KeyType >())) detect_erase_with_key_type
Definition json.hpp:4216
typename T::key_compare detect_key_compare
Definition json.hpp:3713
decltype(std::declval< T & >().start_object(std::declval< std::size_t >())) start_object_function_t
Definition json.hpp:9871
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().data(), std::declval< const Arg & >().size())) string_can_append_data
Definition json.hpp:4484
decltype(std::declval< T & >().number_unsigned(std::declval< Unsigned >())) number_unsigned_function_t
Definition json.hpp:9855
typename detector< nonesuch, void, Op, Args... >::value_t is_detected
Definition json.hpp:305
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3121
std::integral_constant< bool,(std::is_signed< OfType >::value &&(sizeof(T)< sizeof(OfType)))||(same_sign< OfType, T >::value &&sizeof(OfType)==sizeof(T)) > never_out_of_range
Definition json.hpp:4275
is_detected< string_can_append, StringType, Arg > detect_string_can_append
Definition json.hpp:4469
decltype(std::declval< T & >().key(std::declval< String & >())) key_function_t
Definition json.hpp:9875
Definition json.hpp:25506
Definition json.hpp:5802
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition json.hpp:25599
namespace for Niels Lohmann
Definition json.hpp:6305
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:6329
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:6319
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:6309
Definition json.hpp:3721
typename BasicJsonType::object_t object_t
Definition json.hpp:3722
typename BasicJsonType::default_object_comparator_t object_comparator_t
Definition json.hpp:3723
typename std::conditional< has_key_compare< object_t >::value, typename object_t::key_compare, object_comparator_t >::type type
Definition json.hpp:3725
signed char char_type
Definition json.hpp:3768
static constexpr int_type eof() noexcept
Definition json.hpp:3782
uint64_t int_type
Definition json.hpp:3769
static char_type to_char_type(int_type i) noexcept
Definition json.hpp:3777
static int_type to_int_type(char_type c) noexcept
Definition json.hpp:3772
static char_type to_char_type(int_type i) noexcept
Definition json.hpp:3753
static constexpr int_type eof() noexcept
Definition json.hpp:3758
unsigned char char_type
Definition json.hpp:3744
uint64_t int_type
Definition json.hpp:3745
static int_type to_int_type(char_type c) noexcept
Definition json.hpp:3748
Definition json.hpp:3738
Definition json.hpp:3817
decltype(input_adapter(begin(std::declval< ContainerType >()), end(std::declval< ContainerType >()))) adapter_type
Definition json.hpp:7067
Definition json.hpp:4937
Definition json.hpp:4914
Definition json.hpp:4934
Definition json.hpp:4925
Definition json.hpp:4931
Definition json.hpp:4905
Definition json.hpp:4928
Definition json.hpp:292
std::false_type value_t
Definition json.hpp:293
Default type
Definition json.hpp:294
Definition json.hpp:18019
diyfp w
Definition json.hpp:18020
diyfp minus
Definition json.hpp:18021
diyfp plus
Definition json.hpp:18022
Definition json.hpp:18158
std::uint64_t f
Definition json.hpp:18159
int e
Definition json.hpp:18160
int k
Definition json.hpp:18161
Definition json.hpp:17901
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition json.hpp:17925
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:18007
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition json.hpp:17990
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition json.hpp:17913
constexpr diyfp(std::uint64_t f_, int e_) noexcept
Definition json.hpp:17907
std::uint64_t f
Definition json.hpp:17904
int e
Definition json.hpp:17905
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
Definition json.hpp:6004
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
Definition json.hpp:5979
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
Definition json.hpp:5969
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
Definition json.hpp:5991
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
Definition json.hpp:6020
static void construct(BasicJsonType &j, const typename BasicJsonType::binary_t &b)
Definition json.hpp:5908
static void construct(BasicJsonType &j, typename BasicJsonType::binary_t &&b)
Definition json.hpp:5917
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
Definition json.hpp:5862
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
Definition json.hpp:5930
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
Definition json.hpp:5956
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
Definition json.hpp:5943
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
Definition json.hpp:6039
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
Definition json.hpp:6060
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
Definition json.hpp:6049
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
Definition json.hpp:5884
static void construct(BasicJsonType &j, const CompatibleStringType &str)
Definition json.hpp:5895
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
Definition json.hpp:5875
Definition json.hpp:5856
Definition json.hpp:5499
auto operator()(const BasicJsonType &j, T &&val) const noexcept(noexcept(from_json(j, std::forward< T >(val)))) -> decltype(from_json(j, std::forward< T >(val)))
Definition json.hpp:5501
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3675
Definition json.hpp:3660
Definition json.hpp:3716
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3690
Definition json.hpp:3685
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3705
Definition json.hpp:3700
Definition json.hpp:4846
Definition json.hpp:3254
T value_type
Definition json.hpp:3255
static constexpr std::size_t size() noexcept
Definition json.hpp:3256
an iterator value
Definition json.hpp:13749
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition json.hpp:13753
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition json.hpp:13755
Definition json.hpp:3609
Definition json.hpp:3596
Definition json.hpp:4378
Definition json.hpp:4166
Definition json.hpp:4017
Definition json.hpp:4088
Definition json.hpp:3938
typename std::remove_reference< CompatibleReferenceType >::type CVType
Definition json.hpp:4110
typename std::remove_cv< CVType >::type Type
Definition json.hpp:4111
uncvref_t< BasicJsonType > JsonType
Definition json.hpp:4109
static constexpr bool value
Definition json.hpp:4112
Definition json.hpp:4126
Definition json.hpp:3975
static constexpr auto value
Definition json.hpp:3976
Definition json.hpp:4091
Definition json.hpp:4104
Definition json.hpp:3911
Definition json.hpp:4061
Definition json.hpp:3971
Definition json.hpp:3982
ConstructibleStringType laundered_type
Definition json.hpp:3987
static constexpr auto value
Definition json.hpp:3990
Definition json.hpp:4129
Definition json.hpp:3849
Definition json.hpp:3830
Definition json.hpp:308
Definition json.hpp:3668
static constexpr bool value
Definition json.hpp:3669
Definition json.hpp:7020
typename std::iterator_traits< T >::value_type value_type
Definition json.hpp:7021
Definition json.hpp:3864
Definition json.hpp:4135
Definition json.hpp:4156
Definition json.hpp:3619
Definition json.hpp:4235
char x[2]
Definition json.hpp:4236
Definition json.hpp:4231
static one test(decltype(&C::capacity))
@ value
Definition json.hpp:4242
char one
Definition json.hpp:4232
static two test(...)
Definition json.hpp:3883
detected_t< result_of_end, t_ref > sentinel
Definition json.hpp:3888
detected_t< result_of_begin, t_ref > iterator
Definition json.hpp:3887
typename std::add_lvalue_reference< T >::type t_ref
Definition json.hpp:3885
static constexpr bool value
Definition json.hpp:3897
static constexpr auto is_iterator_begin
Definition json.hpp:3893
Definition json.hpp:9925
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9930
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9931
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9934
typename BasicJsonType::exception exception_t
Definition json.hpp:9935
typename BasicJsonType::string_t string_t
Definition json.hpp:9933
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9932
Definition json.hpp:9894
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9903
typename BasicJsonType::exception exception_t
Definition json.hpp:9904
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9901
typename BasicJsonType::string_t string_t
Definition json.hpp:9902
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9900
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9899
Definition json.hpp:4146
Definition json.hpp:4400
typename std::iterator_traits< iterator_type >::value_type char_type
Definition json.hpp:7032
static adapter_type create(IteratorType first, IteratorType last)
Definition json.hpp:7036
iterator_input_adapter< iterator_type > adapter_type
Definition json.hpp:7010
typename std::iterator_traits< iterator_type >::value_type char_type
Definition json.hpp:7009
static adapter_type create(IteratorType first, IteratorType last)
Definition json.hpp:7012
IteratorType iterator_type
Definition json.hpp:7008
std::random_access_iterator_tag iterator_category
Definition json.hpp:3436
Definition json.hpp:3424
Definition json.hpp:3405
Default base class of the basic_json class.
Definition json.hpp:14697
Definition json.hpp:263
void type
Definition json.hpp:264
Definition json.hpp:3824
Definition json.hpp:278
nonesuch(nonesuch const &&)=delete
~nonesuch()=delete
void operator=(nonesuch &&)=delete
void operator=(nonesuch const &)=delete
nonesuch(nonesuch const &)=delete
abstract output adapter interface
Definition json.hpp:15856
output_adapter_protocol(const output_adapter_protocol &)=default
virtual ~output_adapter_protocol()=default
virtual void write_character(CharType c)=0
output_adapter_protocol(output_adapter_protocol &&) noexcept=default
virtual void write_characters(const CharType *s, std::size_t length)=0
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:3337
Definition json.hpp:3343
static JSON_INLINE_VARIABLE constexpr T value
Definition json.hpp:3344
Definition json.hpp:6272
auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward< T >(val)))) -> decltype(to_json(j, std::forward< T >(val)), void())
Definition json.hpp:6274
Definition json.hpp:3274
Definition json.hpp:3293
typename Extend< typename Gen< T, N/2 >::type, N/2, N % 2 >::type type
Definition json.hpp:3295
static constexpr bool test(T val)
Definition json.hpp:4331
static constexpr bool test(T)
Definition json.hpp:4340
Definition json.hpp:4326
static constexpr bool test(T val)
Definition json.hpp:4285
static constexpr bool test(T val)
Definition json.hpp:4305
static constexpr bool test(T val)
Definition json.hpp:4295
static constexpr bool test(T val)
Definition json.hpp:4315
Definition json.hpp:4280
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.hpp:6895
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.hpp:6837
Definition json.hpp:6831
Definition json.hpp:14760
T type
Definition json.hpp:14761
SAX interface.
Definition json.hpp:8857
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
json_sax()=default
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
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:8858
typename BasicJsonType::string_t string_t
Definition json.hpp:8861
virtual bool end_array()=0
the end of an array was read
json_sax(const json_sax &)=default
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:8860
virtual bool null()=0
a null value was read
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:8859
json_sax(json_sax &&) noexcept=default
typename BasicJsonType::binary_t binary_t
Definition json.hpp:8862
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:19970
std::vector< std::pair< const Key, T >, Allocator > Container
Definition json.hpp:19973
std::pair< iterator, bool > insert(value_type &&value)
Definition json.hpp:20264
typename Container::value_type value_type
Definition json.hpp:19977
std::equal_to< Key > key_compare
Definition json.hpp:19981
iterator erase(iterator pos)
Definition json.hpp:20142
T mapped_type
Definition json.hpp:19972
ordered_map(const Allocator &alloc) noexcept(noexcept(Container(alloc)))
Definition json.hpp:19987
T & operator[](KeyType &&key)
Definition json.hpp:20029
typename Container::iterator iterator
Definition json.hpp:19974
const T & at(KeyType &&key) const
Definition json.hpp:20089
T & at(KeyType &&key)
Definition json.hpp:20061
const T & operator[](KeyType &&key) const
Definition json.hpp:20041
iterator find(const key_type &key)
Definition json.hpp:20226
iterator erase(iterator first, iterator last)
Definition json.hpp:20147
const T & at(const key_type &key) const
Definition json.hpp:20074
const_iterator find(const key_type &key) const
Definition json.hpp:20252
T & operator[](const key_type &key)
Definition json.hpp:20022
size_type erase(KeyType &&key)
Definition json.hpp:20123
typename Container::size_type size_type
Definition json.hpp:19976
ordered_map() noexcept(noexcept(Container()))
Definition json.hpp:19986
void insert(InputIt first, InputIt last)
Definition json.hpp:20287
size_type count(const key_type &key) const
Definition json.hpp:20200
std::pair< iterator, bool > emplace(KeyType &&key, T &&t)
Definition json.hpp:20009
size_type erase(const key_type &key)
Definition json.hpp:20102
ordered_map(std::initializer_list< value_type > init, const Allocator &alloc=Allocator())
Definition json.hpp:19991
std::pair< iterator, bool > insert(const value_type &value)
Definition json.hpp:20269
size_type count(KeyType &&key) const
Definition json.hpp:20214
Key key_type
Definition json.hpp:19971
ordered_map(It first, It last, const Allocator &alloc=Allocator())
Definition json.hpp:19989
typename std::enable_if< std::is_convertible< typename std::iterator_traits< InputIt >::iterator_category, std::input_iterator_tag >::value >::type require_input_iter
Definition json.hpp:20284
const T & operator[](const key_type &key) const
Definition json.hpp:20034
iterator find(KeyType &&key)
Definition json.hpp:20240
T & at(const key_type &key)
Definition json.hpp:20046
typename Container::const_iterator const_iterator
Definition json.hpp:19975
std::pair< iterator, bool > emplace(const key_type &key, T &&t)
Definition json.hpp:19994
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL &j) const
Definition json.hpp:25568
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:25582