Arkanjo 0.1
A tool for find code duplicated functions in codebases
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 - 2025 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9/****************************************************************************\
10 * Note on documentation: The source files contain links to the online *
11 * documentation of the public API at https://json.nlohmann.me. This URL *
12 * contains the most recent documentation and should also be applicable to *
13 * previous versions; documentation for deprecated functions is not *
14 * removed, but marked deprecated. See "Generate documentation" section in *
15 * file docs/README.md. *
16\****************************************************************************/
17
18#ifndef INCLUDE_NLOHMANN_JSON_HPP_
19#define INCLUDE_NLOHMANN_JSON_HPP_
20
21#include <algorithm> // all_of, find, for_each
22#include <cstddef> // nullptr_t, ptrdiff_t, size_t
23#include <functional> // hash, less
24#include <initializer_list> // initializer_list
25#ifndef JSON_NO_IO
26 #include <iosfwd> // istream, ostream
27#endif // JSON_NO_IO
28#include <iterator> // random_access_iterator_tag
29#include <memory> // unique_ptr
30#include <string> // string, stoi, to_string
31#include <utility> // declval, forward, move, pair, swap
32#include <vector> // vector
33
34// #include <nlohmann/adl_serializer.hpp>
35// __ _____ _____ _____
36// __| | __| | | | JSON for Modern C++
37// | | |__ | | | | | | version 3.12.0
38// |_____|_____|_____|_|___| https://github.com/nlohmann/json
39//
40// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
41// SPDX-License-Identifier: MIT
42
43
44
45#include <utility>
46
47// #include <nlohmann/detail/abi_macros.hpp>
48// __ _____ _____ _____
49// __| | __| | | | JSON for Modern C++
50// | | |__ | | | | | | version 3.12.0
51// |_____|_____|_____|_|___| https://github.com/nlohmann/json
52//
53// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
54// SPDX-License-Identifier: MIT
55
56
57
58// This file contains all macro definitions affecting or depending on the ABI
59
60#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
61 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
62 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0
63 #warning "Already included a different version of the library!"
64 #endif
65 #endif
66#endif
67
68#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
69#define NLOHMANN_JSON_VERSION_MINOR 12 // NOLINT(modernize-macro-to-enum)
70#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum)
71
72#ifndef JSON_DIAGNOSTICS
73 #define JSON_DIAGNOSTICS 0
74#endif
75
76#ifndef JSON_DIAGNOSTIC_POSITIONS
77 #define JSON_DIAGNOSTIC_POSITIONS 0
78#endif
79
80#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
81 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
82#endif
83
84#if JSON_DIAGNOSTICS
85 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
86#else
87 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
88#endif
89
90#if JSON_DIAGNOSTIC_POSITIONS
91 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp
92#else
93 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS
94#endif
95
96#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
97 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
98#else
99 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
100#endif
101
102#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
103 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
104#endif
105
106// Construct the namespace ABI tags component
107#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c
108#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \
109 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c)
110
111#define NLOHMANN_JSON_ABI_TAGS \
112 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
113 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
114 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \
115 NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS)
116
117// Construct the namespace version component
118#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
119 _v ## major ## _ ## minor ## _ ## patch
120#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
121 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
122
123#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
124#define NLOHMANN_JSON_NAMESPACE_VERSION
125#else
126#define NLOHMANN_JSON_NAMESPACE_VERSION \
127 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
128 NLOHMANN_JSON_VERSION_MINOR, \
129 NLOHMANN_JSON_VERSION_PATCH)
130#endif
131
132// Combine namespace components
133#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
134#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
135 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
136
137#ifndef NLOHMANN_JSON_NAMESPACE
138#define NLOHMANN_JSON_NAMESPACE \
139 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
140 NLOHMANN_JSON_ABI_TAGS, \
141 NLOHMANN_JSON_NAMESPACE_VERSION)
142#endif
143
144#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
145#define NLOHMANN_JSON_NAMESPACE_BEGIN \
146 namespace nlohmann \
147 { \
148 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
149 NLOHMANN_JSON_ABI_TAGS, \
150 NLOHMANN_JSON_NAMESPACE_VERSION) \
151 {
152#endif
153
154#ifndef NLOHMANN_JSON_NAMESPACE_END
155#define NLOHMANN_JSON_NAMESPACE_END \
156 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
157 } // namespace nlohmann
158#endif
159
160// #include <nlohmann/detail/conversions/from_json.hpp>
161// __ _____ _____ _____
162// __| | __| | | | JSON for Modern C++
163// | | |__ | | | | | | version 3.12.0
164// |_____|_____|_____|_|___| https://github.com/nlohmann/json
165//
166// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
167// SPDX-License-Identifier: MIT
168
169
170
171#include <algorithm> // transform
172#include <array> // array
173#include <forward_list> // forward_list
174#include <iterator> // inserter, front_inserter, end
175#include <map> // map
176#include <string> // string
177#include <tuple> // tuple, make_tuple
178#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
179#include <unordered_map> // unordered_map
180#include <utility> // pair, declval
181#include <valarray> // valarray
182
183// #include <nlohmann/detail/exceptions.hpp>
184// __ _____ _____ _____
185// __| | __| | | | JSON for Modern C++
186// | | |__ | | | | | | version 3.12.0
187// |_____|_____|_____|_|___| https://github.com/nlohmann/json
188//
189// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
190// SPDX-License-Identifier: MIT
191
192
193
194#include <cstddef> // nullptr_t
195#include <exception> // exception
196#if JSON_DIAGNOSTICS
197 #include <numeric> // accumulate
198#endif
199#include <stdexcept> // runtime_error
200#include <string> // to_string
201#include <vector> // vector
202
203// #include <nlohmann/detail/value_t.hpp>
204// __ _____ _____ _____
205// __| | __| | | | JSON for Modern C++
206// | | |__ | | | | | | version 3.12.0
207// |_____|_____|_____|_|___| https://github.com/nlohmann/json
208//
209// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
210// SPDX-License-Identifier: MIT
211
212
213
214#include <array> // array
215#include <cstddef> // size_t
216#include <cstdint> // uint8_t
217#include <string> // string
218
219// #include <nlohmann/detail/macro_scope.hpp>
220// __ _____ _____ _____
221// __| | __| | | | JSON for Modern C++
222// | | |__ | | | | | | version 3.12.0
223// |_____|_____|_____|_|___| https://github.com/nlohmann/json
224//
225// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
226// SPDX-License-Identifier: MIT
227
228
229
230#include <utility> // declval, pair
231// #include <nlohmann/detail/meta/detected.hpp>
232// __ _____ _____ _____
233// __| | __| | | | JSON for Modern C++
234// | | |__ | | | | | | version 3.12.0
235// |_____|_____|_____|_|___| https://github.com/nlohmann/json
236//
237// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
238// SPDX-License-Identifier: MIT
239
240
241
242#include <type_traits>
243
244// #include <nlohmann/detail/meta/void_t.hpp>
245// __ _____ _____ _____
246// __| | __| | | | JSON for Modern C++
247// | | |__ | | | | | | version 3.12.0
248// |_____|_____|_____|_|___| https://github.com/nlohmann/json
249//
250// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
251// SPDX-License-Identifier: MIT
252
253
254
255// #include <nlohmann/detail/abi_macros.hpp>
256
257
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 - 2025 Niels Lohmann <https://nlohmann.me>
338// SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson <evan@nemerson.com>
339// SPDX-License-Identifier: MIT
340
341/* Hedley - https://nemequ.github.io/hedley
342 * Created by Evan Nemerson <evan@nemerson.com>
343 */
344
345#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
346#if defined(JSON_HEDLEY_VERSION)
347 #undef JSON_HEDLEY_VERSION
348#endif
349#define JSON_HEDLEY_VERSION 15
350
351#if defined(JSON_HEDLEY_STRINGIFY_EX)
352 #undef JSON_HEDLEY_STRINGIFY_EX
353#endif
354#define JSON_HEDLEY_STRINGIFY_EX(x) #x
355
356#if defined(JSON_HEDLEY_STRINGIFY)
357 #undef JSON_HEDLEY_STRINGIFY
358#endif
359#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
360
361#if defined(JSON_HEDLEY_CONCAT_EX)
362 #undef JSON_HEDLEY_CONCAT_EX
363#endif
364#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
365
366#if defined(JSON_HEDLEY_CONCAT)
367 #undef JSON_HEDLEY_CONCAT
368#endif
369#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
370
371#if defined(JSON_HEDLEY_CONCAT3_EX)
372 #undef JSON_HEDLEY_CONCAT3_EX
373#endif
374#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
375
376#if defined(JSON_HEDLEY_CONCAT3)
377 #undef JSON_HEDLEY_CONCAT3
378#endif
379#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
380
381#if defined(JSON_HEDLEY_VERSION_ENCODE)
382 #undef JSON_HEDLEY_VERSION_ENCODE
383#endif
384#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
385
386#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
387 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
388#endif
389#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
390
391#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
392 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
393#endif
394#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
395
396#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
397 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
398#endif
399#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
400
401#if defined(JSON_HEDLEY_GNUC_VERSION)
402 #undef JSON_HEDLEY_GNUC_VERSION
403#endif
404#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
405 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
406#elif defined(__GNUC__)
407 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
408#endif
409
410#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
411 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
412#endif
413#if defined(JSON_HEDLEY_GNUC_VERSION)
414 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
415#else
416 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
417#endif
418
419#if defined(JSON_HEDLEY_MSVC_VERSION)
420 #undef JSON_HEDLEY_MSVC_VERSION
421#endif
422#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
423 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
424#elif defined(_MSC_FULL_VER) && !defined(__ICL)
425 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
426#elif defined(_MSC_VER) && !defined(__ICL)
427 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
428#endif
429
430#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
431 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
432#endif
433#if !defined(JSON_HEDLEY_MSVC_VERSION)
434 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
435#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
436 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
437#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
438 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
439#else
440 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
441#endif
442
443#if defined(JSON_HEDLEY_INTEL_VERSION)
444 #undef JSON_HEDLEY_INTEL_VERSION
445#endif
446#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
447 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
448#elif defined(__INTEL_COMPILER) && !defined(__ICL)
449 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
450#endif
451
452#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
453 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
454#endif
455#if defined(JSON_HEDLEY_INTEL_VERSION)
456 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
457#else
458 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
459#endif
460
461#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
462 #undef JSON_HEDLEY_INTEL_CL_VERSION
463#endif
464#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
465 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
466#endif
467
468#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
469 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
470#endif
471#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
472 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
473#else
474 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
475#endif
476
477#if defined(JSON_HEDLEY_PGI_VERSION)
478 #undef JSON_HEDLEY_PGI_VERSION
479#endif
480#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
481 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
482#endif
483
484#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
485 #undef JSON_HEDLEY_PGI_VERSION_CHECK
486#endif
487#if defined(JSON_HEDLEY_PGI_VERSION)
488 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
489#else
490 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
491#endif
492
493#if defined(JSON_HEDLEY_SUNPRO_VERSION)
494 #undef JSON_HEDLEY_SUNPRO_VERSION
495#endif
496#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
497 #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)
498#elif defined(__SUNPRO_C)
499 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
500#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
501 #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)
502#elif defined(__SUNPRO_CC)
503 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
504#endif
505
506#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
507 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
508#endif
509#if defined(JSON_HEDLEY_SUNPRO_VERSION)
510 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
511#else
512 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
513#endif
514
515#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
516 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
517#endif
518#if defined(__EMSCRIPTEN__)
519 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
520#endif
521
522#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
523 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
524#endif
525#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
526 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
527#else
528 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
529#endif
530
531#if defined(JSON_HEDLEY_ARM_VERSION)
532 #undef JSON_HEDLEY_ARM_VERSION
533#endif
534#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
535 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
536#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
537 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
538#endif
539
540#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
541 #undef JSON_HEDLEY_ARM_VERSION_CHECK
542#endif
543#if defined(JSON_HEDLEY_ARM_VERSION)
544 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
545#else
546 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
547#endif
548
549#if defined(JSON_HEDLEY_IBM_VERSION)
550 #undef JSON_HEDLEY_IBM_VERSION
551#endif
552#if defined(__ibmxl__)
553 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
554#elif defined(__xlC__) && defined(__xlC_ver__)
555 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
556#elif defined(__xlC__)
557 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
558#endif
559
560#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
561 #undef JSON_HEDLEY_IBM_VERSION_CHECK
562#endif
563#if defined(JSON_HEDLEY_IBM_VERSION)
564 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
565#else
566 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
567#endif
568
569#if defined(JSON_HEDLEY_TI_VERSION)
570 #undef JSON_HEDLEY_TI_VERSION
571#endif
572#if \
573 defined(__TI_COMPILER_VERSION__) && \
574 ( \
575 defined(__TMS470__) || defined(__TI_ARM__) || \
576 defined(__MSP430__) || \
577 defined(__TMS320C2000__) \
578 )
579#if (__TI_COMPILER_VERSION__ >= 16000000)
580 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
581#endif
582#endif
583
584#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
585 #undef JSON_HEDLEY_TI_VERSION_CHECK
586#endif
587#if defined(JSON_HEDLEY_TI_VERSION)
588 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
589#else
590 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
591#endif
592
593#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
594 #undef JSON_HEDLEY_TI_CL2000_VERSION
595#endif
596#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
597 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
598#endif
599
600#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
601 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
602#endif
603#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
604 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
605#else
606 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
607#endif
608
609#if defined(JSON_HEDLEY_TI_CL430_VERSION)
610 #undef JSON_HEDLEY_TI_CL430_VERSION
611#endif
612#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
613 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
614#endif
615
616#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
617 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
618#endif
619#if defined(JSON_HEDLEY_TI_CL430_VERSION)
620 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
621#else
622 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
623#endif
624
625#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
626 #undef JSON_HEDLEY_TI_ARMCL_VERSION
627#endif
628#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
629 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
630#endif
631
632#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
633 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
634#endif
635#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
636 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
637#else
638 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
639#endif
640
641#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
642 #undef JSON_HEDLEY_TI_CL6X_VERSION
643#endif
644#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
645 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
646#endif
647
648#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
649 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
650#endif
651#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
652 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
653#else
654 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
655#endif
656
657#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
658 #undef JSON_HEDLEY_TI_CL7X_VERSION
659#endif
660#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
661 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
662#endif
663
664#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
665 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
666#endif
667#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
668 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
669#else
670 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
671#endif
672
673#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
674 #undef JSON_HEDLEY_TI_CLPRU_VERSION
675#endif
676#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
677 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
678#endif
679
680#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
681 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
682#endif
683#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
684 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
685#else
686 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
687#endif
688
689#if defined(JSON_HEDLEY_CRAY_VERSION)
690 #undef JSON_HEDLEY_CRAY_VERSION
691#endif
692#if defined(_CRAYC)
693 #if defined(_RELEASE_PATCHLEVEL)
694 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
695 #else
696 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
697 #endif
698#endif
699
700#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
701 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
702#endif
703#if defined(JSON_HEDLEY_CRAY_VERSION)
704 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
705#else
706 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
707#endif
708
709#if defined(JSON_HEDLEY_IAR_VERSION)
710 #undef JSON_HEDLEY_IAR_VERSION
711#endif
712#if defined(__IAR_SYSTEMS_ICC__)
713 #if __VER__ > 1000
714 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
715 #else
716 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
717 #endif
718#endif
719
720#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
721 #undef JSON_HEDLEY_IAR_VERSION_CHECK
722#endif
723#if defined(JSON_HEDLEY_IAR_VERSION)
724 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
725#else
726 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
727#endif
728
729#if defined(JSON_HEDLEY_TINYC_VERSION)
730 #undef JSON_HEDLEY_TINYC_VERSION
731#endif
732#if defined(__TINYC__)
733 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
734#endif
735
736#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
737 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
738#endif
739#if defined(JSON_HEDLEY_TINYC_VERSION)
740 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
741#else
742 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
743#endif
744
745#if defined(JSON_HEDLEY_DMC_VERSION)
746 #undef JSON_HEDLEY_DMC_VERSION
747#endif
748#if defined(__DMC__)
749 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
750#endif
751
752#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
753 #undef JSON_HEDLEY_DMC_VERSION_CHECK
754#endif
755#if defined(JSON_HEDLEY_DMC_VERSION)
756 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
757#else
758 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
759#endif
760
761#if defined(JSON_HEDLEY_COMPCERT_VERSION)
762 #undef JSON_HEDLEY_COMPCERT_VERSION
763#endif
764#if defined(__COMPCERT_VERSION__)
765 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
766#endif
767
768#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
769 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
770#endif
771#if defined(JSON_HEDLEY_COMPCERT_VERSION)
772 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
773#else
774 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
775#endif
776
777#if defined(JSON_HEDLEY_PELLES_VERSION)
778 #undef JSON_HEDLEY_PELLES_VERSION
779#endif
780#if defined(__POCC__)
781 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
782#endif
783
784#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
785 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
786#endif
787#if defined(JSON_HEDLEY_PELLES_VERSION)
788 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
789#else
790 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
791#endif
792
793#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
794 #undef JSON_HEDLEY_MCST_LCC_VERSION
795#endif
796#if defined(__LCC__) && defined(__LCC_MINOR__)
797 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
798#endif
799
800#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
801 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
802#endif
803#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
804 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
805#else
806 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
807#endif
808
809#if defined(JSON_HEDLEY_GCC_VERSION)
810 #undef JSON_HEDLEY_GCC_VERSION
811#endif
812#if \
813 defined(JSON_HEDLEY_GNUC_VERSION) && \
814 !defined(__clang__) && \
815 !defined(JSON_HEDLEY_INTEL_VERSION) && \
816 !defined(JSON_HEDLEY_PGI_VERSION) && \
817 !defined(JSON_HEDLEY_ARM_VERSION) && \
818 !defined(JSON_HEDLEY_CRAY_VERSION) && \
819 !defined(JSON_HEDLEY_TI_VERSION) && \
820 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
821 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
822 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
823 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
824 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
825 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
826 !defined(__COMPCERT__) && \
827 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
828 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
829#endif
830
831#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
832 #undef JSON_HEDLEY_GCC_VERSION_CHECK
833#endif
834#if defined(JSON_HEDLEY_GCC_VERSION)
835 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
836#else
837 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
838#endif
839
840#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
841 #undef JSON_HEDLEY_HAS_ATTRIBUTE
842#endif
843#if \
844 defined(__has_attribute) && \
845 ( \
846 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
847 )
848# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
849#else
850# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
851#endif
852
853#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
854 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
855#endif
856#if defined(__has_attribute)
857 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
858#else
859 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
860#endif
861
862#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
863 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
864#endif
865#if defined(__has_attribute)
866 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
867#else
868 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
869#endif
870
871#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
872 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
873#endif
874#if \
875 defined(__has_cpp_attribute) && \
876 defined(__cplusplus) && \
877 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
878 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
879#else
880 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
881#endif
882
883#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
884 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
885#endif
886#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
887 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
888#elif \
889 !defined(JSON_HEDLEY_PGI_VERSION) && \
890 !defined(JSON_HEDLEY_IAR_VERSION) && \
891 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
892 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
893 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
894#else
895 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
896#endif
897
898#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
899 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
900#endif
901#if defined(__has_cpp_attribute) && defined(__cplusplus)
902 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
903#else
904 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
905#endif
906
907#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
908 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
909#endif
910#if defined(__has_cpp_attribute) && defined(__cplusplus)
911 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
912#else
913 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
914#endif
915
916#if defined(JSON_HEDLEY_HAS_BUILTIN)
917 #undef JSON_HEDLEY_HAS_BUILTIN
918#endif
919#if defined(__has_builtin)
920 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
921#else
922 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
923#endif
924
925#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
926 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
927#endif
928#if defined(__has_builtin)
929 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
930#else
931 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
932#endif
933
934#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
935 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
936#endif
937#if defined(__has_builtin)
938 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
939#else
940 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
941#endif
942
943#if defined(JSON_HEDLEY_HAS_FEATURE)
944 #undef JSON_HEDLEY_HAS_FEATURE
945#endif
946#if defined(__has_feature)
947 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
948#else
949 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
950#endif
951
952#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
953 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
954#endif
955#if defined(__has_feature)
956 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
957#else
958 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
959#endif
960
961#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
962 #undef JSON_HEDLEY_GCC_HAS_FEATURE
963#endif
964#if defined(__has_feature)
965 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
966#else
967 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
968#endif
969
970#if defined(JSON_HEDLEY_HAS_EXTENSION)
971 #undef JSON_HEDLEY_HAS_EXTENSION
972#endif
973#if defined(__has_extension)
974 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
975#else
976 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
977#endif
978
979#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
980 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
981#endif
982#if defined(__has_extension)
983 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
984#else
985 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
986#endif
987
988#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
989 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
990#endif
991#if defined(__has_extension)
992 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
993#else
994 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
995#endif
996
997#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
998 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
999#endif
1000#if defined(__has_declspec_attribute)
1001 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
1002#else
1003 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
1004#endif
1005
1006#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1007 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1008#endif
1009#if defined(__has_declspec_attribute)
1010 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1011#else
1012 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1013#endif
1014
1015#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1016 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1017#endif
1018#if defined(__has_declspec_attribute)
1019 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1020#else
1021 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1022#endif
1023
1024#if defined(JSON_HEDLEY_HAS_WARNING)
1025 #undef JSON_HEDLEY_HAS_WARNING
1026#endif
1027#if defined(__has_warning)
1028 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1029#else
1030 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1031#endif
1032
1033#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1034 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1035#endif
1036#if defined(__has_warning)
1037 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1038#else
1039 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1040#endif
1041
1042#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1043 #undef JSON_HEDLEY_GCC_HAS_WARNING
1044#endif
1045#if defined(__has_warning)
1046 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1047#else
1048 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1049#endif
1050
1051#if \
1052 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1053 defined(__clang__) || \
1054 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1055 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1056 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1057 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1058 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1059 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1060 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1061 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1062 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1063 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1064 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1065 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1066 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1067 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1068 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1069 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1070 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1071#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1072 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1073#else
1074 #define JSON_HEDLEY_PRAGMA(value)
1075#endif
1076
1077#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1078 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1079#endif
1080#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1081 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1082#endif
1083#if defined(__clang__)
1084 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1085 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1086#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1087 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1088 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1089#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1090 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1091 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1092#elif \
1093 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1094 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1095 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1096 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1097#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1098 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1099 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1100#elif \
1101 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1102 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1103 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1104 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1105 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1106 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1107 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1108 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1109#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1110 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1111 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1112#else
1113 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1114 #define JSON_HEDLEY_DIAGNOSTIC_POP
1115#endif
1116
1117/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1118 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1119#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1120 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1121#endif
1122#if defined(__cplusplus)
1123# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1124# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1125# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1126# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1127 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1128 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1129 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1130 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1131 xpr \
1132 JSON_HEDLEY_DIAGNOSTIC_POP
1133# else
1134# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1135 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1136 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1137 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1138 xpr \
1139 JSON_HEDLEY_DIAGNOSTIC_POP
1140# endif
1141# else
1142# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1143 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1144 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1145 xpr \
1146 JSON_HEDLEY_DIAGNOSTIC_POP
1147# endif
1148# endif
1149#endif
1150#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1151 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1152#endif
1153
1154#if defined(JSON_HEDLEY_CONST_CAST)
1155 #undef JSON_HEDLEY_CONST_CAST
1156#endif
1157#if defined(__cplusplus)
1158# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1159#elif \
1160 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1161 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1162 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1163# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1164 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1165 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1166 ((T) (expr)); \
1167 JSON_HEDLEY_DIAGNOSTIC_POP \
1168 }))
1169#else
1170# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1171#endif
1172
1173#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1174 #undef JSON_HEDLEY_REINTERPRET_CAST
1175#endif
1176#if defined(__cplusplus)
1177 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1178#else
1179 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1180#endif
1181
1182#if defined(JSON_HEDLEY_STATIC_CAST)
1183 #undef JSON_HEDLEY_STATIC_CAST
1184#endif
1185#if defined(__cplusplus)
1186 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1187#else
1188 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1189#endif
1190
1191#if defined(JSON_HEDLEY_CPP_CAST)
1192 #undef JSON_HEDLEY_CPP_CAST
1193#endif
1194#if defined(__cplusplus)
1195# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1196# define JSON_HEDLEY_CPP_CAST(T, expr) \
1197 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1198 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1199 ((T) (expr)) \
1200 JSON_HEDLEY_DIAGNOSTIC_POP
1201# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1202# define JSON_HEDLEY_CPP_CAST(T, expr) \
1203 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1204 _Pragma("diag_suppress=Pe137") \
1205 JSON_HEDLEY_DIAGNOSTIC_POP
1206# else
1207# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1208# endif
1209#else
1210# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1211#endif
1212
1213#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1214 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1215#endif
1216#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1217 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1218#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1219 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1220#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1221 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1222#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1223 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1224#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1225 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1226#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1227 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1228#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1229 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1230#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1231 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1232#elif \
1233 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1234 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1235 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1236 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1237 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1238 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1239 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1240 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1241 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1242 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1243 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1244 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1245#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1246 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1247#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1248 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1249#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1250 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1251#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1252 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1253#else
1254 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1255#endif
1256
1257#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1258 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1259#endif
1260#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1261 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1262#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1263 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1264#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1265 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1266#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1267 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1268#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1269 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1270#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1271 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1272#elif \
1273 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1274 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1275 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1276 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1277 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1278#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1279 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1280#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1281 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1282#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1283 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1284#else
1285 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1286#endif
1287
1288#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1289 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1290#endif
1291#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1292 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1293#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1294 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1295#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1296 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1297#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1298 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1299#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1300 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1301#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1302 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1303#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1304 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1305#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1306 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1307#elif \
1308 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1309 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1310 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1311 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1312#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1313 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1314#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1315 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1316#else
1317 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1318#endif
1319
1320#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1321 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1322#endif
1323#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1324 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1325#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1326 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1327#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1328 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1329#else
1330 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1331#endif
1332
1333#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1334 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1335#endif
1336#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1337 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1338#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1339 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1340#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1341 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1342#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1343 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1344#else
1345 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1346#endif
1347
1348#if defined(JSON_HEDLEY_DEPRECATED)
1349 #undef JSON_HEDLEY_DEPRECATED
1350#endif
1351#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1352 #undef JSON_HEDLEY_DEPRECATED_FOR
1353#endif
1354#if \
1355 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1356 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1357 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1358 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1359#elif \
1360 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1361 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1362 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1363 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1364 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1365 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1366 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1367 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1368 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1369 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1370 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1371 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1372 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1373 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1374#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1375 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1376 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1377#elif \
1378 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1379 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1380 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1381 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1382 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1383 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1384 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1385 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1386 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1387 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1388 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1389 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1390 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1391 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1392 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1393 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1394 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1395 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1396#elif \
1397 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1398 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1399 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1400 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1401 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1402#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1403 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1404 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1405#else
1406 #define JSON_HEDLEY_DEPRECATED(since)
1407 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1408#endif
1409
1410#if defined(JSON_HEDLEY_UNAVAILABLE)
1411 #undef JSON_HEDLEY_UNAVAILABLE
1412#endif
1413#if \
1414 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1415 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1416 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1417 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1418 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1419#else
1420 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1421#endif
1422
1423#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1424 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1425#endif
1426#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1427 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1428#endif
1429#if \
1430 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1431 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1432 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1433 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1434 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1435 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1436 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1437 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1438 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1439 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1440 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1441 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1442 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1443 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1444 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1445 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1446 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1447 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1448 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1449#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1450 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1451 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1452#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1453 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1454 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1455#elif defined(_Check_return_) /* SAL */
1456 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1457 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1458#else
1459 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1460 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1461#endif
1462
1463#if defined(JSON_HEDLEY_SENTINEL)
1464 #undef JSON_HEDLEY_SENTINEL
1465#endif
1466#if \
1467 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1468 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1469 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1470 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1471 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1472 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1473#else
1474 #define JSON_HEDLEY_SENTINEL(position)
1475#endif
1476
1477#if defined(JSON_HEDLEY_NO_RETURN)
1478 #undef JSON_HEDLEY_NO_RETURN
1479#endif
1480#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1481 #define JSON_HEDLEY_NO_RETURN __noreturn
1482#elif \
1483 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1484 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1485 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1486#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1487 #define JSON_HEDLEY_NO_RETURN _Noreturn
1488#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1489 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1490#elif \
1491 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1492 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1493 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1494 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1495 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1496 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1497 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1498 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1499 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1500 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1501 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1502 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1503 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1504 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1505 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1506 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1507 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1508 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1509#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1510 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1511#elif \
1512 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1513 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1514 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1515#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1516 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1517#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1518 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1519#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1520 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1521#else
1522 #define JSON_HEDLEY_NO_RETURN
1523#endif
1524
1525#if defined(JSON_HEDLEY_NO_ESCAPE)
1526 #undef JSON_HEDLEY_NO_ESCAPE
1527#endif
1528#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1529 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1530#else
1531 #define JSON_HEDLEY_NO_ESCAPE
1532#endif
1533
1534#if defined(JSON_HEDLEY_UNREACHABLE)
1535 #undef JSON_HEDLEY_UNREACHABLE
1536#endif
1537#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1538 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1539#endif
1540#if defined(JSON_HEDLEY_ASSUME)
1541 #undef JSON_HEDLEY_ASSUME
1542#endif
1543#if \
1544 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1545 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1546 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1547 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1548#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1549 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1550#elif \
1551 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1552 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1553 #if defined(__cplusplus)
1554 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1555 #else
1556 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1557 #endif
1558#endif
1559#if \
1560 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1561 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1562 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1563 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1564 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1565 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1566 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1567 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1568#elif defined(JSON_HEDLEY_ASSUME)
1569 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1570#endif
1571#if !defined(JSON_HEDLEY_ASSUME)
1572 #if defined(JSON_HEDLEY_UNREACHABLE)
1573 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1574 #else
1575 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1576 #endif
1577#endif
1578#if defined(JSON_HEDLEY_UNREACHABLE)
1579 #if \
1580 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1581 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1582 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1583 #else
1584 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1585 #endif
1586#else
1587 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1588#endif
1589#if !defined(JSON_HEDLEY_UNREACHABLE)
1590 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1591#endif
1592
1594#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1595 #pragma clang diagnostic ignored "-Wpedantic"
1596#endif
1597#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1598 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1599#endif
1600#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1601 #if defined(__clang__)
1602 #pragma clang diagnostic ignored "-Wvariadic-macros"
1603 #elif defined(JSON_HEDLEY_GCC_VERSION)
1604 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1605 #endif
1606#endif
1607#if defined(JSON_HEDLEY_NON_NULL)
1608 #undef JSON_HEDLEY_NON_NULL
1609#endif
1610#if \
1611 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1612 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1613 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1614 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1615 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1616#else
1617 #define JSON_HEDLEY_NON_NULL(...)
1618#endif
1620
1621#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1622 #undef JSON_HEDLEY_PRINTF_FORMAT
1623#endif
1624#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1625 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1626#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1627 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1628#elif \
1629 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1630 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1631 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1632 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1633 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1634 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1635 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1636 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1637 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1638 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1639 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1640 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1641 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1642 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1643 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1644 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1645 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1646 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1647#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1648 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1649#else
1650 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1651#endif
1652
1653#if defined(JSON_HEDLEY_CONSTEXPR)
1654 #undef JSON_HEDLEY_CONSTEXPR
1655#endif
1656#if defined(__cplusplus)
1657 #if __cplusplus >= 201103L
1658 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1659 #endif
1660#endif
1661#if !defined(JSON_HEDLEY_CONSTEXPR)
1662 #define JSON_HEDLEY_CONSTEXPR
1663#endif
1664
1665#if defined(JSON_HEDLEY_PREDICT)
1666 #undef JSON_HEDLEY_PREDICT
1667#endif
1668#if defined(JSON_HEDLEY_LIKELY)
1669 #undef JSON_HEDLEY_LIKELY
1670#endif
1671#if defined(JSON_HEDLEY_UNLIKELY)
1672 #undef JSON_HEDLEY_UNLIKELY
1673#endif
1674#if defined(JSON_HEDLEY_UNPREDICTABLE)
1675 #undef JSON_HEDLEY_UNPREDICTABLE
1676#endif
1677#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1678 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1679#endif
1680#if \
1681 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1682 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1683 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1684# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1685# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1686# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1687# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1688# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1689#elif \
1690 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1691 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1692 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1693 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1694 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1695 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1696 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1697 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1698 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1699 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1700 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1701 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1702 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1703 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1704 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1705 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1706# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1707 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1708# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1709 (__extension__ ({ \
1710 double hedley_probability_ = (probability); \
1711 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1712 }))
1713# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1714 (__extension__ ({ \
1715 double hedley_probability_ = (probability); \
1716 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1717 }))
1718# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1719# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1720#else
1721# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1722# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1723# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1724# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1725# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1726#endif
1727#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1728 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1729#endif
1730
1731#if defined(JSON_HEDLEY_MALLOC)
1732 #undef JSON_HEDLEY_MALLOC
1733#endif
1734#if \
1735 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1736 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1737 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1738 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1739 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1740 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1741 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1742 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1743 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1744 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1745 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1746 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1747 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1748 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1749 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1750 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1751 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1752 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1753 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1754#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1755 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1756#elif \
1757 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1758 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1759 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1760#else
1761 #define JSON_HEDLEY_MALLOC
1762#endif
1763
1764#if defined(JSON_HEDLEY_PURE)
1765 #undef JSON_HEDLEY_PURE
1766#endif
1767#if \
1768 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1769 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1770 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1771 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1772 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1773 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1774 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1775 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1776 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1777 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1778 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1779 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1780 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1781 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1782 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1783 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1784 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1785 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1786 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1787# define JSON_HEDLEY_PURE __attribute__((__pure__))
1788#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1789# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1790#elif defined(__cplusplus) && \
1791 ( \
1792 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1793 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1794 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1795 )
1796# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1797#else
1798# define JSON_HEDLEY_PURE
1799#endif
1800
1801#if defined(JSON_HEDLEY_CONST)
1802 #undef JSON_HEDLEY_CONST
1803#endif
1804#if \
1805 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1806 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1807 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1808 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1809 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1810 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1811 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1812 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1813 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1814 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1815 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1816 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1817 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1818 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1819 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1820 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1821 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1822 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1823 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1824 #define JSON_HEDLEY_CONST __attribute__((__const__))
1825#elif \
1826 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1827 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1828#else
1829 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1830#endif
1831
1832#if defined(JSON_HEDLEY_RESTRICT)
1833 #undef JSON_HEDLEY_RESTRICT
1834#endif
1835#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1836 #define JSON_HEDLEY_RESTRICT restrict
1837#elif \
1838 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1839 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1840 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1841 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1842 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1843 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1844 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1845 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1846 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1847 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1848 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1849 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1850 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1851 defined(__clang__) || \
1852 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1853 #define JSON_HEDLEY_RESTRICT __restrict
1854#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1855 #define JSON_HEDLEY_RESTRICT _Restrict
1856#else
1857 #define JSON_HEDLEY_RESTRICT
1858#endif
1859
1860#if defined(JSON_HEDLEY_INLINE)
1861 #undef JSON_HEDLEY_INLINE
1862#endif
1863#if \
1864 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1865 (defined(__cplusplus) && (__cplusplus >= 199711L))
1866 #define JSON_HEDLEY_INLINE inline
1867#elif \
1868 defined(JSON_HEDLEY_GCC_VERSION) || \
1869 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1870 #define JSON_HEDLEY_INLINE __inline__
1871#elif \
1872 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1873 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1874 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1875 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1876 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1877 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1878 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1879 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1880 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1881 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1882 #define JSON_HEDLEY_INLINE __inline
1883#else
1884 #define JSON_HEDLEY_INLINE
1885#endif
1886
1887#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1888 #undef JSON_HEDLEY_ALWAYS_INLINE
1889#endif
1890#if \
1891 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1892 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1893 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1894 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1895 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1896 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1897 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1898 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1899 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1900 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1901 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1902 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1903 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1904 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1905 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1906 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1907 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1908 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1909 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1910# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1911#elif \
1912 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1913 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1914# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1915#elif defined(__cplusplus) && \
1916 ( \
1917 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1918 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1919 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1920 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1921 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1922 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1923 )
1924# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1925#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1926# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1927#else
1928# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1929#endif
1930
1931#if defined(JSON_HEDLEY_NEVER_INLINE)
1932 #undef JSON_HEDLEY_NEVER_INLINE
1933#endif
1934#if \
1935 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1936 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1937 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1938 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1939 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1940 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1941 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1942 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1943 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1944 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1945 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1946 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1947 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1948 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1949 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1950 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1951 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1952 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1953 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1954 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1955#elif \
1956 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1957 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1958 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1959#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1960 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1961#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1962 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1963#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1964 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1965#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1966 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1967#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1968 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1969#else
1970 #define JSON_HEDLEY_NEVER_INLINE
1971#endif
1972
1973#if defined(JSON_HEDLEY_PRIVATE)
1974 #undef JSON_HEDLEY_PRIVATE
1975#endif
1976#if defined(JSON_HEDLEY_PUBLIC)
1977 #undef JSON_HEDLEY_PUBLIC
1978#endif
1979#if defined(JSON_HEDLEY_IMPORT)
1980 #undef JSON_HEDLEY_IMPORT
1981#endif
1982#if defined(_WIN32) || defined(__CYGWIN__)
1983# define JSON_HEDLEY_PRIVATE
1984# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1985# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1986#else
1987# if \
1988 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1989 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1990 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1991 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1992 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1993 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1994 ( \
1995 defined(__TI_EABI__) && \
1996 ( \
1997 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1998 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1999 ) \
2000 ) || \
2001 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2002# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
2003# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
2004# else
2005# define JSON_HEDLEY_PRIVATE
2006# define JSON_HEDLEY_PUBLIC
2007# endif
2008# define JSON_HEDLEY_IMPORT extern
2009#endif
2010
2011#if defined(JSON_HEDLEY_NO_THROW)
2012 #undef JSON_HEDLEY_NO_THROW
2013#endif
2014#if \
2015 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2016 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2017 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2018 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2019 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2020#elif \
2021 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2022 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2023 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2024 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2025#else
2026 #define JSON_HEDLEY_NO_THROW
2027#endif
2028
2029#if defined(JSON_HEDLEY_FALL_THROUGH)
2030 #undef JSON_HEDLEY_FALL_THROUGH
2031#endif
2032#if \
2033 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2034 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2035 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2036 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2037#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2038 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2039#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2040 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2041#elif defined(__fallthrough) /* SAL */
2042 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2043#else
2044 #define JSON_HEDLEY_FALL_THROUGH
2045#endif
2046
2047#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2048 #undef JSON_HEDLEY_RETURNS_NON_NULL
2049#endif
2050#if \
2051 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2052 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2053 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2054 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2055#elif defined(_Ret_notnull_) /* SAL */
2056 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2057#else
2058 #define JSON_HEDLEY_RETURNS_NON_NULL
2059#endif
2060
2061#if defined(JSON_HEDLEY_ARRAY_PARAM)
2062 #undef JSON_HEDLEY_ARRAY_PARAM
2063#endif
2064#if \
2065 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2066 !defined(__STDC_NO_VLA__) && \
2067 !defined(__cplusplus) && \
2068 !defined(JSON_HEDLEY_PGI_VERSION) && \
2069 !defined(JSON_HEDLEY_TINYC_VERSION)
2070 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2071#else
2072 #define JSON_HEDLEY_ARRAY_PARAM(name)
2073#endif
2074
2075#if defined(JSON_HEDLEY_IS_CONSTANT)
2076 #undef JSON_HEDLEY_IS_CONSTANT
2077#endif
2078#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2079 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2080#endif
2081/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2082 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2083#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2084 #undef JSON_HEDLEY_IS_CONSTEXPR_
2085#endif
2086#if \
2087 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2088 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2089 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2090 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2091 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2092 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2093 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2094 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2095 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2096 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2097 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2098#endif
2099#if !defined(__cplusplus)
2100# if \
2101 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2102 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2103 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2104 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2105 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2106 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2107 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2108#if defined(__INTPTR_TYPE__)
2109 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2110#else
2111 #include <stdint.h>
2112 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2113#endif
2114# elif \
2115 ( \
2116 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2117 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2118 !defined(JSON_HEDLEY_PGI_VERSION) && \
2119 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2120 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2121 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2122 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2123 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2124 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2125#if defined(__INTPTR_TYPE__)
2126 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2127#else
2128 #include <stdint.h>
2129 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2130#endif
2131# elif \
2132 defined(JSON_HEDLEY_GCC_VERSION) || \
2133 defined(JSON_HEDLEY_INTEL_VERSION) || \
2134 defined(JSON_HEDLEY_TINYC_VERSION) || \
2135 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2136 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2137 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2138 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2139 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2140 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2141 defined(__clang__)
2142# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2143 sizeof(void) != \
2144 sizeof(*( \
2145 1 ? \
2146 ((void*) ((expr) * 0L) ) : \
2147((struct { char v[sizeof(void) * 2]; } *) 1) \
2148 ) \
2149 ) \
2150 )
2151# endif
2152#endif
2153#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2154 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2155 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2156 #endif
2157 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2158#else
2159 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2160 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2161 #endif
2162 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2163#endif
2164
2165#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2166 #undef JSON_HEDLEY_BEGIN_C_DECLS
2167#endif
2168#if defined(JSON_HEDLEY_END_C_DECLS)
2169 #undef JSON_HEDLEY_END_C_DECLS
2170#endif
2171#if defined(JSON_HEDLEY_C_DECL)
2172 #undef JSON_HEDLEY_C_DECL
2173#endif
2174#if defined(__cplusplus)
2175 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2176 #define JSON_HEDLEY_END_C_DECLS }
2177 #define JSON_HEDLEY_C_DECL extern "C"
2178#else
2179 #define JSON_HEDLEY_BEGIN_C_DECLS
2180 #define JSON_HEDLEY_END_C_DECLS
2181 #define JSON_HEDLEY_C_DECL
2182#endif
2183
2184#if defined(JSON_HEDLEY_STATIC_ASSERT)
2185 #undef JSON_HEDLEY_STATIC_ASSERT
2186#endif
2187#if \
2188 !defined(__cplusplus) && ( \
2189 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2190 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2191 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2192 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2193 defined(_Static_assert) \
2194 )
2195# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2196#elif \
2197 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2198 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2199 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2200# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2201#else
2202# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2203#endif
2204
2205#if defined(JSON_HEDLEY_NULL)
2206 #undef JSON_HEDLEY_NULL
2207#endif
2208#if defined(__cplusplus)
2209 #if __cplusplus >= 201103L
2210 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2211 #elif defined(NULL)
2212 #define JSON_HEDLEY_NULL NULL
2213 #else
2214 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2215 #endif
2216#elif defined(NULL)
2217 #define JSON_HEDLEY_NULL NULL
2218#else
2219 #define JSON_HEDLEY_NULL ((void*) 0)
2220#endif
2221
2222#if defined(JSON_HEDLEY_MESSAGE)
2223 #undef JSON_HEDLEY_MESSAGE
2224#endif
2225#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2226# define JSON_HEDLEY_MESSAGE(msg) \
2227 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2228 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2229 JSON_HEDLEY_PRAGMA(message msg) \
2230 JSON_HEDLEY_DIAGNOSTIC_POP
2231#elif \
2232 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2233 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2234# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2235#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2236# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2237#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2238# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2239#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2240# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2241#else
2242# define JSON_HEDLEY_MESSAGE(msg)
2243#endif
2244
2245#if defined(JSON_HEDLEY_WARNING)
2246 #undef JSON_HEDLEY_WARNING
2247#endif
2248#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2249# define JSON_HEDLEY_WARNING(msg) \
2250 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2251 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2252 JSON_HEDLEY_PRAGMA(clang warning msg) \
2253 JSON_HEDLEY_DIAGNOSTIC_POP
2254#elif \
2255 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2256 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2257 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2258# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2259#elif \
2260 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2261 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2262# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2263#else
2264# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2265#endif
2266
2267#if defined(JSON_HEDLEY_REQUIRE)
2268 #undef JSON_HEDLEY_REQUIRE
2269#endif
2270#if defined(JSON_HEDLEY_REQUIRE_MSG)
2271 #undef JSON_HEDLEY_REQUIRE_MSG
2272#endif
2273#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2274# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2275# define JSON_HEDLEY_REQUIRE(expr) \
2276 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2277 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2278 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2279 JSON_HEDLEY_DIAGNOSTIC_POP
2280# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2281 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2282 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2283 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2284 JSON_HEDLEY_DIAGNOSTIC_POP
2285# else
2286# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2287# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2288# endif
2289#else
2290# define JSON_HEDLEY_REQUIRE(expr)
2291# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2292#endif
2293
2294#if defined(JSON_HEDLEY_FLAGS)
2295 #undef JSON_HEDLEY_FLAGS
2296#endif
2297#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2298 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2299#else
2300 #define JSON_HEDLEY_FLAGS
2301#endif
2302
2303#if defined(JSON_HEDLEY_FLAGS_CAST)
2304 #undef JSON_HEDLEY_FLAGS_CAST
2305#endif
2306#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2307# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2308 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2309 _Pragma("warning(disable:188)") \
2310 ((T) (expr)); \
2311 JSON_HEDLEY_DIAGNOSTIC_POP \
2312 }))
2313#else
2314# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2315#endif
2316
2317#if defined(JSON_HEDLEY_EMPTY_BASES)
2318 #undef JSON_HEDLEY_EMPTY_BASES
2319#endif
2320#if \
2321 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2322 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2323 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2324#else
2325 #define JSON_HEDLEY_EMPTY_BASES
2326#endif
2327
2328/* Remaining macros are deprecated. */
2329
2330#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2331 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2332#endif
2333#if defined(__clang__)
2334 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2335#else
2336 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2337#endif
2338
2339#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2340 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2341#endif
2342#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2343
2344#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2345 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2346#endif
2347#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2348
2349#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2350 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2351#endif
2352#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2353
2354#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2355 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2356#endif
2357#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2358
2359#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2360 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2361#endif
2362#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2363
2364#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2365 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2366#endif
2367#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2368
2369#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2370 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2371#endif
2372#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2373
2374#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2375
2376
2377// This file contains all internal macro definitions (except those affecting ABI)
2378// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2379
2380// #include <nlohmann/detail/abi_macros.hpp>
2381
2382
2383// exclude unsupported compilers
2384#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2385 #if defined(__clang__)
2386 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2387 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2388 #endif
2389 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2390 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2391 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2392 #endif
2393 #endif
2394#endif
2395
2396// C++ language standard detection
2397// if the user manually specified the used C++ version, this is skipped
2398#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)
2399 #if (defined(__cplusplus) && __cplusplus > 202302L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202302L)
2400 #define JSON_HAS_CPP_26
2401 #define JSON_HAS_CPP_23
2402 #define JSON_HAS_CPP_20
2403 #define JSON_HAS_CPP_17
2404 #define JSON_HAS_CPP_14
2405 #elif (defined(__cplusplus) && __cplusplus > 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L)
2406 #define JSON_HAS_CPP_23
2407 #define JSON_HAS_CPP_20
2408 #define JSON_HAS_CPP_17
2409 #define JSON_HAS_CPP_14
2410 #elif (defined(__cplusplus) && __cplusplus > 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L)
2411 #define JSON_HAS_CPP_20
2412 #define JSON_HAS_CPP_17
2413 #define JSON_HAS_CPP_14
2414 #elif (defined(__cplusplus) && __cplusplus > 201402L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2415 #define JSON_HAS_CPP_17
2416 #define JSON_HAS_CPP_14
2417 #elif (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2418 #define JSON_HAS_CPP_14
2419 #endif
2420 // the cpp 11 flag is always specified because it is the minimal required version
2421 #define JSON_HAS_CPP_11
2422#endif
2423
2424#ifdef __has_include
2425 #if __has_include(<version>)
2426 #include <version>
2427 #endif
2428#endif
2429
2430#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2431 #ifdef JSON_HAS_CPP_17
2432 #if defined(__cpp_lib_filesystem)
2433 #define JSON_HAS_FILESYSTEM 1
2434 #elif defined(__cpp_lib_experimental_filesystem)
2435 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2436 #elif !defined(__has_include)
2437 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2438 #elif __has_include(<filesystem>)
2439 #define JSON_HAS_FILESYSTEM 1
2440 #elif __has_include(<experimental/filesystem>)
2441 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2442 #endif
2443
2444 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2445 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2446 #undef JSON_HAS_FILESYSTEM
2447 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2448 #endif
2449
2450 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2451 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2452 #undef JSON_HAS_FILESYSTEM
2453 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2454 #endif
2455
2456 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2457 #if defined(__clang_major__) && __clang_major__ < 7
2458 #undef JSON_HAS_FILESYSTEM
2459 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2460 #endif
2461
2462 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2463 #if defined(_MSC_VER) && _MSC_VER < 1914
2464 #undef JSON_HAS_FILESYSTEM
2465 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2466 #endif
2467
2468 // no filesystem support before iOS 13
2469 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2470 #undef JSON_HAS_FILESYSTEM
2471 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2472 #endif
2473
2474 // no filesystem support before macOS Catalina
2475 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2476 #undef JSON_HAS_FILESYSTEM
2477 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2478 #endif
2479 #endif
2480#endif
2481
2482#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2483 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2484#endif
2485
2486#ifndef JSON_HAS_FILESYSTEM
2487 #define JSON_HAS_FILESYSTEM 0
2488#endif
2489
2490#ifndef JSON_HAS_THREE_WAY_COMPARISON
2491 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2492 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2493 #define JSON_HAS_THREE_WAY_COMPARISON 1
2494 #else
2495 #define JSON_HAS_THREE_WAY_COMPARISON 0
2496 #endif
2497#endif
2498
2499#ifndef JSON_HAS_RANGES
2500 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has a syntax error
2501 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2502 #define JSON_HAS_RANGES 0
2503 #elif defined(__cpp_lib_ranges)
2504 #define JSON_HAS_RANGES 1
2505 #else
2506 #define JSON_HAS_RANGES 0
2507 #endif
2508#endif
2509
2510#ifndef JSON_HAS_STATIC_RTTI
2511 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2512 #define JSON_HAS_STATIC_RTTI 1
2513 #else
2514 #define JSON_HAS_STATIC_RTTI 0
2515 #endif
2516#endif
2517
2518#ifdef JSON_HAS_CPP_17
2519 #define JSON_INLINE_VARIABLE inline
2520#else
2521 #define JSON_INLINE_VARIABLE
2522#endif
2523
2524#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2525 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2526#else
2527 #define JSON_NO_UNIQUE_ADDRESS
2528#endif
2529
2530// disable documentation warnings on clang
2531#if defined(__clang__)
2532 #pragma clang diagnostic push
2533 #pragma clang diagnostic ignored "-Wdocumentation"
2534 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2535#endif
2536
2537// allow disabling exceptions
2538#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2539 #define JSON_THROW(exception) throw exception
2540 #define JSON_TRY try
2541 #define JSON_CATCH(exception) catch(exception)
2542 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2543#else
2544 #include <cstdlib>
2545 #define JSON_THROW(exception) std::abort()
2546 #define JSON_TRY if(true)
2547 #define JSON_CATCH(exception) if(false)
2548 #define JSON_INTERNAL_CATCH(exception) if(false)
2549#endif
2550
2551// override exception macros
2552#if defined(JSON_THROW_USER)
2553 #undef JSON_THROW
2554 #define JSON_THROW JSON_THROW_USER
2555#endif
2556#if defined(JSON_TRY_USER)
2557 #undef JSON_TRY
2558 #define JSON_TRY JSON_TRY_USER
2559#endif
2560#if defined(JSON_CATCH_USER)
2561 #undef JSON_CATCH
2562 #define JSON_CATCH JSON_CATCH_USER
2563 #undef JSON_INTERNAL_CATCH
2564 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2565#endif
2566#if defined(JSON_INTERNAL_CATCH_USER)
2567 #undef JSON_INTERNAL_CATCH
2568 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2569#endif
2570
2571// allow overriding assert
2572#if !defined(JSON_ASSERT)
2573 #include <cassert> // assert
2574 #define JSON_ASSERT(x) assert(x)
2575#endif
2576
2577// allow accessing some private functions (needed by the test suite)
2578#if defined(JSON_TESTS_PRIVATE)
2579 #define JSON_PRIVATE_UNLESS_TESTED public
2580#else
2581 #define JSON_PRIVATE_UNLESS_TESTED private
2582#endif
2583
2589#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2590 template<typename BasicJsonType> \
2591 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2592 { \
2593 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2594 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2595 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2596 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2597 auto it = std::find_if(std::begin(m), std::end(m), \
2598 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2599 { \
2600 return ej_pair.first == e; \
2601 }); \
2602 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2603 } \
2604 template<typename BasicJsonType> \
2605 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2606 { \
2607 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2608 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2609 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2610 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2611 auto it = std::find_if(std::begin(m), std::end(m), \
2612 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2613 { \
2614 return ej_pair.second == j; \
2615 }); \
2616 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2617 }
2618
2619// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2620// may be removed in the future once the class is split.
2621
2622#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2623 template<template<typename, typename, typename...> class ObjectType, \
2624 template<typename, typename...> class ArrayType, \
2625 class StringType, class BooleanType, class NumberIntegerType, \
2626 class NumberUnsignedType, class NumberFloatType, \
2627 template<typename> class AllocatorType, \
2628 template<typename, typename = void> class JSONSerializer, \
2629 class BinaryType, \
2630 class CustomBaseClass>
2631
2632#define NLOHMANN_BASIC_JSON_TPL \
2633 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2634 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2635 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2636
2637// Macros to simplify conversion from/to types
2638
2639#define NLOHMANN_JSON_EXPAND( x ) x
2640#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
2641#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2642 NLOHMANN_JSON_PASTE64, \
2643 NLOHMANN_JSON_PASTE63, \
2644 NLOHMANN_JSON_PASTE62, \
2645 NLOHMANN_JSON_PASTE61, \
2646 NLOHMANN_JSON_PASTE60, \
2647 NLOHMANN_JSON_PASTE59, \
2648 NLOHMANN_JSON_PASTE58, \
2649 NLOHMANN_JSON_PASTE57, \
2650 NLOHMANN_JSON_PASTE56, \
2651 NLOHMANN_JSON_PASTE55, \
2652 NLOHMANN_JSON_PASTE54, \
2653 NLOHMANN_JSON_PASTE53, \
2654 NLOHMANN_JSON_PASTE52, \
2655 NLOHMANN_JSON_PASTE51, \
2656 NLOHMANN_JSON_PASTE50, \
2657 NLOHMANN_JSON_PASTE49, \
2658 NLOHMANN_JSON_PASTE48, \
2659 NLOHMANN_JSON_PASTE47, \
2660 NLOHMANN_JSON_PASTE46, \
2661 NLOHMANN_JSON_PASTE45, \
2662 NLOHMANN_JSON_PASTE44, \
2663 NLOHMANN_JSON_PASTE43, \
2664 NLOHMANN_JSON_PASTE42, \
2665 NLOHMANN_JSON_PASTE41, \
2666 NLOHMANN_JSON_PASTE40, \
2667 NLOHMANN_JSON_PASTE39, \
2668 NLOHMANN_JSON_PASTE38, \
2669 NLOHMANN_JSON_PASTE37, \
2670 NLOHMANN_JSON_PASTE36, \
2671 NLOHMANN_JSON_PASTE35, \
2672 NLOHMANN_JSON_PASTE34, \
2673 NLOHMANN_JSON_PASTE33, \
2674 NLOHMANN_JSON_PASTE32, \
2675 NLOHMANN_JSON_PASTE31, \
2676 NLOHMANN_JSON_PASTE30, \
2677 NLOHMANN_JSON_PASTE29, \
2678 NLOHMANN_JSON_PASTE28, \
2679 NLOHMANN_JSON_PASTE27, \
2680 NLOHMANN_JSON_PASTE26, \
2681 NLOHMANN_JSON_PASTE25, \
2682 NLOHMANN_JSON_PASTE24, \
2683 NLOHMANN_JSON_PASTE23, \
2684 NLOHMANN_JSON_PASTE22, \
2685 NLOHMANN_JSON_PASTE21, \
2686 NLOHMANN_JSON_PASTE20, \
2687 NLOHMANN_JSON_PASTE19, \
2688 NLOHMANN_JSON_PASTE18, \
2689 NLOHMANN_JSON_PASTE17, \
2690 NLOHMANN_JSON_PASTE16, \
2691 NLOHMANN_JSON_PASTE15, \
2692 NLOHMANN_JSON_PASTE14, \
2693 NLOHMANN_JSON_PASTE13, \
2694 NLOHMANN_JSON_PASTE12, \
2695 NLOHMANN_JSON_PASTE11, \
2696 NLOHMANN_JSON_PASTE10, \
2697 NLOHMANN_JSON_PASTE9, \
2698 NLOHMANN_JSON_PASTE8, \
2699 NLOHMANN_JSON_PASTE7, \
2700 NLOHMANN_JSON_PASTE6, \
2701 NLOHMANN_JSON_PASTE5, \
2702 NLOHMANN_JSON_PASTE4, \
2703 NLOHMANN_JSON_PASTE3, \
2704 NLOHMANN_JSON_PASTE2, \
2705 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2706#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2707#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2708#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2709#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2710#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2711#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)
2712#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)
2713#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)
2714#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)
2715#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)
2716#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)
2717#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)
2718#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)
2719#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)
2720#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)
2721#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)
2722#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)
2723#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)
2724#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)
2725#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)
2726#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)
2727#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)
2728#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)
2729#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)
2730#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)
2731#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)
2732#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)
2733#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)
2734#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)
2735#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)
2736#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)
2737#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)
2738#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)
2739#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)
2740#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)
2741#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)
2742#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)
2743#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)
2744#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)
2745#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)
2746#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)
2747#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)
2748#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)
2749#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)
2750#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)
2751#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)
2752#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)
2753#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)
2754#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)
2755#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)
2756#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)
2757#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)
2758#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)
2759#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)
2760#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)
2761#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)
2762#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)
2763#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)
2764#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)
2765#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)
2766#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)
2767#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)
2768#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)
2769
2770#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2771#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2772#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;
2773
2780#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2781 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2782 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2783 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2784 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2785
2792#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2793 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2794 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2795 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2796 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__)) }
2797
2804#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2805 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2806 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2807
2814#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2815 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2816 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2817 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2818 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2819
2826#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2827 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2828 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2829 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2830 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__)) }
2831
2838#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2839 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2840 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2841
2848#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \
2849 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2850 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__)) } \
2851 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2852 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__)) }
2853
2860#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2861 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2862 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__)) } \
2863 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2864 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__)) }
2865
2872#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2873 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2874 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__)) }
2875
2882#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \
2883 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2884 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__)) } \
2885 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2886 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__)) }
2887
2894#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2895 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2896 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__)) } \
2897 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2898 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__)) }
2899
2906#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2907 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2908 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__)) }
2909
2910// inspired from https://stackoverflow.com/a/26745591
2911// allows calling any std function as if (e.g., with begin):
2912// using std::begin; begin(x);
2913//
2914// it allows using the detected idiom to retrieve the return type
2915// of such an expression
2916#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2917 namespace detail { \
2918 using std::std_name; \
2919 \
2920 template<typename... T> \
2921 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2922 } \
2923 \
2924 namespace detail2 { \
2925 struct std_name##_tag \
2926 { \
2927 }; \
2928 \
2929 template<typename... T> \
2930 std_name##_tag std_name(T&&...); \
2931 \
2932 template<typename... T> \
2933 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2934 \
2935 template<typename... T> \
2936 struct would_call_std_##std_name \
2937 { \
2938 static constexpr auto const value = ::nlohmann::detail:: \
2939 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2940 }; \
2941 } /* namespace detail2 */ \
2942 \
2943 template<typename... T> \
2944 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2945 { \
2946 }
2947
2948#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2949 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2950#endif
2951
2952#if JSON_USE_IMPLICIT_CONVERSIONS
2953 #define JSON_EXPLICIT
2954#else
2955 #define JSON_EXPLICIT explicit
2956#endif
2957
2958#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2959 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2960#endif
2961
2962#ifndef JSON_USE_GLOBAL_UDLS
2963 #define JSON_USE_GLOBAL_UDLS 1
2964#endif
2965
2966#if JSON_HAS_THREE_WAY_COMPARISON
2967 #include <compare> // partial_ordering
2968#endif
2969
2971namespace detail
2972{
2973
2975// JSON type enumeration //
2977
3002enum class value_t : std::uint8_t
3003{
3004 null,
3005 object,
3006 array,
3007 string,
3008 boolean,
3011 number_float,
3012 binary,
3013 discarded
3014};
3015
3029#if JSON_HAS_THREE_WAY_COMPARISON
3030 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
3031#else
3032 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3033#endif
3034{
3035 static constexpr std::array<std::uint8_t, 9> order = {{
3036 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
3037 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
3038 6 /* binary */
3039 }
3040 };
3041
3042 const auto l_index = static_cast<std::size_t>(lhs);
3043 const auto r_index = static_cast<std::size_t>(rhs);
3044#if JSON_HAS_THREE_WAY_COMPARISON
3045 if (l_index < order.size() && r_index < order.size())
3046 {
3047 return order[l_index] <=> order[r_index]; // *NOPAD*
3048 }
3049 return std::partial_ordering::unordered;
3050#else
3051 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
3052#endif
3053}
3054
3055// GCC selects the built-in operator< over an operator rewritten from
3056// a user-defined spaceship operator
3057// Clang, MSVC, and ICC select the rewritten candidate
3058// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
3059#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
3060inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3061{
3062 return std::is_lt(lhs <=> rhs); // *NOPAD*
3063}
3064#endif
3065
3066} // namespace detail
3068
3069// #include <nlohmann/detail/string_escape.hpp>
3070// __ _____ _____ _____
3071// __| | __| | | | JSON for Modern C++
3072// | | |__ | | | | | | version 3.12.0
3073// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3074//
3075// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3076// SPDX-License-Identifier: MIT
3077
3078
3079
3080// #include <nlohmann/detail/abi_macros.hpp>
3081
3082
3084namespace detail
3085{
3086
3100template<typename StringType>
3101inline void replace_substring(StringType& s, const StringType& f,
3102 const StringType& t)
3103{
3104 JSON_ASSERT(!f.empty());
3105 for (auto pos = s.find(f); // find the first occurrence of f
3106 pos != StringType::npos; // make sure f was found
3107 s.replace(pos, f.size(), t), // replace with t, and
3108 pos = s.find(f, pos + t.size())) // find the next occurrence of f
3109 {}
3110}
3111
3119template<typename StringType>
3120inline StringType escape(StringType s)
3121{
3122 replace_substring(s, StringType{"~"}, StringType{"~0"});
3123 replace_substring(s, StringType{"/"}, StringType{"~1"});
3124 return s;
3125}
3126
3134template<typename StringType>
3135inline void unescape(StringType& s)
3136{
3137 replace_substring(s, StringType{"~1"}, StringType{"/"});
3138 replace_substring(s, StringType{"~0"}, StringType{"~"});
3139}
3140
3141} // namespace detail
3143
3144// #include <nlohmann/detail/input/position_t.hpp>
3145// __ _____ _____ _____
3146// __| | __| | | | JSON for Modern C++
3147// | | |__ | | | | | | version 3.12.0
3148// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3149//
3150// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3151// SPDX-License-Identifier: MIT
3152
3153
3154
3155#include <cstddef> // size_t
3156
3157// #include <nlohmann/detail/abi_macros.hpp>
3158
3159
3161namespace detail
3162{
3163
3166{
3168 std::size_t chars_read_total = 0;
3172 std::size_t lines_read = 0;
3173
3175 constexpr operator size_t() const
3176 {
3177 return chars_read_total;
3178 }
3179};
3180
3181} // namespace detail
3183
3184// #include <nlohmann/detail/macro_scope.hpp>
3185
3186// #include <nlohmann/detail/meta/cpp_future.hpp>
3187// __ _____ _____ _____
3188// __| | __| | | | JSON for Modern C++
3189// | | |__ | | | | | | version 3.12.0
3190// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3191//
3192// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3193// SPDX-FileCopyrightText: 2018 The Abseil Authors
3194// SPDX-License-Identifier: MIT
3195
3196
3197
3198#include <array> // array
3199#include <cstddef> // size_t
3200#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3201#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3202
3203// #include <nlohmann/detail/macro_scope.hpp>
3204
3205
3207namespace detail
3208{
3209
3210template<typename T>
3211using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3212
3213#ifdef JSON_HAS_CPP_14
3214
3215// the following utilities are natively available in C++14
3216using std::enable_if_t;
3217using std::index_sequence;
3218using std::make_index_sequence;
3219using std::index_sequence_for;
3220
3221#else
3222
3223// alias templates to reduce boilerplate
3224template<bool B, typename T = void>
3225using enable_if_t = typename std::enable_if<B, T>::type;
3226
3227// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3228// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3229
3231
3232// integer_sequence
3233//
3234// Class template representing a compile-time integer sequence. An instantiation
3235// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3236// type through its template arguments (which is a common need when
3237// working with C++11 variadic templates). `absl::integer_sequence` is designed
3238// to be a drop-in replacement for C++14's `std::integer_sequence`.
3239//
3240// Example:
3241//
3242// template< class T, T... Ints >
3243// void user_function(integer_sequence<T, Ints...>);
3244//
3245// int main()
3246// {
3247// // user_function's `T` will be deduced to `int` and `Ints...`
3248// // will be deduced to `0, 1, 2, 3, 4`.
3249// user_function(make_integer_sequence<int, 5>());
3250// }
3251template <typename T, T... Ints>
3253{
3254 using value_type = T;
3255 static constexpr std::size_t size() noexcept
3256 {
3257 return sizeof...(Ints);
3258 }
3259};
3260
3261// index_sequence
3262//
3263// A helper template for an `integer_sequence` of `size_t`,
3264// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3265// `std::index_sequence`.
3266template <size_t... Ints>
3267using index_sequence = integer_sequence<size_t, Ints...>;
3268
3269namespace utility_internal
3270{
3271
3272template <typename Seq, size_t SeqSize, size_t Rem>
3273struct Extend;
3274
3275// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3276template <typename T, T... Ints, size_t SeqSize>
3277struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3278{
3279 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3280};
3281
3282template <typename T, T... Ints, size_t SeqSize>
3283struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3284{
3285 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3286};
3287
3288// Recursion helper for 'make_integer_sequence<T, N>'.
3289// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3290template <typename T, size_t N>
3291struct Gen
3292{
3293 using type =
3294 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3295};
3296
3297template <typename T>
3298struct Gen<T, 0>
3299{
3301};
3302
3303} // namespace utility_internal
3304
3305// Compile-time sequences of integers
3306
3307// make_integer_sequence
3308//
3309// This template alias is equivalent to
3310// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3311// replacement for C++14's `std::make_integer_sequence`.
3312template <typename T, T N>
3314
3315// make_index_sequence
3316//
3317// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3318// and is designed to be a drop-in replacement for C++14's
3319// `std::make_index_sequence`.
3320template <size_t N>
3322
3323// index_sequence_for
3324//
3325// Converts a typename pack into an index sequence of the same length, and
3326// is designed to be a drop-in replacement for C++14's
3327// `std::index_sequence_for()`
3328template <typename... Ts>
3330
3332
3333#endif
3334
3335// dispatch utility (taken from ranges-v3)
3336template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3337template<> struct priority_tag<0> {};
3338
3339// taken from ranges-v3
3340template<typename T>
3342{
3343 static JSON_INLINE_VARIABLE constexpr T value{};
3344};
3345
3346#ifndef JSON_HAS_CPP_17
3347 template<typename T>
3348 constexpr T static_const<T>::value;
3349#endif
3350
3351template<typename T, typename... Args>
3352constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3353{
3354 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3355}
3356
3357} // namespace detail
3359
3360// #include <nlohmann/detail/meta/type_traits.hpp>
3361// __ _____ _____ _____
3362// __| | __| | | | JSON for Modern C++
3363// | | |__ | | | | | | version 3.12.0
3364// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3365//
3366// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3367// SPDX-License-Identifier: MIT
3368
3369
3370
3371#include <limits> // numeric_limits
3372#include <string> // char_traits
3373#include <tuple> // tuple
3374#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3375#include <utility> // declval
3376#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3377 #include <cstddef> // byte
3378#endif
3379// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3380// __ _____ _____ _____
3381// __| | __| | | | JSON for Modern C++
3382// | | |__ | | | | | | version 3.12.0
3383// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3384//
3385// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3386// SPDX-License-Identifier: MIT
3387
3388
3389
3390#include <iterator> // random_access_iterator_tag
3391
3392// #include <nlohmann/detail/abi_macros.hpp>
3393
3394// #include <nlohmann/detail/meta/void_t.hpp>
3395
3396// #include <nlohmann/detail/meta/cpp_future.hpp>
3397
3398
3400namespace detail
3401{
3402
3403template<typename It, typename = void>
3405
3406template<typename It>
3408 It,
3409 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3410 typename It::reference, typename It::iterator_category >>
3411{
3412 using difference_type = typename It::difference_type;
3413 using value_type = typename It::value_type;
3414 using pointer = typename It::pointer;
3415 using reference = typename It::reference;
3416 using iterator_category = typename It::iterator_category;
3417};
3418
3419// This is required as some compilers implement std::iterator_traits in a way that
3420// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3421template<typename T, typename = void>
3423{
3424};
3425
3426template<typename T>
3427struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3428 : iterator_types<T>
3429{
3430};
3431
3432template<typename T>
3434{
3435 using iterator_category = std::random_access_iterator_tag;
3436 using value_type = T;
3437 using difference_type = ptrdiff_t;
3438 using pointer = T*;
3439 using reference = T&;
3440};
3441
3442} // namespace detail
3444
3445// #include <nlohmann/detail/macro_scope.hpp>
3446
3447// #include <nlohmann/detail/meta/call_std/begin.hpp>
3448// __ _____ _____ _____
3449// __| | __| | | | JSON for Modern C++
3450// | | |__ | | | | | | version 3.12.0
3451// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3452//
3453// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3454// SPDX-License-Identifier: MIT
3455
3456
3457
3458// #include <nlohmann/detail/macro_scope.hpp>
3459
3460
3462
3464
3466
3467// #include <nlohmann/detail/meta/call_std/end.hpp>
3468// __ _____ _____ _____
3469// __| | __| | | | JSON for Modern C++
3470// | | |__ | | | | | | version 3.12.0
3471// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3472//
3473// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3474// SPDX-License-Identifier: MIT
3475
3476
3477
3478// #include <nlohmann/detail/macro_scope.hpp>
3479
3480
3482
3484
3486
3487// #include <nlohmann/detail/meta/cpp_future.hpp>
3488
3489// #include <nlohmann/detail/meta/detected.hpp>
3490
3491// #include <nlohmann/json_fwd.hpp>
3492// __ _____ _____ _____
3493// __| | __| | | | JSON for Modern C++
3494// | | |__ | | | | | | version 3.12.0
3495// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3496//
3497// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3498// SPDX-License-Identifier: MIT
3499
3500#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3501 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3502
3503 #include <cstdint> // int64_t, uint64_t
3504 #include <map> // map
3505 #include <memory> // allocator
3506 #include <string> // string
3507 #include <vector> // vector
3508
3509 // #include <nlohmann/detail/abi_macros.hpp>
3510
3511
3518
3526 template<typename T = void, typename SFINAE = void>
3527 struct adl_serializer;
3528
3531 template<template<typename U, typename V, typename... Args> class ObjectType =
3532 std::map,
3533 template<typename U, typename... Args> class ArrayType = std::vector,
3534 class StringType = std::string, class BooleanType = bool,
3535 class NumberIntegerType = std::int64_t,
3536 class NumberUnsignedType = std::uint64_t,
3537 class NumberFloatType = double,
3538 template<typename U> class AllocatorType = std::allocator,
3539 template<typename T, typename SFINAE = void> class JSONSerializer =
3541 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3542 class CustomBaseClass = void>
3543 class basic_json;
3544
3547 template<typename RefStringType>
3548 class json_pointer;
3549
3555
3558 template<class Key, class T, class IgnoredLess, class Allocator>
3559 struct ordered_map;
3560
3564
3566
3567#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3568
3569
3579namespace detail
3580{
3581
3583// helpers //
3585
3586// Note to maintainers:
3587//
3588// Every trait in this file expects a non-CV-qualified type.
3589// The only exceptions are in the 'aliases for detected' section
3590// (i.e., those of the form: decltype(T::member_function(std::declval<T>())))
3591//
3592// In this case, T has to be properly CV-qualified to constraint the function arguments
3593// (e.g., to_json(BasicJsonType&, const T&))
3594
3595template<typename> struct is_basic_json : std::false_type {};
3596
3598struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3599
3600// used by exceptions create() member functions
3601// true_type for the pointer to possibly cv-qualified basic_json or std::nullptr_t
3602// false_type otherwise
3603template<typename BasicJsonContext>
3605 std::integral_constant < bool,
3606 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3607 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3608{};
3609
3611// json_ref helpers //
3613
3614template<typename>
3615class json_ref;
3616
3617template<typename>
3618struct is_json_ref : std::false_type {};
3619
3620template<typename T>
3621struct is_json_ref<json_ref<T>> : std::true_type {};
3622
3624// aliases for detected //
3626
3627template<typename T>
3628using mapped_type_t = typename T::mapped_type;
3629
3630template<typename T>
3631using key_type_t = typename T::key_type;
3632
3633template<typename T>
3634using value_type_t = typename T::value_type;
3635
3636template<typename T>
3637using difference_type_t = typename T::difference_type;
3638
3639template<typename T>
3640using pointer_t = typename T::pointer;
3641
3642template<typename T>
3643using reference_t = typename T::reference;
3644
3645template<typename T>
3646using iterator_category_t = typename T::iterator_category;
3647
3648template<typename T, typename... Args>
3649using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3650
3651template<typename T, typename... Args>
3652using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3653
3654template<typename T, typename U>
3655using get_template_function = decltype(std::declval<T>().template get<U>());
3656
3657// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3658template<typename BasicJsonType, typename T, typename = void>
3659struct has_from_json : std::false_type {};
3660
3661// trait checking if j.get<T> is valid
3662// use this trait instead of std::is_constructible or std::is_convertible,
3663// both rely on, or make use of implicit conversions, and thus fail when T
3664// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3665template <typename BasicJsonType, typename T>
3670
3671template<typename BasicJsonType, typename T>
3672struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3673{
3674 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3675
3676 static constexpr bool value =
3678 const BasicJsonType&, T&>::value;
3679};
3680
3681// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3682// this overload is used for non-default-constructible user-defined-types
3683template<typename BasicJsonType, typename T, typename = void>
3684struct has_non_default_from_json : std::false_type {};
3685
3686template<typename BasicJsonType, typename T>
3687struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3688{
3689 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3690
3691 static constexpr bool value =
3693 const BasicJsonType&>::value;
3694};
3695
3696// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3697// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3698template<typename BasicJsonType, typename T, typename = void>
3699struct has_to_json : std::false_type {};
3700
3701template<typename BasicJsonType, typename T>
3702struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3703{
3704 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3705
3706 static constexpr bool value =
3707 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3708 T>::value;
3709};
3710
3711template<typename T>
3712using detect_key_compare = typename T::key_compare;
3713
3714template<typename T>
3715struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3716
3717// obtains the actual object key comparator
3718template<typename BasicJsonType>
3720{
3721 using object_t = typename BasicJsonType::object_t;
3722 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3723 using type = typename std::conditional < has_key_compare<object_t>::value,
3724 typename object_t::key_compare, object_comparator_t>::type;
3725};
3726
3727template<typename BasicJsonType>
3729
3731// char_traits //
3733
3734// Primary template of char_traits calls std char_traits
3735template<typename T>
3736struct char_traits : std::char_traits<T>
3737{};
3738
3739// Explicitly define char traits for unsigned char since it is not standard
3740template<>
3741struct char_traits<unsigned char> : std::char_traits<char>
3742{
3743 using char_type = unsigned char;
3744 using int_type = uint64_t;
3745
3746 // Redefine to_int_type function
3747 static int_type to_int_type(char_type c) noexcept
3748 {
3749 return static_cast<int_type>(c);
3750 }
3751
3753 {
3754 return static_cast<char_type>(i);
3755 }
3756
3757 static constexpr int_type eof() noexcept
3758 {
3759 return static_cast<int_type>(std::char_traits<char>::eof());
3760 }
3761};
3762
3763// Explicitly define char traits for signed char since it is not standard
3764template<>
3765struct char_traits<signed char> : std::char_traits<char>
3766{
3767 using char_type = signed char;
3768 using int_type = uint64_t;
3769
3770 // Redefine to_int_type function
3771 static int_type to_int_type(char_type c) noexcept
3772 {
3773 return static_cast<int_type>(c);
3774 }
3775
3777 {
3778 return static_cast<char_type>(i);
3779 }
3780
3781 static constexpr int_type eof() noexcept
3782 {
3783 return static_cast<int_type>(std::char_traits<char>::eof());
3784 }
3785};
3786
3787#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3788template<>
3789struct char_traits<std::byte> : std::char_traits<char>
3790{
3791 using char_type = std::byte;
3792 using int_type = uint64_t;
3793
3794 static int_type to_int_type(char_type c) noexcept
3795 {
3796 return static_cast<int_type>(std::to_integer<unsigned char>(c));
3797 }
3798
3799 static char_type to_char_type(int_type i) noexcept
3800 {
3801 return std::byte(static_cast<unsigned char>(i));
3802 }
3803
3804 static constexpr int_type eof() noexcept
3805 {
3806 return static_cast<int_type>(std::char_traits<char>::eof());
3807 }
3808};
3809#endif
3810
3812// is_ functions //
3814
3815// https://en.cppreference.com/w/cpp/types/conjunction
3816template<class...> struct conjunction : std::true_type { };
3817template<class B> struct conjunction<B> : B { };
3818template<class B, class... Bn>
3819struct conjunction<B, Bn...>
3820: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3821
3822// https://en.cppreference.com/w/cpp/types/negation
3823template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3824
3825// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3826// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3827// This causes compile errors in e.g., Clang 3.5 or GCC 4.9.
3828template <typename T>
3829struct is_default_constructible : std::is_default_constructible<T> {};
3830
3831template <typename T1, typename T2>
3832struct is_default_constructible<std::pair<T1, T2>>
3833 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3834
3835template <typename T1, typename T2>
3836struct is_default_constructible<const std::pair<T1, T2>>
3837 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3838
3839template <typename... Ts>
3840struct is_default_constructible<std::tuple<Ts...>>
3841 : conjunction<is_default_constructible<Ts>...> {};
3842
3843template <typename... Ts>
3844struct is_default_constructible<const std::tuple<Ts...>>
3845 : conjunction<is_default_constructible<Ts>...> {};
3846
3847template <typename T, typename... Args>
3848struct is_constructible : std::is_constructible<T, Args...> {};
3849
3850template <typename T1, typename T2>
3851struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3852
3853template <typename T1, typename T2>
3854struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3855
3856template <typename... Ts>
3857struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3858
3859template <typename... Ts>
3860struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3861
3862template<typename T, typename = void>
3863struct is_iterator_traits : std::false_type {};
3864
3865template<typename T>
3879
3880template<typename T>
3882{
3883 private:
3884 using t_ref = typename std::add_lvalue_reference<T>::type;
3885
3886 using iterator = detected_t<result_of_begin, t_ref>;
3887 using sentinel = detected_t<result_of_end, t_ref>;
3888
3889 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3890 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3891 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3892 static constexpr auto is_iterator_begin =
3894
3895 public:
3896 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3897};
3898
3899template<typename R>
3900using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3901
3902template<typename T>
3904
3905// The following implementation of is_complete_type is taken from
3906// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3907// and is written by Xiang Fan who agreed to use it in this library.
3908
3909template<typename T, typename = void>
3910struct is_complete_type : std::false_type {};
3911
3912template<typename T>
3913struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3914
3915template<typename BasicJsonType, typename CompatibleObjectType,
3916 typename = void>
3917struct is_compatible_object_type_impl : std::false_type {};
3918
3919template<typename BasicJsonType, typename CompatibleObjectType>
3921 BasicJsonType, CompatibleObjectType,
3922 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3923 is_detected<key_type_t, CompatibleObjectType>::value >>
3924{
3925 using object_t = typename BasicJsonType::object_t;
3926
3927 // macOS's is_constructible does not play well with nonesuch...
3928 static constexpr bool value =
3929 is_constructible<typename object_t::key_type,
3930 typename CompatibleObjectType::key_type>::value &&
3931 is_constructible<typename object_t::mapped_type,
3932 typename CompatibleObjectType::mapped_type>::value;
3933};
3934
3935template<typename BasicJsonType, typename CompatibleObjectType>
3937 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3938
3939template<typename BasicJsonType, typename ConstructibleObjectType,
3940 typename = void>
3941struct is_constructible_object_type_impl : std::false_type {};
3942
3943template<typename BasicJsonType, typename ConstructibleObjectType>
3945 BasicJsonType, ConstructibleObjectType,
3946 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3947 is_detected<key_type_t, ConstructibleObjectType>::value >>
3948{
3949 using object_t = typename BasicJsonType::object_t;
3950
3951 static constexpr bool value =
3953 (std::is_move_assignable<ConstructibleObjectType>::value ||
3954 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3955 (is_constructible<typename ConstructibleObjectType::key_type,
3956 typename object_t::key_type>::value &&
3957 std::is_same <
3958 typename object_t::mapped_type,
3959 typename ConstructibleObjectType::mapped_type >::value)) ||
3960 (has_from_json<BasicJsonType,
3961 typename ConstructibleObjectType::mapped_type>::value ||
3963 BasicJsonType,
3964 typename ConstructibleObjectType::mapped_type >::value);
3965};
3966
3967template<typename BasicJsonType, typename ConstructibleObjectType>
3969 : is_constructible_object_type_impl<BasicJsonType,
3970 ConstructibleObjectType> {};
3971
3972template<typename BasicJsonType, typename CompatibleStringType>
3978
3979template<typename BasicJsonType, typename ConstructibleStringType>
3981{
3982 // launder type through decltype() to fix compilation failure on ICPC
3983#ifdef __INTEL_COMPILER
3984 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3985#else
3986 using laundered_type = ConstructibleStringType;
3987#endif
3988
3989 static constexpr auto value =
3990 conjunction <
3992 is_detected_exact<typename BasicJsonType::string_t::value_type,
3994};
3995
3996template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3997struct is_compatible_array_type_impl : std::false_type {};
3998
3999template<typename BasicJsonType, typename CompatibleArrayType>
4001 BasicJsonType, CompatibleArrayType,
4002 enable_if_t <
4003 is_detected<iterator_t, CompatibleArrayType>::value&&
4004 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
4005// special case for types like std::filesystem::path whose iterator's value_type are themselves
4006// c.f. https://github.com/nlohmann/json/pull/3073
4007 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
4008{
4009 static constexpr bool value =
4010 is_constructible<BasicJsonType,
4012};
4013
4014template<typename BasicJsonType, typename CompatibleArrayType>
4016 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
4017
4018template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
4019struct is_constructible_array_type_impl : std::false_type {};
4020
4021template<typename BasicJsonType, typename ConstructibleArrayType>
4023 BasicJsonType, ConstructibleArrayType,
4024 enable_if_t<std::is_same<ConstructibleArrayType,
4025 typename BasicJsonType::value_type>::value >>
4026 : std::true_type {};
4027
4028template<typename BasicJsonType, typename ConstructibleArrayType>
4030 BasicJsonType, ConstructibleArrayType,
4031 enable_if_t < !std::is_same<ConstructibleArrayType,
4032 typename BasicJsonType::value_type>::value&&
4033 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4034 is_default_constructible<ConstructibleArrayType>::value&&
4035(std::is_move_assignable<ConstructibleArrayType>::value ||
4036 std::is_copy_assignable<ConstructibleArrayType>::value)&&
4037is_detected<iterator_t, ConstructibleArrayType>::value&&
4038is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
4039is_detected<range_value_t, ConstructibleArrayType>::value&&
4040// special case for types like std::filesystem::path whose iterator's value_type are themselves
4041// c.f. https://github.com/nlohmann/json/pull/3073
4042!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
4044detected_t<range_value_t, ConstructibleArrayType >>::value >>
4045{
4047
4048 static constexpr bool value =
4049 std::is_same<value_type,
4050 typename BasicJsonType::array_t::value_type>::value ||
4051 has_from_json<BasicJsonType,
4054 BasicJsonType,
4056};
4057
4058template<typename BasicJsonType, typename ConstructibleArrayType>
4060 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
4061
4062template<typename RealIntegerType, typename CompatibleNumberIntegerType,
4063 typename = void>
4064struct is_compatible_integer_type_impl : std::false_type {};
4065
4066template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4068 RealIntegerType, CompatibleNumberIntegerType,
4069 enable_if_t < std::is_integral<RealIntegerType>::value&&
4070 std::is_integral<CompatibleNumberIntegerType>::value&&
4071 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
4072{
4073 // is there an assert somewhere on overflows?
4074 using RealLimits = std::numeric_limits<RealIntegerType>;
4075 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
4076
4077 static constexpr auto value =
4078 is_constructible<RealIntegerType,
4079 CompatibleNumberIntegerType>::value &&
4080 CompatibleLimits::is_integer &&
4081 RealLimits::is_signed == CompatibleLimits::is_signed;
4082};
4083
4084template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4086 : is_compatible_integer_type_impl<RealIntegerType,
4087 CompatibleNumberIntegerType> {};
4088
4089template<typename BasicJsonType, typename CompatibleType, typename = void>
4090struct is_compatible_type_impl: std::false_type {};
4091
4092template<typename BasicJsonType, typename CompatibleType>
4094 BasicJsonType, CompatibleType,
4095 enable_if_t<is_complete_type<CompatibleType>::value >>
4096{
4097 static constexpr bool value =
4099};
4100
4101template<typename BasicJsonType, typename CompatibleType>
4103 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
4104
4105template<typename T1, typename T2>
4106struct is_constructible_tuple : std::false_type {};
4107
4108template<typename T1, typename... Args>
4109struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
4110
4111template<typename BasicJsonType, typename T>
4112struct is_json_iterator_of : std::false_type {};
4113
4114template<typename BasicJsonType>
4115struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
4116
4117template<typename BasicJsonType>
4118struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
4119{};
4120
4121// checks if a given type T is a template specialization of Primary
4122template<template <typename...> class Primary, typename T>
4123struct is_specialization_of : std::false_type {};
4124
4125template<template <typename...> class Primary, typename... Args>
4126struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
4127
4128template<typename T>
4130
4131// checks if A and B are comparable using Compare functor
4132template<typename Compare, typename A, typename B, typename = void>
4133struct is_comparable : std::false_type {};
4134
4135template<typename Compare, typename A, typename B>
4136struct is_comparable<Compare, A, B, void_t<
4137decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
4138decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
4139>> : std::true_type {};
4140
4141template<typename T>
4142using detect_is_transparent = typename T::is_transparent;
4143
4144// type trait to check if KeyType can be used as an object key (without a BasicJsonType)
4145// see is_usable_as_basic_json_key_type below
4146template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4147 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4148using is_usable_as_key_type = typename std::conditional <
4150 && !(ExcludeObjectKeyType && std::is_same<KeyType,
4151 ObjectKeyType>::value)
4152 && (!RequireTransparentComparator
4153 || is_detected <detect_is_transparent, Comparator>::value)
4155 std::true_type,
4156 std::false_type >::type;
4157
4158// type trait to check if KeyType can be used as an object key
4159// true if:
4160// - KeyType is comparable with BasicJsonType::object_t::key_type
4161// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4162// - the comparator is transparent or RequireTransparentComparator is false
4163// - KeyType is not a JSON iterator or json_pointer
4164template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4165 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4166using is_usable_as_basic_json_key_type = typename std::conditional <
4167 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4168 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4169 RequireTransparentComparator, ExcludeObjectKeyType>::value
4171 std::true_type,
4172 std::false_type >::type;
4173
4174template<typename ObjectType, typename KeyType>
4175using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4176
4177// type trait to check if object_t has an erase() member functions accepting KeyType
4178template<typename BasicJsonType, typename KeyType>
4179using has_erase_with_key_type = typename std::conditional <
4180 is_detected <
4182 typename BasicJsonType::object_t, KeyType >::value,
4183 std::true_type,
4184 std::false_type >::type;
4185
4186// a naive helper to check if a type is an ordered_map (exploits the fact that
4187// ordered_map inherits capacity() from std::vector)
4188template <typename T>
4190{
4191 using one = char;
4192
4193 struct two
4194 {
4195 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4196 };
4197
4198 template <typename C> static one test( decltype(&C::capacity) ) ;
4199 template <typename C> static two test(...);
4200
4201 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4202};
4203
4204// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4205template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4207{
4208 return static_cast<T>(value);
4209}
4210
4211template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4213{
4214 return value;
4215}
4216
4217template<typename... Types>
4219
4220template<typename... Types>
4222
4223template<typename... Types>
4225
4226// there's a disjunction trait in another PR; replace when merged
4227template<typename... Types>
4228using same_sign = std::integral_constant < bool,
4229 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4230
4231template<typename OfType, typename T>
4232using never_out_of_range = std::integral_constant < bool,
4233 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4234 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4235
4236template<typename OfType, typename T,
4237 bool OfTypeSigned = std::is_signed<OfType>::value,
4238 bool TSigned = std::is_signed<T>::value>
4240
4241template<typename OfType, typename T>
4242struct value_in_range_of_impl2<OfType, T, false, false>
4243{
4244 static constexpr bool test(T val)
4245 {
4246 using CommonType = typename std::common_type<OfType, T>::type;
4247 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4248 }
4249};
4250
4251template<typename OfType, typename T>
4252struct value_in_range_of_impl2<OfType, T, true, false>
4253{
4254 static constexpr bool test(T val)
4255 {
4256 using CommonType = typename std::common_type<OfType, T>::type;
4257 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4258 }
4259};
4260
4261template<typename OfType, typename T>
4262struct value_in_range_of_impl2<OfType, T, false, true>
4263{
4264 static constexpr bool test(T val)
4265 {
4266 using CommonType = typename std::common_type<OfType, T>::type;
4267 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4268 }
4269};
4270
4271template<typename OfType, typename T>
4272struct value_in_range_of_impl2<OfType, T, true, true>
4273{
4274 static constexpr bool test(T val)
4275 {
4276 using CommonType = typename std::common_type<OfType, T>::type;
4277 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4278 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4279 }
4280};
4281
4282template<typename OfType, typename T,
4283 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4286
4287template<typename OfType, typename T>
4288struct value_in_range_of_impl1<OfType, T, false>
4289{
4290 static constexpr bool test(T val)
4291 {
4293 }
4294};
4295
4296template<typename OfType, typename T>
4297struct value_in_range_of_impl1<OfType, T, true>
4298{
4299 static constexpr bool test(T /*val*/)
4300 {
4301 return true;
4302 }
4303};
4304
4305template<typename OfType, typename T>
4306constexpr bool value_in_range_of(T val)
4307{
4309}
4310
4311template<bool Value>
4312using bool_constant = std::integral_constant<bool, Value>;
4313
4315// is_c_string
4317
4318namespace impl
4319{
4320
4321template<typename T>
4322constexpr bool is_c_string()
4323{
4324 using TUnExt = typename std::remove_extent<T>::type;
4325 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4326 using TUnPtr = typename std::remove_pointer<T>::type;
4327 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4328 return
4329 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4330 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4331}
4332
4333} // namespace impl
4334
4335// checks whether T is a [cv] char */[cv] char[] C string
4336template<typename T>
4337struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4338
4339template<typename T>
4341
4343// is_transparent
4345
4346namespace impl
4347{
4348
4349template<typename T>
4350constexpr bool is_transparent()
4351{
4353}
4354
4355} // namespace impl
4356
4357// checks whether T has a member named is_transparent
4358template<typename T>
4359struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4360
4362
4363} // namespace detail
4365
4366// #include <nlohmann/detail/string_concat.hpp>
4367// __ _____ _____ _____
4368// __| | __| | | | JSON for Modern C++
4369// | | |__ | | | | | | version 3.12.0
4370// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4371//
4372// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4373// SPDX-License-Identifier: MIT
4374
4375
4376
4377#include <cstring> // strlen
4378#include <string> // string
4379#include <utility> // forward
4380
4381// #include <nlohmann/detail/meta/cpp_future.hpp>
4382
4383// #include <nlohmann/detail/meta/detected.hpp>
4384
4385
4387namespace detail
4388{
4389
4390inline std::size_t concat_length()
4391{
4392 return 0;
4393}
4394
4395template<typename... Args>
4396inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4397
4398template<typename StringType, typename... Args>
4399inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4400
4401template<typename... Args>
4402inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4403{
4404 return 1 + concat_length(rest...);
4405}
4406
4407template<typename... Args>
4408inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4409{
4410 // cppcheck-suppress ignoredReturnValue
4411 return ::strlen(cstr) + concat_length(rest...);
4412}
4413
4414template<typename StringType, typename... Args>
4415inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4416{
4417 return str.size() + concat_length(rest...);
4418}
4419
4420template<typename OutStringType>
4421inline void concat_into(OutStringType& /*out*/)
4422{}
4423
4424template<typename StringType, typename Arg>
4425using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4426
4427template<typename StringType, typename Arg>
4429
4430template<typename StringType, typename Arg>
4431using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4432
4433template<typename StringType, typename Arg>
4435
4436template<typename StringType, typename Arg>
4437using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4438
4439template<typename StringType, typename Arg>
4441
4442template<typename StringType, typename Arg>
4443using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4444
4445template<typename StringType, typename Arg>
4447
4448template < typename OutStringType, typename Arg, typename... Args,
4449 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4451inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4452
4453template < typename OutStringType, typename Arg, typename... Args,
4454 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4457inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4458
4459template < typename OutStringType, typename Arg, typename... Args,
4460 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4464inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4465
4466template<typename OutStringType, typename Arg, typename... Args,
4468inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4469{
4470 out.append(std::forward<Arg>(arg));
4471 concat_into(out, std::forward<Args>(rest)...);
4472}
4473
4474template < typename OutStringType, typename Arg, typename... Args,
4475 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4476 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4477inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4478{
4479 out += std::forward<Arg>(arg);
4480 concat_into(out, std::forward<Args>(rest)...);
4481}
4482
4483template < typename OutStringType, typename Arg, typename... Args,
4484 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4485 && !detect_string_can_append_op<OutStringType, Arg>::value
4486 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4487inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4488{
4489 out.append(arg.begin(), arg.end());
4490 concat_into(out, std::forward<Args>(rest)...);
4491}
4492
4493template < typename OutStringType, typename Arg, typename... Args,
4494 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4495 && !detect_string_can_append_op<OutStringType, Arg>::value
4496 && !detect_string_can_append_iter<OutStringType, Arg>::value
4497 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4498inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4499{
4500 out.append(arg.data(), arg.size());
4501 concat_into(out, std::forward<Args>(rest)...);
4502}
4503
4504template<typename OutStringType = std::string, typename... Args>
4505inline OutStringType concat(Args && ... args)
4506{
4507 OutStringType str;
4508 str.reserve(concat_length(args...));
4509 concat_into(str, std::forward<Args>(args)...);
4510 return str;
4511}
4512
4513} // namespace detail
4515
4516
4517// With -Wweak-vtables, Clang will complain about the exception classes as they
4518// have no out-of-line virtual method definitions and their vtable will be
4519// emitted in every translation unit. This issue cannot be fixed with a
4520// header-only library as there is no implementation file to move these
4521// functions to. As a result, we suppress this warning here to avoid client
4522// code stumbling over this. See https://github.com/nlohmann/json/issues/4087
4523// for a discussion.
4524#if defined(__clang__)
4525 #pragma clang diagnostic push
4526 #pragma clang diagnostic ignored "-Wweak-vtables"
4527#endif
4528
4530namespace detail
4531{
4532
4534// exceptions //
4536
4539class exception : public std::exception
4540{
4541 public:
4543 const char* what() const noexcept override
4544 {
4545 return m.what();
4546 }
4547
4549 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4550
4551 protected:
4553 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4554
4555 static std::string name(const std::string& ename, int id_)
4556 {
4557 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4558 }
4559
4560 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4561 {
4562 return "";
4563 }
4564
4565 template<typename BasicJsonType>
4566 static std::string diagnostics(const BasicJsonType* leaf_element)
4567 {
4568#if JSON_DIAGNOSTICS
4569 std::vector<std::string> tokens;
4570 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4571 {
4572 switch (current->m_parent->type())
4573 {
4574 case value_t::array:
4575 {
4576 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4577 {
4578 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4579 {
4580 tokens.emplace_back(std::to_string(i));
4581 break;
4582 }
4583 }
4584 break;
4585 }
4586
4587 case value_t::object:
4588 {
4589 for (const auto& element : *current->m_parent->m_data.m_value.object)
4590 {
4591 if (&element.second == current)
4592 {
4593 tokens.emplace_back(element.first.c_str());
4594 break;
4595 }
4596 }
4597 break;
4598 }
4599
4600 case value_t::null: // LCOV_EXCL_LINE
4601 case value_t::string: // LCOV_EXCL_LINE
4602 case value_t::boolean: // LCOV_EXCL_LINE
4603 case value_t::number_integer: // LCOV_EXCL_LINE
4604 case value_t::number_unsigned: // LCOV_EXCL_LINE
4605 case value_t::number_float: // LCOV_EXCL_LINE
4606 case value_t::binary: // LCOV_EXCL_LINE
4607 case value_t::discarded: // LCOV_EXCL_LINE
4608 default: // LCOV_EXCL_LINE
4609 break; // LCOV_EXCL_LINE
4610 }
4611 }
4612
4613 if (tokens.empty())
4614 {
4615 return "";
4616 }
4617
4618 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4619 [](const std::string & a, const std::string & b)
4620 {
4621 return concat(a, '/', detail::escape(b));
4622 });
4623
4624 return concat('(', str, ") ", get_byte_positions(leaf_element));
4625#else
4626 return get_byte_positions(leaf_element);
4627#endif
4628 }
4629
4630 private:
4632 std::runtime_error m;
4633#if JSON_DIAGNOSTIC_POSITIONS
4634 template<typename BasicJsonType>
4635 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4636 {
4637 if ((leaf_element->start_pos() != std::string::npos) && (leaf_element->end_pos() != std::string::npos))
4638 {
4639 return concat("(bytes ", std::to_string(leaf_element->start_pos()), "-", std::to_string(leaf_element->end_pos()), ") ");
4640 }
4641 return "";
4642 }
4643#else
4644 template<typename BasicJsonType>
4645 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4646 {
4647 static_cast<void>(leaf_element);
4648 return "";
4649 }
4650#endif
4651};
4652
4656{
4657 public:
4667 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4668 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4669 {
4670 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4671 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4672 return {id_, pos.chars_read_total, w.c_str()};
4673 }
4674
4675 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4676 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4677 {
4678 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4679 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4680 ": ", exception::diagnostics(context), what_arg);
4681 return {id_, byte_, w.c_str()};
4682 }
4683
4693 const std::size_t byte;
4694
4695 private:
4696 parse_error(int id_, std::size_t byte_, const char* what_arg)
4697 : exception(id_, what_arg), byte(byte_) {}
4698
4699 static std::string position_string(const position_t& pos)
4700 {
4701 return concat(" at line ", std::to_string(pos.lines_read + 1),
4702 ", column ", std::to_string(pos.chars_read_current_line));
4703 }
4704};
4705
4709{
4710 public:
4711 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4712 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4713 {
4714 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4715 return {id_, w.c_str()};
4716 }
4717
4718 private:
4720 invalid_iterator(int id_, const char* what_arg)
4721 : exception(id_, what_arg) {}
4722};
4723
4726class type_error : public exception
4727{
4728 public:
4729 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4730 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4731 {
4732 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4733 return {id_, w.c_str()};
4734 }
4735
4736 private:
4738 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4739};
4740
4744{
4745 public:
4746 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4747 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4748 {
4749 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4750 return {id_, w.c_str()};
4751 }
4752
4753 private:
4755 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4756};
4757
4761{
4762 public:
4763 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4764 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4765 {
4766 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4767 return {id_, w.c_str()};
4768 }
4769
4770 private:
4772 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4773};
4774
4775} // namespace detail
4777
4778#if defined(__clang__)
4779 #pragma clang diagnostic pop
4780#endif
4781
4782// #include <nlohmann/detail/macro_scope.hpp>
4783
4784// #include <nlohmann/detail/meta/cpp_future.hpp>
4785
4786// #include <nlohmann/detail/meta/identity_tag.hpp>
4787// __ _____ _____ _____
4788// __| | __| | | | JSON for Modern C++
4789// | | |__ | | | | | | version 3.12.0
4790// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4791//
4792// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4793// SPDX-License-Identifier: MIT
4794
4795
4796
4797// #include <nlohmann/detail/abi_macros.hpp>
4798
4799
4801namespace detail
4802{
4803
4804// dispatching helper struct
4805template <class T> struct identity_tag {};
4806
4807} // namespace detail
4809
4810// #include <nlohmann/detail/meta/std_fs.hpp>
4811// __ _____ _____ _____
4812// __| | __| | | | JSON for Modern C++
4813// | | |__ | | | | | | version 3.12.0
4814// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4815//
4816// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4817// SPDX-License-Identifier: MIT
4818
4819
4820
4821// #include <nlohmann/detail/macro_scope.hpp>
4822
4823
4824#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4825#include <experimental/filesystem>
4827namespace detail
4828{
4829namespace std_fs = std::experimental::filesystem;
4830} // namespace detail
4832#elif JSON_HAS_FILESYSTEM
4833#include <filesystem> // NOLINT(build/c++17)
4835namespace detail
4836{
4837namespace std_fs = std::filesystem;
4838} // namespace detail
4840#endif
4841
4842// #include <nlohmann/detail/meta/type_traits.hpp>
4843
4844// #include <nlohmann/detail/string_concat.hpp>
4845
4846// #include <nlohmann/detail/value_t.hpp>
4847
4848
4849// include after macro_scope.hpp
4850#ifdef JSON_HAS_CPP_17
4851 #include <optional> // optional
4852#endif
4853
4854#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4855 #include <string_view> // u8string_view
4856#endif
4857
4859namespace detail
4860{
4861
4862template<typename BasicJsonType>
4863inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4864{
4865 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4866 {
4867 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4868 }
4869 n = nullptr;
4870}
4871
4872#ifdef JSON_HAS_CPP_17
4873template<typename BasicJsonType, typename T>
4874void from_json(const BasicJsonType& j, std::optional<T>& opt)
4875{
4876 if (j.is_null())
4877 {
4878 opt = std::nullopt;
4879 }
4880 else
4881 {
4882 opt.emplace(j.template get<T>());
4883 }
4884}
4885#endif // JSON_HAS_CPP_17
4886
4887// overloads for basic_json template parameters
4888template < typename BasicJsonType, typename ArithmeticType,
4889 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4890 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4891 int > = 0 >
4892void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4893{
4894 switch (static_cast<value_t>(j))
4895 {
4897 {
4898 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4899 break;
4900 }
4902 {
4903 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4904 break;
4905 }
4907 {
4908 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4909 break;
4910 }
4911
4912 case value_t::null:
4913 case value_t::object:
4914 case value_t::array:
4915 case value_t::string:
4916 case value_t::boolean:
4917 case value_t::binary:
4918 case value_t::discarded:
4919 default:
4920 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4921 }
4922}
4923
4924template<typename BasicJsonType>
4925inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4926{
4927 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4928 {
4929 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4930 }
4931 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4932}
4933
4934template<typename BasicJsonType>
4935inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4936{
4937 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4938 {
4939 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4940 }
4941 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4942}
4943
4944template <
4945 typename BasicJsonType, typename StringType,
4946 enable_if_t <
4947 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4948 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4949 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4950 && !is_json_ref<StringType>::value, int > = 0 >
4951inline void from_json(const BasicJsonType& j, StringType& s)
4952{
4953 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4954 {
4955 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4956 }
4957
4958 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4959}
4960
4961template<typename BasicJsonType>
4962inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4963{
4964 get_arithmetic_value(j, val);
4965}
4966
4967template<typename BasicJsonType>
4968inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4969{
4970 get_arithmetic_value(j, val);
4971}
4972
4973template<typename BasicJsonType>
4974inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4975{
4976 get_arithmetic_value(j, val);
4977}
4978
4979#if !JSON_DISABLE_ENUM_SERIALIZATION
4980template<typename BasicJsonType, typename EnumType,
4981 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4982inline void from_json(const BasicJsonType& j, EnumType& e)
4983{
4984 typename std::underlying_type<EnumType>::type val;
4985 get_arithmetic_value(j, val);
4986 e = static_cast<EnumType>(val);
4987}
4988#endif // JSON_DISABLE_ENUM_SERIALIZATION
4989
4990// forward_list doesn't have an insert method
4991template<typename BasicJsonType, typename T, typename Allocator,
4992 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4993inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4994{
4995 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4996 {
4997 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4998 }
4999 l.clear();
5000 std::transform(j.rbegin(), j.rend(),
5001 std::front_inserter(l), [](const BasicJsonType & i)
5002 {
5003 return i.template get<T>();
5004 });
5005}
5006
5007// valarray doesn't have an insert method
5008template<typename BasicJsonType, typename T,
5009 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
5010inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
5011{
5012 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5013 {
5014 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5015 }
5016 l.resize(j.size());
5017 std::transform(j.begin(), j.end(), std::begin(l),
5018 [](const BasicJsonType & elem)
5019 {
5020 return elem.template get<T>();
5021 });
5022}
5023
5024template<typename BasicJsonType, typename T, std::size_t N>
5025auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5026-> decltype(j.template get<T>(), void())
5027{
5028 for (std::size_t i = 0; i < N; ++i)
5029 {
5030 arr[i] = j.at(i).template get<T>();
5031 }
5032}
5033
5034template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2>
5035auto from_json(const BasicJsonType& j, T (&arr)[N1][N2]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5036-> decltype(j.template get<T>(), void())
5037{
5038 for (std::size_t i1 = 0; i1 < N1; ++i1)
5039 {
5040 for (std::size_t i2 = 0; i2 < N2; ++i2)
5041 {
5042 arr[i1][i2] = j.at(i1).at(i2).template get<T>();
5043 }
5044 }
5045}
5046
5047template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3>
5048auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5049-> decltype(j.template get<T>(), void())
5050{
5051 for (std::size_t i1 = 0; i1 < N1; ++i1)
5052 {
5053 for (std::size_t i2 = 0; i2 < N2; ++i2)
5054 {
5055 for (std::size_t i3 = 0; i3 < N3; ++i3)
5056 {
5057 arr[i1][i2][i3] = j.at(i1).at(i2).at(i3).template get<T>();
5058 }
5059 }
5060 }
5061}
5062
5063template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3, std::size_t N4>
5064auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3][N4]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5065-> decltype(j.template get<T>(), void())
5066{
5067 for (std::size_t i1 = 0; i1 < N1; ++i1)
5068 {
5069 for (std::size_t i2 = 0; i2 < N2; ++i2)
5070 {
5071 for (std::size_t i3 = 0; i3 < N3; ++i3)
5072 {
5073 for (std::size_t i4 = 0; i4 < N4; ++i4)
5074 {
5075 arr[i1][i2][i3][i4] = j.at(i1).at(i2).at(i3).at(i4).template get<T>();
5076 }
5077 }
5078 }
5079 }
5080}
5081
5082template<typename BasicJsonType>
5083inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
5084{
5085 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
5086}
5087
5088template<typename BasicJsonType, typename T, std::size_t N>
5089auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
5090 priority_tag<2> /*unused*/)
5091-> decltype(j.template get<T>(), void())
5092{
5093 for (std::size_t i = 0; i < N; ++i)
5094 {
5095 arr[i] = j.at(i).template get<T>();
5096 }
5097}
5098
5099template<typename BasicJsonType, typename ConstructibleArrayType,
5101 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5102 int> = 0>
5103auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
5104-> decltype(
5105 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
5107 void())
5108{
5109 using std::end;
5110
5111 ConstructibleArrayType ret;
5112 ret.reserve(j.size());
5113 std::transform(j.begin(), j.end(),
5114 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
5115 {
5116 // get<BasicJsonType>() returns *this, this won't call a from_json
5117 // method when value_type is BasicJsonType
5119 });
5120 arr = std::move(ret);
5121}
5122
5123template<typename BasicJsonType, typename ConstructibleArrayType,
5125 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5126 int> = 0>
5127inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
5128 priority_tag<0> /*unused*/)
5129{
5130 using std::end;
5131
5132 ConstructibleArrayType ret;
5133 std::transform(
5134 j.begin(), j.end(), std::inserter(ret, end(ret)),
5135 [](const BasicJsonType & i)
5136 {
5137 // get<BasicJsonType>() returns *this, this won't call a from_json
5138 // method when value_type is BasicJsonType
5140 });
5141 arr = std::move(ret);
5142}
5143
5144template < typename BasicJsonType, typename ConstructibleArrayType,
5145 enable_if_t <
5146 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
5147 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
5149 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
5150 !is_basic_json<ConstructibleArrayType>::value,
5151 int > = 0 >
5152auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
5153-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
5155void())
5156{
5157 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5158 {
5159 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5160 }
5161
5162 from_json_array_impl(j, arr, priority_tag<3> {});
5163}
5164
5165template < typename BasicJsonType, typename T, std::size_t... Idx >
5166std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
5167 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
5168{
5169 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
5170}
5171
5172template < typename BasicJsonType, typename T, std::size_t N >
5173auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
5174-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
5175{
5176 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5177 {
5178 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5179 }
5180
5181 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
5182}
5183
5184template<typename BasicJsonType>
5185inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
5186{
5187 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
5188 {
5189 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
5190 }
5191
5192 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
5193}
5194
5195template<typename BasicJsonType, typename ConstructibleObjectType,
5196 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
5197inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
5198{
5199 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
5200 {
5201 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
5202 }
5203
5204 ConstructibleObjectType ret;
5205 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
5206 using value_type = typename ConstructibleObjectType::value_type;
5207 std::transform(
5208 inner_object->begin(), inner_object->end(),
5209 std::inserter(ret, ret.begin()),
5210 [](typename BasicJsonType::object_t::value_type const & p)
5211 {
5212 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
5213 });
5214 obj = std::move(ret);
5215}
5216
5217// overload for arithmetic types, not chosen for basic_json template arguments
5218// (BooleanType, etc.); note: Is it really necessary to provide explicit
5219// overloads for boolean_t etc. in case of a custom BooleanType which is not
5220// an arithmetic type?
5221template < typename BasicJsonType, typename ArithmeticType,
5222 enable_if_t <
5223 std::is_arithmetic<ArithmeticType>::value&&
5224 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
5225 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
5226 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
5227 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
5228 int > = 0 >
5229inline void from_json(const BasicJsonType& j, ArithmeticType& val)
5230{
5231 switch (static_cast<value_t>(j))
5232 {
5234 {
5235 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
5236 break;
5237 }
5239 {
5240 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5241 break;
5242 }
5244 {
5245 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5246 break;
5247 }
5248 case value_t::boolean:
5249 {
5250 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5251 break;
5252 }
5253
5254 case value_t::null:
5255 case value_t::object:
5256 case value_t::array:
5257 case value_t::string:
5258 case value_t::binary:
5259 case value_t::discarded:
5260 default:
5261 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5262 }
5263}
5264
5265template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5266std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5267{
5268 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5269}
5270
5271template<typename BasicJsonType>
5272std::tuple<> from_json_tuple_impl_base(BasicJsonType& /*unused*/, index_sequence<> /*unused*/)
5273{
5274 return {};
5275}
5276
5277template < typename BasicJsonType, class A1, class A2 >
5278std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5279{
5280 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5281 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5282}
5283
5284template<typename BasicJsonType, typename A1, typename A2>
5285inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5286{
5287 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5288}
5289
5290template<typename BasicJsonType, typename... Args>
5291std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5292{
5293 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5294}
5295
5296template<typename BasicJsonType, typename... Args>
5297inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5298{
5299 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5300}
5301
5302template<typename BasicJsonType, typename TupleRelated>
5303auto from_json(BasicJsonType&& j, TupleRelated&& t)
5304-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5305{
5306 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5307 {
5308 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5309 }
5310
5311 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5312}
5313
5314template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5315 typename = enable_if_t < !std::is_constructible <
5316 typename BasicJsonType::string_t, Key >::value >>
5317inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5318{
5319 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5320 {
5321 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5322 }
5323 m.clear();
5324 for (const auto& p : j)
5325 {
5326 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5327 {
5328 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5329 }
5330 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5331 }
5332}
5333
5334template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5335 typename = enable_if_t < !std::is_constructible <
5336 typename BasicJsonType::string_t, Key >::value >>
5337inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5338{
5339 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5340 {
5341 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5342 }
5343 m.clear();
5344 for (const auto& p : j)
5345 {
5346 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5347 {
5348 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5349 }
5350 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5351 }
5352}
5353
5354#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5355template<typename BasicJsonType>
5356inline void from_json(const BasicJsonType& j, std_fs::path& p)
5357{
5358 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5359 {
5360 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5361 }
5362 const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5363 // Checking for C++20 standard or later can be insufficient in case the
5364 // library support for char8_t is either incomplete or was disabled
5365 // altogether. Use the __cpp_lib_char8_t feature test instead.
5366#if defined(__cpp_lib_char8_t) && (__cpp_lib_char8_t >= 201907L)
5367 p = std_fs::path(std::u8string_view(reinterpret_cast<const char8_t*>(s.data()), s.size()));
5368#else
5369 p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20
5370#endif
5371}
5372#endif
5373
5375{
5376 template<typename BasicJsonType, typename T>
5377 auto operator()(const BasicJsonType& j, T&& val) const
5378 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5379 -> decltype(from_json(j, std::forward<T>(val)))
5380 {
5381 return from_json(j, std::forward<T>(val));
5382 }
5383};
5384
5385} // namespace detail
5386
5387#ifndef JSON_HAS_CPP_17
5391namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5392{
5393#endif
5394JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5396#ifndef JSON_HAS_CPP_17
5397} // namespace
5398#endif
5399
5401
5402// #include <nlohmann/detail/conversions/to_json.hpp>
5403// __ _____ _____ _____
5404// __| | __| | | | JSON for Modern C++
5405// | | |__ | | | | | | version 3.12.0
5406// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5407//
5408// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5409// SPDX-License-Identifier: MIT
5410
5411
5412
5413// #include <nlohmann/detail/macro_scope.hpp>
5414// JSON_HAS_CPP_17
5415#ifdef JSON_HAS_CPP_17
5416 #include <optional> // optional
5417#endif
5418
5419#include <algorithm> // copy
5420#include <iterator> // begin, end
5421#include <memory> // allocator_traits
5422#include <string> // basic_string, char_traits
5423#include <tuple> // tuple, get
5424#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5425#include <utility> // move, forward, declval, pair
5426#include <valarray> // valarray
5427#include <vector> // vector
5428
5429// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5430// __ _____ _____ _____
5431// __| | __| | | | JSON for Modern C++
5432// | | |__ | | | | | | version 3.12.0
5433// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5434//
5435// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5436// SPDX-License-Identifier: MIT
5437
5438
5439
5440#include <cstddef> // size_t
5441#include <iterator> // forward_iterator_tag
5442#include <tuple> // tuple_size, get, tuple_element
5443#include <utility> // move
5444
5445#if JSON_HAS_RANGES
5446 #include <ranges> // enable_borrowed_range
5447#endif
5448
5449// #include <nlohmann/detail/abi_macros.hpp>
5450
5451// #include <nlohmann/detail/meta/type_traits.hpp>
5452
5453// #include <nlohmann/detail/string_utils.hpp>
5454// __ _____ _____ _____
5455// __| | __| | | | JSON for Modern C++
5456// | | |__ | | | | | | version 3.12.0
5457// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5458//
5459// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5460// SPDX-License-Identifier: MIT
5461
5462
5463
5464#include <cstddef> // size_t
5465#include <string> // string, to_string
5466
5467// #include <nlohmann/detail/abi_macros.hpp>
5468
5469
5471namespace detail
5472{
5473
5474template<typename StringType>
5475void int_to_string(StringType& target, std::size_t value)
5476{
5477 // For ADL
5478 using std::to_string;
5479 target = to_string(value);
5480}
5481
5482template<typename StringType>
5483StringType to_string(std::size_t value)
5484{
5485 StringType result;
5486 int_to_string(result, value);
5487 return result;
5488}
5489
5490} // namespace detail
5492
5493// #include <nlohmann/detail/value_t.hpp>
5494
5495
5497namespace detail
5498{
5499
5500template<typename IteratorType> class iteration_proxy_value
5501{
5502 public:
5503 using difference_type = std::ptrdiff_t;
5507 using iterator_category = std::forward_iterator_tag;
5508 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5509
5510 private:
5512 IteratorType anchor{};
5514 std::size_t array_index = 0;
5516 mutable std::size_t array_index_last = 0;
5518 mutable string_type array_index_str = "0";
5520 string_type empty_str{};
5521
5522 public:
5523 explicit iteration_proxy_value() = default;
5524 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5525 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5526 && std::is_nothrow_default_constructible<string_type>::value)
5527 : anchor(std::move(it))
5528 , array_index(array_index_)
5529 {}
5530
5533 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5535 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5536 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5538 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5539 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5541
5543 const iteration_proxy_value& operator*() const
5544 {
5545 return *this;
5546 }
5547
5550 {
5551 ++anchor;
5552 ++array_index;
5553
5554 return *this;
5555 }
5556
5557 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5558 {
5559 auto tmp = iteration_proxy_value(anchor, array_index);
5560 ++anchor;
5561 ++array_index;
5562 return tmp;
5563 }
5564
5567 {
5568 return anchor == o.anchor;
5569 }
5570
5573 {
5574 return anchor != o.anchor;
5575 }
5576
5578 const string_type& key() const
5579 {
5580 JSON_ASSERT(anchor.m_object != nullptr);
5581
5582 switch (anchor.m_object->type())
5583 {
5584 // use integer array index as key
5585 case value_t::array:
5586 {
5587 if (array_index != array_index_last)
5588 {
5589 int_to_string( array_index_str, array_index );
5590 array_index_last = array_index;
5591 }
5592 return array_index_str;
5593 }
5594
5595 // use key from the object
5596 case value_t::object:
5597 return anchor.key();
5598
5599 // use an empty key for all primitive types
5600 case value_t::null:
5601 case value_t::string:
5602 case value_t::boolean:
5606 case value_t::binary:
5607 case value_t::discarded:
5608 default:
5609 return empty_str;
5610 }
5611 }
5612
5614 typename IteratorType::reference value() const
5615 {
5616 return anchor.value();
5617 }
5618};
5619
5621template<typename IteratorType> class iteration_proxy
5622{
5623 private:
5625 typename IteratorType::pointer container = nullptr;
5626
5627 public:
5628 explicit iteration_proxy() = default;
5629
5631 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5632 : container(&cont) {}
5633
5636 iteration_proxy(iteration_proxy&&) noexcept = default;
5637 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5638 ~iteration_proxy() = default;
5639
5641 iteration_proxy_value<IteratorType> begin() const noexcept
5642 {
5643 return iteration_proxy_value<IteratorType>(container->begin());
5644 }
5645
5648 {
5649 return iteration_proxy_value<IteratorType>(container->end());
5650 }
5651};
5652
5653// Structured Bindings Support
5654// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5655// And see https://github.com/nlohmann/json/pull/1391
5656template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5657auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5658{
5659 return i.key();
5660}
5661// Structured Bindings Support
5662// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5663// And see https://github.com/nlohmann/json/pull/1391
5664template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5665auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5666{
5667 return i.value();
5668}
5669
5670} // namespace detail
5672
5673// The Addition to the STD Namespace is required to add
5674// Structured Bindings Support to the iteration_proxy_value class
5675// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5676// And see https://github.com/nlohmann/json/pull/1391
5677namespace std
5678{
5679
5680#if defined(__clang__)
5681 // Fix: https://github.com/nlohmann/json/issues/1401
5682 #pragma clang diagnostic push
5683 #pragma clang diagnostic ignored "-Wmismatched-tags"
5684#endif
5685template<typename IteratorType>
5686class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5687 : public std::integral_constant<std::size_t, 2> {};
5688
5689template<std::size_t N, typename IteratorType>
5690class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5691{
5692 public:
5693 using type = decltype(
5694 get<N>(std::declval <
5695 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5696};
5697#if defined(__clang__)
5698 #pragma clang diagnostic pop
5699#endif
5700
5701} // namespace std
5702
5703#if JSON_HAS_RANGES
5704 template <typename IteratorType>
5705 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5706#endif
5707
5708// #include <nlohmann/detail/meta/cpp_future.hpp>
5709
5710// #include <nlohmann/detail/meta/std_fs.hpp>
5711
5712// #include <nlohmann/detail/meta/type_traits.hpp>
5713
5714// #include <nlohmann/detail/value_t.hpp>
5715
5716
5718namespace detail
5719{
5720
5722// constructors //
5724
5725/*
5726 * Note all external_constructor<>::construct functions need to call
5727 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5728 * allocated value (e.g., a string). See bug issue
5729 * https://github.com/nlohmann/json/issues/2865 for more information.
5730 */
5731
5732template<value_t> struct external_constructor;
5733
5734template<>
5736{
5737 template<typename BasicJsonType>
5738 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5739 {
5740 j.m_data.m_value.destroy(j.m_data.m_type);
5741 j.m_data.m_type = value_t::boolean;
5742 j.m_data.m_value = b;
5743 j.assert_invariant();
5744 }
5745};
5746
5747template<>
5749{
5750 template<typename BasicJsonType>
5751 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5752 {
5753 j.m_data.m_value.destroy(j.m_data.m_type);
5754 j.m_data.m_type = value_t::string;
5755 j.m_data.m_value = s;
5756 j.assert_invariant();
5757 }
5758
5759 template<typename BasicJsonType>
5760 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5761 {
5762 j.m_data.m_value.destroy(j.m_data.m_type);
5763 j.m_data.m_type = value_t::string;
5764 j.m_data.m_value = std::move(s);
5765 j.assert_invariant();
5766 }
5767
5768 template < typename BasicJsonType, typename CompatibleStringType,
5769 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5770 int > = 0 >
5771 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5772 {
5773 j.m_data.m_value.destroy(j.m_data.m_type);
5774 j.m_data.m_type = value_t::string;
5775 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5776 j.assert_invariant();
5777 }
5778};
5779
5780template<>
5782{
5783 template<typename BasicJsonType>
5784 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5785 {
5786 j.m_data.m_value.destroy(j.m_data.m_type);
5787 j.m_data.m_type = value_t::binary;
5788 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5789 j.assert_invariant();
5790 }
5791
5792 template<typename BasicJsonType>
5793 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5794 {
5795 j.m_data.m_value.destroy(j.m_data.m_type);
5796 j.m_data.m_type = value_t::binary;
5797 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5798 j.assert_invariant();
5799 }
5800};
5801
5802template<>
5804{
5805 template<typename BasicJsonType>
5806 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5807 {
5808 j.m_data.m_value.destroy(j.m_data.m_type);
5809 j.m_data.m_type = value_t::number_float;
5810 j.m_data.m_value = val;
5811 j.assert_invariant();
5812 }
5813};
5814
5815template<>
5817{
5818 template<typename BasicJsonType>
5819 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5820 {
5821 j.m_data.m_value.destroy(j.m_data.m_type);
5822 j.m_data.m_type = value_t::number_unsigned;
5823 j.m_data.m_value = val;
5824 j.assert_invariant();
5825 }
5826};
5827
5828template<>
5830{
5831 template<typename BasicJsonType>
5832 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5833 {
5834 j.m_data.m_value.destroy(j.m_data.m_type);
5835 j.m_data.m_type = value_t::number_integer;
5836 j.m_data.m_value = val;
5837 j.assert_invariant();
5838 }
5839};
5840
5841template<>
5843{
5844 template<typename BasicJsonType>
5845 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5846 {
5847 j.m_data.m_value.destroy(j.m_data.m_type);
5848 j.m_data.m_type = value_t::array;
5849 j.m_data.m_value = arr;
5850 j.set_parents();
5851 j.assert_invariant();
5852 }
5853
5854 template<typename BasicJsonType>
5855 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5856 {
5857 j.m_data.m_value.destroy(j.m_data.m_type);
5858 j.m_data.m_type = value_t::array;
5859 j.m_data.m_value = std::move(arr);
5860 j.set_parents();
5861 j.assert_invariant();
5862 }
5863
5864 template < typename BasicJsonType, typename CompatibleArrayType,
5865 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5866 int > = 0 >
5867 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5868 {
5869 using std::begin;
5870 using std::end;
5871
5872 j.m_data.m_value.destroy(j.m_data.m_type);
5873 j.m_data.m_type = value_t::array;
5874 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5875 j.set_parents();
5876 j.assert_invariant();
5877 }
5878
5879 template<typename BasicJsonType>
5880 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5881 {
5882 j.m_data.m_value.destroy(j.m_data.m_type);
5883 j.m_data.m_type = value_t::array;
5884 j.m_data.m_value = value_t::array;
5885 j.m_data.m_value.array->reserve(arr.size());
5886 for (const bool x : arr)
5887 {
5888 j.m_data.m_value.array->push_back(x);
5889 j.set_parent(j.m_data.m_value.array->back());
5890 }
5891 j.assert_invariant();
5892 }
5893
5894 template<typename BasicJsonType, typename T,
5896 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5897 {
5898 j.m_data.m_value.destroy(j.m_data.m_type);
5899 j.m_data.m_type = value_t::array;
5900 j.m_data.m_value = value_t::array;
5901 j.m_data.m_value.array->resize(arr.size());
5902 if (arr.size() > 0)
5903 {
5904 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5905 }
5906 j.set_parents();
5907 j.assert_invariant();
5908 }
5909};
5910
5911template<>
5913{
5914 template<typename BasicJsonType>
5915 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5916 {
5917 j.m_data.m_value.destroy(j.m_data.m_type);
5918 j.m_data.m_type = value_t::object;
5919 j.m_data.m_value = obj;
5920 j.set_parents();
5921 j.assert_invariant();
5922 }
5923
5924 template<typename BasicJsonType>
5925 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5926 {
5927 j.m_data.m_value.destroy(j.m_data.m_type);
5928 j.m_data.m_type = value_t::object;
5929 j.m_data.m_value = std::move(obj);
5930 j.set_parents();
5931 j.assert_invariant();
5932 }
5933
5934 template < typename BasicJsonType, typename CompatibleObjectType,
5935 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5936 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5937 {
5938 using std::begin;
5939 using std::end;
5940
5941 j.m_data.m_value.destroy(j.m_data.m_type);
5942 j.m_data.m_type = value_t::object;
5943 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5944 j.set_parents();
5945 j.assert_invariant();
5946 }
5947};
5948
5950// to_json //
5952
5953#ifdef JSON_HAS_CPP_17
5954template<typename BasicJsonType, typename T,
5955 enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
5956void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept
5957{
5958 if (opt.has_value())
5959 {
5960 j = *opt;
5961 }
5962 else
5963 {
5964 j = nullptr;
5965 }
5966}
5967#endif
5968
5969template<typename BasicJsonType, typename T,
5970 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5971inline void to_json(BasicJsonType& j, T b) noexcept
5972{
5974}
5975
5976template < typename BasicJsonType, typename BoolRef,
5977 enable_if_t <
5978 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5979 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5980 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5981 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5982 typename BasicJsonType::boolean_t >::value))
5983 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5984inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5985{
5986 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5987}
5988
5989template<typename BasicJsonType, typename CompatibleString,
5990 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5991inline void to_json(BasicJsonType& j, const CompatibleString& s)
5992{
5994}
5995
5996template<typename BasicJsonType>
5997inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5998{
6000}
6001
6002template<typename BasicJsonType, typename FloatType,
6003 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
6004inline void to_json(BasicJsonType& j, FloatType val) noexcept
6005{
6006 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
6007}
6008
6009template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
6010 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
6011inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
6012{
6013 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
6014}
6015
6016template<typename BasicJsonType, typename CompatibleNumberIntegerType,
6017 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
6018inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
6019{
6020 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
6021}
6022
6023#if !JSON_DISABLE_ENUM_SERIALIZATION
6024template<typename BasicJsonType, typename EnumType,
6025 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
6026inline void to_json(BasicJsonType& j, EnumType e) noexcept
6027{
6028 using underlying_type = typename std::underlying_type<EnumType>::type;
6029 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
6030 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
6031}
6032#endif // JSON_DISABLE_ENUM_SERIALIZATION
6033
6034template<typename BasicJsonType>
6035inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
6036{
6038}
6039
6040template < typename BasicJsonType, typename CompatibleArrayType,
6041 enable_if_t < is_compatible_array_type<BasicJsonType,
6042 CompatibleArrayType>::value&&
6043 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
6045 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
6046 !is_basic_json<CompatibleArrayType>::value,
6047 int > = 0 >
6048inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
6049{
6051}
6052
6053template<typename BasicJsonType>
6054inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
6055{
6057}
6058
6059template<typename BasicJsonType, typename T,
6060 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
6061inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
6062{
6064}
6065
6066template<typename BasicJsonType>
6067inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
6068{
6070}
6071
6072template < typename BasicJsonType, typename CompatibleObjectType,
6073 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
6074inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
6075{
6077}
6078
6079template<typename BasicJsonType>
6080inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
6081{
6083}
6084
6085template <
6086 typename BasicJsonType, typename T, std::size_t N,
6087 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
6088 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6089 int > = 0 >
6090inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6091{
6093}
6094
6095template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
6096inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
6097{
6098 j = { p.first, p.second };
6099}
6100
6101// for https://github.com/nlohmann/json/pull/1134
6102template<typename BasicJsonType, typename T,
6104inline void to_json(BasicJsonType& j, const T& b)
6105{
6106 j = { {b.key(), b.value()} };
6107}
6108
6109template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
6110inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
6111{
6112 j = { std::get<Idx>(t)... };
6113}
6114
6115template<typename BasicJsonType, typename Tuple>
6116inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& /*unused*/, index_sequence<> /*unused*/)
6117{
6118 using array_t = typename BasicJsonType::array_t;
6119 j = array_t();
6120}
6121
6122template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
6123inline void to_json(BasicJsonType& j, const T& t)
6124{
6125 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
6126}
6127
6128#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
6129#if defined(__cpp_lib_char8_t)
6130template<typename BasicJsonType, typename Tr, typename Allocator>
6131inline void to_json(BasicJsonType& j, const std::basic_string<char8_t, Tr, Allocator>& s)
6132{
6133 using OtherAllocator = typename std::allocator_traits<Allocator>::template rebind_alloc<char>;
6134 j = std::basic_string<char, std::char_traits<char>, OtherAllocator>(s.begin(), s.end(), s.get_allocator());
6135}
6136#endif
6137
6138template<typename BasicJsonType>
6139inline void to_json(BasicJsonType& j, const std_fs::path& p)
6140{
6141 // Returns either a std::string or a std::u8string depending whether library
6142 // support for char8_t is enabled.
6143 j = p.u8string();
6144}
6145#endif
6146
6148{
6149 template<typename BasicJsonType, typename T>
6150 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
6151 -> decltype(to_json(j, std::forward<T>(val)), void())
6152 {
6153 return to_json(j, std::forward<T>(val));
6154 }
6155};
6156} // namespace detail
6157
6158#ifndef JSON_HAS_CPP_17
6162namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
6163{
6164#endif
6165JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
6167#ifndef JSON_HAS_CPP_17
6168} // namespace
6169#endif
6170
6172
6173// #include <nlohmann/detail/meta/identity_tag.hpp>
6174
6175
6177
6179template<typename ValueType, typename>
6181{
6184 template<typename BasicJsonType, typename TargetType = ValueType>
6185 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
6186 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
6187 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
6188 {
6189 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
6190 }
6191
6194 template<typename BasicJsonType, typename TargetType = ValueType>
6195 static auto from_json(BasicJsonType && j) noexcept(
6196 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
6197 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
6198 {
6199 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
6200 }
6201
6204 template<typename BasicJsonType, typename TargetType = ValueType>
6205 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
6206 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
6207 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
6208 {
6209 ::nlohmann::to_json(j, std::forward<TargetType>(val));
6210 }
6211};
6212
6214
6215// #include <nlohmann/byte_container_with_subtype.hpp>
6216// __ _____ _____ _____
6217// __| | __| | | | JSON for Modern C++
6218// | | |__ | | | | | | version 3.12.0
6219// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6220//
6221// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6222// SPDX-License-Identifier: MIT
6223
6224
6225
6226#include <cstdint> // uint8_t, uint64_t
6227#include <tuple> // tie
6228#include <utility> // move
6229
6230// #include <nlohmann/detail/abi_macros.hpp>
6231
6232
6234
6237template<typename BinaryType>
6238class byte_container_with_subtype : public BinaryType
6239{
6240 public:
6241 using container_type = BinaryType;
6242 using subtype_type = std::uint64_t;
6243
6246 : container_type()
6247 {}
6248
6251 : container_type(b)
6252 {}
6253
6255 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
6256 : container_type(std::move(b))
6257 {}
6258
6261 : container_type(b)
6262 , m_subtype(subtype_)
6263 , m_has_subtype(true)
6264 {}
6265
6267 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
6268 : container_type(std::move(b))
6269 , m_subtype(subtype_)
6270 , m_has_subtype(true)
6271 {}
6272
6274 {
6275 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
6276 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
6277 }
6278
6280 {
6281 return !(rhs == *this);
6282 }
6283
6286 void set_subtype(subtype_type subtype_) noexcept
6287 {
6288 m_subtype = subtype_;
6289 m_has_subtype = true;
6290 }
6291
6294 constexpr subtype_type subtype() const noexcept
6295 {
6296 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
6297 }
6298
6301 constexpr bool has_subtype() const noexcept
6302 {
6303 return m_has_subtype;
6304 }
6305
6308 void clear_subtype() noexcept
6309 {
6310 m_subtype = 0;
6311 m_has_subtype = false;
6312 }
6313
6314 private:
6315 subtype_type m_subtype = 0;
6316 bool m_has_subtype = false;
6317};
6318
6320
6321// #include <nlohmann/detail/conversions/from_json.hpp>
6322
6323// #include <nlohmann/detail/conversions/to_json.hpp>
6324
6325// #include <nlohmann/detail/exceptions.hpp>
6326
6327// #include <nlohmann/detail/hash.hpp>
6328// __ _____ _____ _____
6329// __| | __| | | | JSON for Modern C++
6330// | | |__ | | | | | | version 3.12.0
6331// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6332//
6333// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6334// SPDX-License-Identifier: MIT
6335
6336
6337
6338#include <cstdint> // uint8_t
6339#include <cstddef> // size_t
6340#include <functional> // hash
6341
6342// #include <nlohmann/detail/abi_macros.hpp>
6343
6344// #include <nlohmann/detail/value_t.hpp>
6345
6346
6348namespace detail
6349{
6350
6351// boost::hash_combine
6352inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6353{
6354 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6355 return seed;
6356}
6357
6369template<typename BasicJsonType>
6370std::size_t hash(const BasicJsonType& j)
6371{
6372 using string_t = typename BasicJsonType::string_t;
6373 using number_integer_t = typename BasicJsonType::number_integer_t;
6374 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6375 using number_float_t = typename BasicJsonType::number_float_t;
6376
6377 const auto type = static_cast<std::size_t>(j.type());
6378 switch (j.type())
6379 {
6380 case BasicJsonType::value_t::null:
6381 case BasicJsonType::value_t::discarded:
6382 {
6383 return combine(type, 0);
6384 }
6385
6386 case BasicJsonType::value_t::object:
6387 {
6388 auto seed = combine(type, j.size());
6389 for (const auto& element : j.items())
6390 {
6391 const auto h = std::hash<string_t> {}(element.key());
6392 seed = combine(seed, h);
6393 seed = combine(seed, hash(element.value()));
6394 }
6395 return seed;
6396 }
6397
6398 case BasicJsonType::value_t::array:
6399 {
6400 auto seed = combine(type, j.size());
6401 for (const auto& element : j)
6402 {
6403 seed = combine(seed, hash(element));
6404 }
6405 return seed;
6406 }
6407
6408 case BasicJsonType::value_t::string:
6409 {
6410 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6411 return combine(type, h);
6412 }
6413
6414 case BasicJsonType::value_t::boolean:
6415 {
6416 const auto h = std::hash<bool> {}(j.template get<bool>());
6417 return combine(type, h);
6418 }
6419
6420 case BasicJsonType::value_t::number_integer:
6421 {
6422 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6423 return combine(type, h);
6424 }
6425
6426 case BasicJsonType::value_t::number_unsigned:
6427 {
6428 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6429 return combine(type, h);
6430 }
6431
6432 case BasicJsonType::value_t::number_float:
6433 {
6434 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6435 return combine(type, h);
6436 }
6437
6438 case BasicJsonType::value_t::binary:
6439 {
6440 auto seed = combine(type, j.get_binary().size());
6441 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6442 seed = combine(seed, h);
6443 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6444 for (const auto byte : j.get_binary())
6445 {
6446 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6447 }
6448 return seed;
6449 }
6450
6451 default: // LCOV_EXCL_LINE
6452 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6453 return 0; // LCOV_EXCL_LINE
6454 }
6455}
6456
6457} // namespace detail
6459
6460// #include <nlohmann/detail/input/binary_reader.hpp>
6461// __ _____ _____ _____
6462// __| | __| | | | JSON for Modern C++
6463// | | |__ | | | | | | version 3.12.0
6464// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6465//
6466// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6467// SPDX-License-Identifier: MIT
6468
6469
6470
6471#include <algorithm> // generate_n
6472#include <array> // array
6473#include <cmath> // ldexp
6474#include <cstddef> // size_t
6475#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6476#include <cstdio> // snprintf
6477#include <cstring> // memcpy
6478#include <iterator> // back_inserter
6479#include <limits> // numeric_limits
6480#include <string> // char_traits, string
6481#include <utility> // make_pair, move
6482#include <vector> // vector
6483#ifdef __cpp_lib_byteswap
6484 #include <bit> //byteswap
6485#endif
6486
6487// #include <nlohmann/detail/exceptions.hpp>
6488
6489// #include <nlohmann/detail/input/input_adapters.hpp>
6490// __ _____ _____ _____
6491// __| | __| | | | JSON for Modern C++
6492// | | |__ | | | | | | version 3.12.0
6493// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6494//
6495// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6496// SPDX-License-Identifier: MIT
6497
6498
6499
6500#include <array> // array
6501#include <cstddef> // size_t
6502#include <cstring> // strlen
6503#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6504#include <memory> // shared_ptr, make_shared, addressof
6505#include <numeric> // accumulate
6506#include <string> // string, char_traits
6507#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6508#include <utility> // pair, declval
6509
6510#ifndef JSON_NO_IO
6511 #include <cstdio> // FILE *
6512 #include <istream> // istream
6513#endif // JSON_NO_IO
6514
6515// #include <nlohmann/detail/exceptions.hpp>
6516
6517// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6518
6519// #include <nlohmann/detail/macro_scope.hpp>
6520
6521// #include <nlohmann/detail/meta/type_traits.hpp>
6522
6523
6525namespace detail
6526{
6527
6530
6532// input adapters //
6534
6535#ifndef JSON_NO_IO
6541{
6542 public:
6543 using char_type = char;
6544
6546 explicit file_input_adapter(std::FILE* f) noexcept
6547 : m_file(f)
6548 {
6549 JSON_ASSERT(m_file != nullptr);
6550 }
6551
6552 // make class move-only
6555 file_input_adapter& operator=(const file_input_adapter&) = delete;
6558
6559 std::char_traits<char>::int_type get_character() noexcept
6560 {
6561 return std::fgetc(m_file);
6562 }
6563
6564 // returns the number of characters successfully read
6565 template<class T>
6566 std::size_t get_elements(T* dest, std::size_t count = 1)
6567 {
6568 return fread(dest, 1, sizeof(T) * count, m_file);
6569 }
6570
6571 private:
6573 std::FILE* m_file;
6574};
6575
6586{
6587 public:
6588 using char_type = char;
6589
6591 {
6592 // clear stream flags; we use underlying streambuf I/O, do not
6593 // maintain ifstream flags, except eof
6594 if (is != nullptr)
6595 {
6596 is->clear(is->rdstate() & std::ios::eofbit);
6597 }
6598 }
6599
6600 explicit input_stream_adapter(std::istream& i)
6601 : is(&i), sb(i.rdbuf())
6602 {}
6603
6604 // deleted because of pointer members
6608
6610 : is(rhs.is), sb(rhs.sb)
6611 {
6612 rhs.is = nullptr;
6613 rhs.sb = nullptr;
6614 }
6615
6616 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6617 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6618 // end up as the same value, e.g., 0xFFFFFFFF.
6619 std::char_traits<char>::int_type get_character()
6620 {
6621 auto res = sb->sbumpc();
6622 // set eof manually, as we don't use the istream interface.
6623 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6624 {
6625 is->clear(is->rdstate() | std::ios::eofbit);
6626 }
6627 return res;
6628 }
6629
6630 template<class T>
6631 std::size_t get_elements(T* dest, std::size_t count = 1)
6632 {
6633 auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
6634 if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T)))
6635 {
6636 is->clear(is->rdstate() | std::ios::eofbit);
6637 }
6638 return res;
6639 }
6640
6641 private:
6643 std::istream* is = nullptr;
6644 std::streambuf* sb = nullptr;
6645};
6646#endif // JSON_NO_IO
6647
6648// General-purpose iterator-based adapter. It might not be as fast as
6649// theoretically possible for some containers, but it is extremely versatile.
6650template<typename IteratorType>
6652{
6653 public:
6654 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6655
6656 iterator_input_adapter(IteratorType first, IteratorType last)
6657 : current(std::move(first)), end(std::move(last))
6658 {}
6659
6661 {
6662 if (JSON_HEDLEY_LIKELY(current != end))
6663 {
6664 auto result = char_traits<char_type>::to_int_type(*current);
6665 std::advance(current, 1);
6666 return result;
6667 }
6668
6670 }
6671
6672 // for general iterators, we cannot really do something better than falling back to processing the range one-by-one
6673 template<class T>
6674 std::size_t get_elements(T* dest, std::size_t count = 1)
6675 {
6676 auto* ptr = reinterpret_cast<char*>(dest);
6677 for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index)
6678 {
6679 if (JSON_HEDLEY_LIKELY(current != end))
6680 {
6681 ptr[read_index] = static_cast<char>(*current);
6682 std::advance(current, 1);
6683 }
6684 else
6685 {
6686 return read_index;
6687 }
6688 }
6689 return count * sizeof(T);
6690 }
6691
6692 private:
6693 IteratorType current;
6694 IteratorType end;
6695
6696 template<typename BaseInputAdapter, size_t T>
6698
6699 bool empty() const
6700 {
6701 return current == end;
6702 }
6703};
6704
6705template<typename BaseInputAdapter, size_t T>
6707
6708template<typename BaseInputAdapter>
6709struct wide_string_input_helper<BaseInputAdapter, 4>
6710{
6711 // UTF-32
6712 static void fill_buffer(BaseInputAdapter& input,
6713 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6714 size_t& utf8_bytes_index,
6715 size_t& utf8_bytes_filled)
6716 {
6717 utf8_bytes_index = 0;
6718
6719 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6720 {
6721 utf8_bytes[0] = std::char_traits<char>::eof();
6722 utf8_bytes_filled = 1;
6723 }
6724 else
6725 {
6726 // get the current character
6727 const auto wc = input.get_character();
6728
6729 // UTF-32 to UTF-8 encoding
6730 if (wc < 0x80)
6731 {
6732 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6733 utf8_bytes_filled = 1;
6734 }
6735 else if (wc <= 0x7FF)
6736 {
6737 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6738 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6739 utf8_bytes_filled = 2;
6740 }
6741 else if (wc <= 0xFFFF)
6742 {
6743 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6744 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6745 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6746 utf8_bytes_filled = 3;
6747 }
6748 else if (wc <= 0x10FFFF)
6749 {
6750 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6751 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6752 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6753 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6754 utf8_bytes_filled = 4;
6755 }
6756 else
6757 {
6758 // unknown character
6759 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6760 utf8_bytes_filled = 1;
6761 }
6762 }
6763 }
6764};
6765
6766template<typename BaseInputAdapter>
6767struct wide_string_input_helper<BaseInputAdapter, 2>
6768{
6769 // UTF-16
6770 static void fill_buffer(BaseInputAdapter& input,
6771 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6772 size_t& utf8_bytes_index,
6773 size_t& utf8_bytes_filled)
6774 {
6775 utf8_bytes_index = 0;
6776
6777 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6778 {
6779 utf8_bytes[0] = std::char_traits<char>::eof();
6780 utf8_bytes_filled = 1;
6781 }
6782 else
6783 {
6784 // get the current character
6785 const auto wc = input.get_character();
6786
6787 // UTF-16 to UTF-8 encoding
6788 if (wc < 0x80)
6789 {
6790 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6791 utf8_bytes_filled = 1;
6792 }
6793 else if (wc <= 0x7FF)
6794 {
6795 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6796 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6797 utf8_bytes_filled = 2;
6798 }
6799 else if (0xD800 > wc || wc >= 0xE000)
6800 {
6801 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6802 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6803 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6804 utf8_bytes_filled = 3;
6805 }
6806 else
6807 {
6808 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6809 {
6810 const auto wc2 = static_cast<unsigned int>(input.get_character());
6811 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6812 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6813 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6814 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6815 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6816 utf8_bytes_filled = 4;
6817 }
6818 else
6819 {
6820 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6821 utf8_bytes_filled = 1;
6822 }
6823 }
6824 }
6825 }
6826};
6827
6828// Wraps another input adapter to convert wide character types into individual bytes.
6829template<typename BaseInputAdapter, typename WideCharType>
6831{
6832 public:
6833 using char_type = char;
6834
6835 wide_string_input_adapter(BaseInputAdapter base)
6836 : base_adapter(base) {}
6837
6838 typename std::char_traits<char>::int_type get_character() noexcept
6839 {
6840 // check if the buffer needs to be filled
6841 if (utf8_bytes_index == utf8_bytes_filled)
6842 {
6843 fill_buffer<sizeof(WideCharType)>();
6844
6845 JSON_ASSERT(utf8_bytes_filled > 0);
6846 JSON_ASSERT(utf8_bytes_index == 0);
6847 }
6848
6849 // use buffer
6850 JSON_ASSERT(utf8_bytes_filled > 0);
6851 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6852 return utf8_bytes[utf8_bytes_index++];
6853 }
6854
6855 // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
6856 template<class T>
6857 std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
6858 {
6859 JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
6860 }
6861
6862 private:
6863 BaseInputAdapter base_adapter;
6864
6865 template<size_t T>
6866 void fill_buffer()
6867 {
6868 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6869 }
6870
6872 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6873
6875 std::size_t utf8_bytes_index = 0;
6877 std::size_t utf8_bytes_filled = 0;
6878};
6879
6880template<typename IteratorType, typename Enable = void>
6882{
6883 using iterator_type = IteratorType;
6884 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6886
6887 static adapter_type create(IteratorType first, IteratorType last)
6888 {
6889 return adapter_type(std::move(first), std::move(last));
6890 }
6891};
6892
6893template<typename T>
6895{
6896 using value_type = typename std::iterator_traits<T>::value_type;
6897 enum
6898 {
6899 value = sizeof(value_type) > 1
6900 };
6901};
6902
6903template<typename IteratorType>
6905{
6906 using iterator_type = IteratorType;
6907 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6910
6911 static adapter_type create(IteratorType first, IteratorType last)
6912 {
6913 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6914 }
6915};
6916
6917// General purpose iterator-based input
6918template<typename IteratorType>
6920{
6922 return factory_type::create(first, last);
6923}
6924
6925// Convenience shorthand from container to iterator
6926// Enables ADL on begin(container) and end(container)
6927// Encloses the using declarations in namespace for not to leak them to outside scope
6928
6929namespace container_input_adapter_factory_impl
6930{
6931
6932using std::begin;
6933using std::end;
6934
6935template<typename ContainerType, typename Enable = void>
6937
6938template<typename ContainerType>
6940 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6941 {
6942 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6943
6944 static adapter_type create(const ContainerType& container)
6945{
6946 return input_adapter(begin(container), end(container));
6947}
6948 };
6949
6950} // namespace container_input_adapter_factory_impl
6951
6952template<typename ContainerType>
6957
6958// specialization for std::string
6959using string_input_adapter_type = decltype(input_adapter(std::declval<std::string>()));
6960
6961#ifndef JSON_NO_IO
6962// Special cases with fast paths
6963inline file_input_adapter input_adapter(std::FILE* file)
6964{
6965 if (file == nullptr)
6966 {
6967 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));
6968 }
6969 return file_input_adapter(file);
6970}
6971
6972inline input_stream_adapter input_adapter(std::istream& stream)
6973{
6974 return input_stream_adapter(stream);
6975}
6976
6977inline input_stream_adapter input_adapter(std::istream&& stream)
6978{
6979 return input_stream_adapter(stream);
6980}
6981#endif // JSON_NO_IO
6982
6983using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6984
6985// Null-delimited strings, and the like.
6986template < typename CharT,
6987 typename std::enable_if <
6988 std::is_pointer<CharT>::value&&
6989 !std::is_array<CharT>::value&&
6990 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6991 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6992 int >::type = 0 >
6994{
6995 if (b == nullptr)
6996 {
6997 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));
6998 }
6999 auto length = std::strlen(reinterpret_cast<const char*>(b));
7000 const auto* ptr = reinterpret_cast<const char*>(b);
7001 return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck]
7002}
7003
7004template<typename T, std::size_t N>
7005auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
7006{
7007 return input_adapter(array, array + N);
7008}
7009
7010// This class only handles inputs of input_buffer_adapter type.
7011// It's required so that expressions like {ptr, len} can be implicitly cast
7012// to the correct adapter.
7014{
7015 public:
7016 template < typename CharT,
7017 typename std::enable_if <
7018 std::is_pointer<CharT>::value&&
7019 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
7020 sizeof(typename std::remove_pointer<CharT>::type) == 1,
7021 int >::type = 0 >
7022 span_input_adapter(CharT b, std::size_t l)
7023 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
7024
7025 template<class IteratorType,
7026 typename std::enable_if<
7027 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
7028 int>::type = 0>
7029 span_input_adapter(IteratorType first, IteratorType last)
7030 : ia(input_adapter(first, last)) {}
7031
7033 {
7034 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
7035 }
7036
7037 private:
7039};
7040
7041} // namespace detail
7043
7044// #include <nlohmann/detail/input/json_sax.hpp>
7045// __ _____ _____ _____
7046// __| | __| | | | JSON for Modern C++
7047// | | |__ | | | | | | version 3.12.0
7048// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7049//
7050// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7051// SPDX-License-Identifier: MIT
7052
7053
7054
7055#include <cstddef>
7056#include <string> // string
7057#include <type_traits> // enable_if_t
7058#include <utility> // move
7059#include <vector> // vector
7060
7061// #include <nlohmann/detail/exceptions.hpp>
7062
7063// #include <nlohmann/detail/input/lexer.hpp>
7064// __ _____ _____ _____
7065// __| | __| | | | JSON for Modern C++
7066// | | |__ | | | | | | version 3.12.0
7067// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7068//
7069// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7070// SPDX-License-Identifier: MIT
7071
7072
7073
7074#include <array> // array
7075#include <clocale> // localeconv
7076#include <cstddef> // size_t
7077#include <cstdio> // snprintf
7078#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7079#include <initializer_list> // initializer_list
7080#include <string> // char_traits, string
7081#include <utility> // move
7082#include <vector> // vector
7083
7084// #include <nlohmann/detail/input/input_adapters.hpp>
7085
7086// #include <nlohmann/detail/input/position_t.hpp>
7087
7088// #include <nlohmann/detail/macro_scope.hpp>
7089
7090// #include <nlohmann/detail/meta/type_traits.hpp>
7091
7092
7094namespace detail
7095{
7096
7098// lexer //
7100
7101template<typename BasicJsonType>
7103{
7104 public:
7126
7130 static const char* token_type_name(const token_type t) noexcept
7131 {
7132 switch (t)
7133 {
7135 return "<uninitialized>";
7137 return "true literal";
7139 return "false literal";
7141 return "null literal";
7143 return "string literal";
7147 return "number literal";
7149 return "'['";
7151 return "'{'";
7153 return "']'";
7155 return "'}'";
7157 return "':'";
7159 return "','";
7161 return "<parse error>";
7163 return "end of input";
7165 return "'[', '{', or a literal";
7166 // LCOV_EXCL_START
7167 default: // catch non-enum values
7168 return "unknown token";
7169 // LCOV_EXCL_STOP
7170 }
7171 }
7172};
7178template<typename BasicJsonType, typename InputAdapterType>
7179class lexer : public lexer_base<BasicJsonType>
7180{
7181 using number_integer_t = typename BasicJsonType::number_integer_t;
7182 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7183 using number_float_t = typename BasicJsonType::number_float_t;
7184 using string_t = typename BasicJsonType::string_t;
7185 using char_type = typename InputAdapterType::char_type;
7186 using char_int_type = typename char_traits<char_type>::int_type;
7187
7188 public:
7190
7191 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7192 : ia(std::move(adapter))
7193 , ignore_comments(ignore_comments_)
7194 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7195 {}
7196
7197 // deleted because of pointer members
7198 lexer(const lexer&) = delete;
7199 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7200 lexer& operator=(lexer&) = delete;
7201 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7202 ~lexer() = default;
7203
7204 private:
7206 // locales
7208
7211 static char get_decimal_point() noexcept
7212 {
7213 const auto* loc = localeconv();
7214 JSON_ASSERT(loc != nullptr);
7215 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7216 }
7217
7219 // scan functions
7221
7237 int get_codepoint()
7238 {
7239 // this function only makes sense after reading `\u`
7240 JSON_ASSERT(current == 'u');
7241 int codepoint = 0;
7242
7243 const auto factors = { 12u, 8u, 4u, 0u };
7244 for (const auto factor : factors)
7245 {
7246 get();
7247
7248 if (current >= '0' && current <= '9')
7249 {
7250 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7251 }
7252 else if (current >= 'A' && current <= 'F')
7253 {
7254 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7255 }
7256 else if (current >= 'a' && current <= 'f')
7257 {
7258 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7259 }
7260 else
7261 {
7262 return -1;
7263 }
7264 }
7265
7266 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7267 return codepoint;
7268 }
7269
7285 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7286 {
7287 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7288 add(current);
7289
7290 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7291 {
7292 get();
7293 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7294 {
7295 add(current);
7296 }
7297 else
7298 {
7299 error_message = "invalid string: ill-formed UTF-8 byte";
7300 return false;
7301 }
7302 }
7303
7304 return true;
7305 }
7306
7322 token_type scan_string()
7323 {
7324 // reset token_buffer (ignore opening quote)
7325 reset();
7326
7327 // we entered the function by reading an open quote
7328 JSON_ASSERT(current == '\"');
7329
7330 while (true)
7331 {
7332 // get the next character
7333 switch (get())
7334 {
7335 // end of file while parsing the string
7336 case char_traits<char_type>::eof():
7337 {
7338 error_message = "invalid string: missing closing quote";
7339 return token_type::parse_error;
7340 }
7341
7342 // closing quote
7343 case '\"':
7344 {
7345 return token_type::value_string;
7346 }
7347
7348 // escapes
7349 case '\\':
7350 {
7351 switch (get())
7352 {
7353 // quotation mark
7354 case '\"':
7355 add('\"');
7356 break;
7357 // reverse solidus
7358 case '\\':
7359 add('\\');
7360 break;
7361 // solidus
7362 case '/':
7363 add('/');
7364 break;
7365 // backspace
7366 case 'b':
7367 add('\b');
7368 break;
7369 // form feed
7370 case 'f':
7371 add('\f');
7372 break;
7373 // line feed
7374 case 'n':
7375 add('\n');
7376 break;
7377 // carriage return
7378 case 'r':
7379 add('\r');
7380 break;
7381 // tab
7382 case 't':
7383 add('\t');
7384 break;
7385
7386 // unicode escapes
7387 case 'u':
7388 {
7389 const int codepoint1 = get_codepoint();
7390 int codepoint = codepoint1; // start with codepoint1
7391
7392 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7393 {
7394 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7395 return token_type::parse_error;
7396 }
7397
7398 // check if code point is a high surrogate
7399 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7400 {
7401 // expect next \uxxxx entry
7402 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7403 {
7404 const int codepoint2 = get_codepoint();
7405
7406 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7407 {
7408 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7409 return token_type::parse_error;
7410 }
7411
7412 // check if codepoint2 is a low surrogate
7413 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7414 {
7415 // overwrite codepoint
7416 codepoint = static_cast<int>(
7417 // high surrogate occupies the most significant 22 bits
7418 (static_cast<unsigned int>(codepoint1) << 10u)
7419 // low surrogate occupies the least significant 15 bits
7420 + static_cast<unsigned int>(codepoint2)
7421 // there is still the 0xD800, 0xDC00, and 0x10000 noise
7422 // in the result, so we have to subtract with:
7423 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7424 - 0x35FDC00u);
7425 }
7426 else
7427 {
7428 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7429 return token_type::parse_error;
7430 }
7431 }
7432 else
7433 {
7434 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7435 return token_type::parse_error;
7436 }
7437 }
7438 else
7439 {
7440 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7441 {
7442 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7443 return token_type::parse_error;
7444 }
7445 }
7446
7447 // the result of the above calculation yields a proper codepoint
7448 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7449
7450 // translate codepoint into bytes
7451 if (codepoint < 0x80)
7452 {
7453 // 1-byte characters: 0xxxxxxx (ASCII)
7454 add(static_cast<char_int_type>(codepoint));
7455 }
7456 else if (codepoint <= 0x7FF)
7457 {
7458 // 2-byte characters: 110xxxxx 10xxxxxx
7459 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7460 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7461 }
7462 else if (codepoint <= 0xFFFF)
7463 {
7464 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7465 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7466 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7467 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7468 }
7469 else
7470 {
7471 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7472 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7473 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7474 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7475 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7476 }
7477
7478 break;
7479 }
7480
7481 // other characters after escape
7482 default:
7483 error_message = "invalid string: forbidden character after backslash";
7484 return token_type::parse_error;
7485 }
7486
7487 break;
7488 }
7489
7490 // invalid control characters
7491 case 0x00:
7492 {
7493 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7494 return token_type::parse_error;
7495 }
7496
7497 case 0x01:
7498 {
7499 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7500 return token_type::parse_error;
7501 }
7502
7503 case 0x02:
7504 {
7505 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7506 return token_type::parse_error;
7507 }
7508
7509 case 0x03:
7510 {
7511 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7512 return token_type::parse_error;
7513 }
7514
7515 case 0x04:
7516 {
7517 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7518 return token_type::parse_error;
7519 }
7520
7521 case 0x05:
7522 {
7523 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7524 return token_type::parse_error;
7525 }
7526
7527 case 0x06:
7528 {
7529 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7530 return token_type::parse_error;
7531 }
7532
7533 case 0x07:
7534 {
7535 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7536 return token_type::parse_error;
7537 }
7538
7539 case 0x08:
7540 {
7541 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7542 return token_type::parse_error;
7543 }
7544
7545 case 0x09:
7546 {
7547 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7548 return token_type::parse_error;
7549 }
7550
7551 case 0x0A:
7552 {
7553 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7554 return token_type::parse_error;
7555 }
7556
7557 case 0x0B:
7558 {
7559 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7560 return token_type::parse_error;
7561 }
7562
7563 case 0x0C:
7564 {
7565 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7566 return token_type::parse_error;
7567 }
7568
7569 case 0x0D:
7570 {
7571 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7572 return token_type::parse_error;
7573 }
7574
7575 case 0x0E:
7576 {
7577 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7578 return token_type::parse_error;
7579 }
7580
7581 case 0x0F:
7582 {
7583 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7584 return token_type::parse_error;
7585 }
7586
7587 case 0x10:
7588 {
7589 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7590 return token_type::parse_error;
7591 }
7592
7593 case 0x11:
7594 {
7595 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7596 return token_type::parse_error;
7597 }
7598
7599 case 0x12:
7600 {
7601 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7602 return token_type::parse_error;
7603 }
7604
7605 case 0x13:
7606 {
7607 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7608 return token_type::parse_error;
7609 }
7610
7611 case 0x14:
7612 {
7613 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7614 return token_type::parse_error;
7615 }
7616
7617 case 0x15:
7618 {
7619 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7620 return token_type::parse_error;
7621 }
7622
7623 case 0x16:
7624 {
7625 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7626 return token_type::parse_error;
7627 }
7628
7629 case 0x17:
7630 {
7631 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7632 return token_type::parse_error;
7633 }
7634
7635 case 0x18:
7636 {
7637 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7638 return token_type::parse_error;
7639 }
7640
7641 case 0x19:
7642 {
7643 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7644 return token_type::parse_error;
7645 }
7646
7647 case 0x1A:
7648 {
7649 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7650 return token_type::parse_error;
7651 }
7652
7653 case 0x1B:
7654 {
7655 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7656 return token_type::parse_error;
7657 }
7658
7659 case 0x1C:
7660 {
7661 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7662 return token_type::parse_error;
7663 }
7664
7665 case 0x1D:
7666 {
7667 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7668 return token_type::parse_error;
7669 }
7670
7671 case 0x1E:
7672 {
7673 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7674 return token_type::parse_error;
7675 }
7676
7677 case 0x1F:
7678 {
7679 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7680 return token_type::parse_error;
7681 }
7682
7683 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7684 case 0x20:
7685 case 0x21:
7686 case 0x23:
7687 case 0x24:
7688 case 0x25:
7689 case 0x26:
7690 case 0x27:
7691 case 0x28:
7692 case 0x29:
7693 case 0x2A:
7694 case 0x2B:
7695 case 0x2C:
7696 case 0x2D:
7697 case 0x2E:
7698 case 0x2F:
7699 case 0x30:
7700 case 0x31:
7701 case 0x32:
7702 case 0x33:
7703 case 0x34:
7704 case 0x35:
7705 case 0x36:
7706 case 0x37:
7707 case 0x38:
7708 case 0x39:
7709 case 0x3A:
7710 case 0x3B:
7711 case 0x3C:
7712 case 0x3D:
7713 case 0x3E:
7714 case 0x3F:
7715 case 0x40:
7716 case 0x41:
7717 case 0x42:
7718 case 0x43:
7719 case 0x44:
7720 case 0x45:
7721 case 0x46:
7722 case 0x47:
7723 case 0x48:
7724 case 0x49:
7725 case 0x4A:
7726 case 0x4B:
7727 case 0x4C:
7728 case 0x4D:
7729 case 0x4E:
7730 case 0x4F:
7731 case 0x50:
7732 case 0x51:
7733 case 0x52:
7734 case 0x53:
7735 case 0x54:
7736 case 0x55:
7737 case 0x56:
7738 case 0x57:
7739 case 0x58:
7740 case 0x59:
7741 case 0x5A:
7742 case 0x5B:
7743 case 0x5D:
7744 case 0x5E:
7745 case 0x5F:
7746 case 0x60:
7747 case 0x61:
7748 case 0x62:
7749 case 0x63:
7750 case 0x64:
7751 case 0x65:
7752 case 0x66:
7753 case 0x67:
7754 case 0x68:
7755 case 0x69:
7756 case 0x6A:
7757 case 0x6B:
7758 case 0x6C:
7759 case 0x6D:
7760 case 0x6E:
7761 case 0x6F:
7762 case 0x70:
7763 case 0x71:
7764 case 0x72:
7765 case 0x73:
7766 case 0x74:
7767 case 0x75:
7768 case 0x76:
7769 case 0x77:
7770 case 0x78:
7771 case 0x79:
7772 case 0x7A:
7773 case 0x7B:
7774 case 0x7C:
7775 case 0x7D:
7776 case 0x7E:
7777 case 0x7F:
7778 {
7779 add(current);
7780 break;
7781 }
7782
7783 // U+0080..U+07FF: bytes C2..DF 80..BF
7784 case 0xC2:
7785 case 0xC3:
7786 case 0xC4:
7787 case 0xC5:
7788 case 0xC6:
7789 case 0xC7:
7790 case 0xC8:
7791 case 0xC9:
7792 case 0xCA:
7793 case 0xCB:
7794 case 0xCC:
7795 case 0xCD:
7796 case 0xCE:
7797 case 0xCF:
7798 case 0xD0:
7799 case 0xD1:
7800 case 0xD2:
7801 case 0xD3:
7802 case 0xD4:
7803 case 0xD5:
7804 case 0xD6:
7805 case 0xD7:
7806 case 0xD8:
7807 case 0xD9:
7808 case 0xDA:
7809 case 0xDB:
7810 case 0xDC:
7811 case 0xDD:
7812 case 0xDE:
7813 case 0xDF:
7814 {
7815 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7816 {
7817 return token_type::parse_error;
7818 }
7819 break;
7820 }
7821
7822 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7823 case 0xE0:
7824 {
7825 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7826 {
7827 return token_type::parse_error;
7828 }
7829 break;
7830 }
7831
7832 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7833 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7834 case 0xE1:
7835 case 0xE2:
7836 case 0xE3:
7837 case 0xE4:
7838 case 0xE5:
7839 case 0xE6:
7840 case 0xE7:
7841 case 0xE8:
7842 case 0xE9:
7843 case 0xEA:
7844 case 0xEB:
7845 case 0xEC:
7846 case 0xEE:
7847 case 0xEF:
7848 {
7849 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7850 {
7851 return token_type::parse_error;
7852 }
7853 break;
7854 }
7855
7856 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7857 case 0xED:
7858 {
7859 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7860 {
7861 return token_type::parse_error;
7862 }
7863 break;
7864 }
7865
7866 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7867 case 0xF0:
7868 {
7869 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7870 {
7871 return token_type::parse_error;
7872 }
7873 break;
7874 }
7875
7876 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7877 case 0xF1:
7878 case 0xF2:
7879 case 0xF3:
7880 {
7881 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7882 {
7883 return token_type::parse_error;
7884 }
7885 break;
7886 }
7887
7888 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7889 case 0xF4:
7890 {
7891 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7892 {
7893 return token_type::parse_error;
7894 }
7895 break;
7896 }
7897
7898 // the remaining bytes (80..C1 and F5..FF) are ill-formed
7899 default:
7900 {
7901 error_message = "invalid string: ill-formed UTF-8 byte";
7902 return token_type::parse_error;
7903 }
7904 }
7905 }
7906 }
7907
7912 bool scan_comment()
7913 {
7914 switch (get())
7915 {
7916 // single-line comments skip input until a newline or EOF is read
7917 case '/':
7918 {
7919 while (true)
7920 {
7921 switch (get())
7922 {
7923 case '\n':
7924 case '\r':
7925 case char_traits<char_type>::eof():
7926 case '\0':
7927 return true;
7928
7929 default:
7930 break;
7931 }
7932 }
7933 }
7934
7935 // multi-line comments skip input until */ is read
7936 case '*':
7937 {
7938 while (true)
7939 {
7940 switch (get())
7941 {
7942 case char_traits<char_type>::eof():
7943 case '\0':
7944 {
7945 error_message = "invalid comment; missing closing '*/'";
7946 return false;
7947 }
7948
7949 case '*':
7950 {
7951 switch (get())
7952 {
7953 case '/':
7954 return true;
7955
7956 default:
7957 {
7958 unget();
7959 continue;
7960 }
7961 }
7962 }
7963
7964 default:
7965 continue;
7966 }
7967 }
7968 }
7969
7970 // unexpected character after reading '/'
7971 default:
7972 {
7973 error_message = "invalid comment; expecting '/' or '*' after '/'";
7974 return false;
7975 }
7976 }
7977 }
7978
7980 static void strtof(float& f, const char* str, char** endptr) noexcept
7981 {
7982 f = std::strtof(str, endptr);
7983 }
7984
7986 static void strtof(double& f, const char* str, char** endptr) noexcept
7987 {
7988 f = std::strtod(str, endptr);
7989 }
7990
7992 static void strtof(long double& f, const char* str, char** endptr) noexcept
7993 {
7994 f = std::strtold(str, endptr);
7995 }
7996
8037 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.
8038 {
8039 // reset token_buffer to store the number's bytes
8040 reset();
8041
8042 // the type of the parsed number; initially set to unsigned; will be
8043 // changed if minus sign, decimal point, or exponent is read
8044 token_type number_type = token_type::value_unsigned;
8045
8046 // state (init): we just found out we need to scan a number
8047 switch (current)
8048 {
8049 case '-':
8050 {
8051 add(current);
8052 goto scan_number_minus;
8053 }
8054
8055 case '0':
8056 {
8057 add(current);
8058 goto scan_number_zero;
8059 }
8060
8061 case '1':
8062 case '2':
8063 case '3':
8064 case '4':
8065 case '5':
8066 case '6':
8067 case '7':
8068 case '8':
8069 case '9':
8070 {
8071 add(current);
8072 goto scan_number_any1;
8073 }
8074
8075 // all other characters are rejected outside scan_number()
8076 default: // LCOV_EXCL_LINE
8077 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8078 }
8079
8080scan_number_minus:
8081 // state: we just parsed a leading minus sign
8082 number_type = token_type::value_integer;
8083 switch (get())
8084 {
8085 case '0':
8086 {
8087 add(current);
8088 goto scan_number_zero;
8089 }
8090
8091 case '1':
8092 case '2':
8093 case '3':
8094 case '4':
8095 case '5':
8096 case '6':
8097 case '7':
8098 case '8':
8099 case '9':
8100 {
8101 add(current);
8102 goto scan_number_any1;
8103 }
8104
8105 default:
8106 {
8107 error_message = "invalid number; expected digit after '-'";
8108 return token_type::parse_error;
8109 }
8110 }
8111
8112scan_number_zero:
8113 // state: we just parse a zero (maybe with a leading minus sign)
8114 switch (get())
8115 {
8116 case '.':
8117 {
8118 add(decimal_point_char);
8119 decimal_point_position = token_buffer.size() - 1;
8120 goto scan_number_decimal1;
8121 }
8122
8123 case 'e':
8124 case 'E':
8125 {
8126 add(current);
8127 goto scan_number_exponent;
8128 }
8129
8130 default:
8131 goto scan_number_done;
8132 }
8133
8134scan_number_any1:
8135 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8136 switch (get())
8137 {
8138 case '0':
8139 case '1':
8140 case '2':
8141 case '3':
8142 case '4':
8143 case '5':
8144 case '6':
8145 case '7':
8146 case '8':
8147 case '9':
8148 {
8149 add(current);
8150 goto scan_number_any1;
8151 }
8152
8153 case '.':
8154 {
8155 add(decimal_point_char);
8156 decimal_point_position = token_buffer.size() - 1;
8157 goto scan_number_decimal1;
8158 }
8159
8160 case 'e':
8161 case 'E':
8162 {
8163 add(current);
8164 goto scan_number_exponent;
8165 }
8166
8167 default:
8168 goto scan_number_done;
8169 }
8170
8171scan_number_decimal1:
8172 // state: we just parsed a decimal point
8173 number_type = token_type::value_float;
8174 switch (get())
8175 {
8176 case '0':
8177 case '1':
8178 case '2':
8179 case '3':
8180 case '4':
8181 case '5':
8182 case '6':
8183 case '7':
8184 case '8':
8185 case '9':
8186 {
8187 add(current);
8188 goto scan_number_decimal2;
8189 }
8190
8191 default:
8192 {
8193 error_message = "invalid number; expected digit after '.'";
8194 return token_type::parse_error;
8195 }
8196 }
8197
8198scan_number_decimal2:
8199 // we just parsed at least one number after a decimal point
8200 switch (get())
8201 {
8202 case '0':
8203 case '1':
8204 case '2':
8205 case '3':
8206 case '4':
8207 case '5':
8208 case '6':
8209 case '7':
8210 case '8':
8211 case '9':
8212 {
8213 add(current);
8214 goto scan_number_decimal2;
8215 }
8216
8217 case 'e':
8218 case 'E':
8219 {
8220 add(current);
8221 goto scan_number_exponent;
8222 }
8223
8224 default:
8225 goto scan_number_done;
8226 }
8227
8228scan_number_exponent:
8229 // we just parsed an exponent
8230 number_type = token_type::value_float;
8231 switch (get())
8232 {
8233 case '+':
8234 case '-':
8235 {
8236 add(current);
8237 goto scan_number_sign;
8238 }
8239
8240 case '0':
8241 case '1':
8242 case '2':
8243 case '3':
8244 case '4':
8245 case '5':
8246 case '6':
8247 case '7':
8248 case '8':
8249 case '9':
8250 {
8251 add(current);
8252 goto scan_number_any2;
8253 }
8254
8255 default:
8256 {
8257 error_message =
8258 "invalid number; expected '+', '-', or digit after exponent";
8259 return token_type::parse_error;
8260 }
8261 }
8262
8263scan_number_sign:
8264 // we just parsed an exponent 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_any2;
8280 }
8281
8282 default:
8283 {
8284 error_message = "invalid number; expected digit after exponent sign";
8285 return token_type::parse_error;
8286 }
8287 }
8288
8289scan_number_any2:
8290 // we just parsed a number after the exponent or exponent sign
8291 switch (get())
8292 {
8293 case '0':
8294 case '1':
8295 case '2':
8296 case '3':
8297 case '4':
8298 case '5':
8299 case '6':
8300 case '7':
8301 case '8':
8302 case '9':
8303 {
8304 add(current);
8305 goto scan_number_any2;
8306 }
8307
8308 default:
8309 goto scan_number_done;
8310 }
8311
8312scan_number_done:
8313 // unget the character after the number (we only read it to know that
8314 // we are done scanning a number)
8315 unget();
8316
8317 char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8318 errno = 0;
8319
8320 // try to parse integers first and fall back to floats
8321 if (number_type == token_type::value_unsigned)
8322 {
8323 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8324
8325 // we checked the number format before
8326 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8327
8328 if (errno != ERANGE)
8329 {
8330 value_unsigned = static_cast<number_unsigned_t>(x);
8331 if (value_unsigned == x)
8332 {
8333 return token_type::value_unsigned;
8334 }
8335 }
8336 }
8337 else if (number_type == token_type::value_integer)
8338 {
8339 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8340
8341 // we checked the number format before
8342 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8343
8344 if (errno != ERANGE)
8345 {
8346 value_integer = static_cast<number_integer_t>(x);
8347 if (value_integer == x)
8348 {
8349 return token_type::value_integer;
8350 }
8351 }
8352 }
8353
8354 // this code is reached if we parse a floating-point number or if an
8355 // integer conversion above failed
8356 strtof(value_float, token_buffer.data(), &endptr);
8357
8358 // we checked the number format before
8359 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8360
8361 return token_type::value_float;
8362 }
8363
8370 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8371 token_type return_type)
8372 {
8373 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8374 for (std::size_t i = 1; i < length; ++i)
8375 {
8376 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8377 {
8378 error_message = "invalid literal";
8379 return token_type::parse_error;
8380 }
8381 }
8382 return return_type;
8383 }
8384
8386 // input management
8388
8390 void reset() noexcept
8391 {
8392 token_buffer.clear();
8393 token_string.clear();
8394 decimal_point_position = std::string::npos;
8395 token_string.push_back(char_traits<char_type>::to_char_type(current));
8396 }
8397
8398 /*
8399 @brief get next character from the input
8400
8401 This function provides the interface to the used input adapter. It does
8402 not throw in case the input reached EOF, but returns a
8403 `char_traits<char>::eof()` in that case. Stores the scanned characters
8404 for use in error messages.
8405
8406 @return character read from the input
8407 */
8408 char_int_type get()
8409 {
8410 ++position.chars_read_total;
8411 ++position.chars_read_current_line;
8412
8413 if (next_unget)
8414 {
8415 // only reset the next_unget variable and work with current
8416 next_unget = false;
8417 }
8418 else
8419 {
8420 current = ia.get_character();
8421 }
8422
8423 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8424 {
8425 token_string.push_back(char_traits<char_type>::to_char_type(current));
8426 }
8427
8428 if (current == '\n')
8429 {
8430 ++position.lines_read;
8431 position.chars_read_current_line = 0;
8432 }
8433
8434 return current;
8435 }
8436
8445 void unget()
8446 {
8447 next_unget = true;
8448
8449 --position.chars_read_total;
8450
8451 // in case we "unget" a newline, we have to also decrement the lines_read
8452 if (position.chars_read_current_line == 0)
8453 {
8454 if (position.lines_read > 0)
8455 {
8456 --position.lines_read;
8457 }
8458 }
8459 else
8460 {
8461 --position.chars_read_current_line;
8462 }
8463
8464 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8465 {
8466 JSON_ASSERT(!token_string.empty());
8467 token_string.pop_back();
8468 }
8469 }
8470
8472 void add(char_int_type c)
8473 {
8474 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8475 }
8476
8477 public:
8479 // value getters
8481
8483 constexpr number_integer_t get_number_integer() const noexcept
8484 {
8485 return value_integer;
8486 }
8487
8489 constexpr number_unsigned_t get_number_unsigned() const noexcept
8490 {
8491 return value_unsigned;
8492 }
8493
8495 constexpr number_float_t get_number_float() const noexcept
8496 {
8497 return value_float;
8498 }
8499
8501 string_t& get_string()
8502 {
8503 // translate decimal points from locale back to '.' (#4084)
8504 if (decimal_point_char != '.' && decimal_point_position != std::string::npos)
8505 {
8506 token_buffer[decimal_point_position] = '.';
8507 }
8508 return token_buffer;
8509 }
8510
8512 // diagnostics
8514
8516 constexpr position_t get_position() const noexcept
8517 {
8518 return position;
8519 }
8520
8524 std::string get_token_string() const
8525 {
8526 // escape control characters
8527 std::string result;
8528 for (const auto c : token_string)
8529 {
8530 if (static_cast<unsigned char>(c) <= '\x1F')
8531 {
8532 // escape control characters
8533 std::array<char, 9> cs{{}};
8534 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8535 result += cs.data();
8536 }
8537 else
8538 {
8539 // add character as is
8540 result.push_back(static_cast<std::string::value_type>(c));
8541 }
8542 }
8543
8544 return result;
8545 }
8546
8549 constexpr const char* get_error_message() const noexcept
8550 {
8551 return error_message;
8552 }
8553
8555 // actual scanner
8557
8563 {
8564 if (get() == 0xEF)
8565 {
8566 // check if we completely parse the BOM
8567 return get() == 0xBB && get() == 0xBF;
8568 }
8569
8570 // the first character is not the beginning of the BOM; unget it to
8571 // process is later
8572 unget();
8573 return true;
8574 }
8575
8577 {
8578 do
8579 {
8580 get();
8581 }
8582 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8583 }
8584
8586 {
8587 // initially, skip the BOM
8588 if (position.chars_read_total == 0 && !skip_bom())
8589 {
8590 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8591 return token_type::parse_error;
8592 }
8593
8594 // read the next character and ignore whitespace
8595 skip_whitespace();
8596
8597 // ignore comments
8598 while (ignore_comments && current == '/')
8599 {
8600 if (!scan_comment())
8601 {
8602 return token_type::parse_error;
8603 }
8604
8605 // skip following whitespace
8606 skip_whitespace();
8607 }
8608
8609 switch (current)
8610 {
8611 // structural characters
8612 case '[':
8613 return token_type::begin_array;
8614 case ']':
8615 return token_type::end_array;
8616 case '{':
8617 return token_type::begin_object;
8618 case '}':
8619 return token_type::end_object;
8620 case ':':
8621 return token_type::name_separator;
8622 case ',':
8623 return token_type::value_separator;
8624
8625 // literals
8626 case 't':
8627 {
8628 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')}};
8629 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8630 }
8631 case 'f':
8632 {
8633 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')}};
8634 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8635 }
8636 case 'n':
8637 {
8638 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')}};
8639 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8640 }
8641
8642 // string
8643 case '\"':
8644 return scan_string();
8645
8646 // number
8647 case '-':
8648 case '0':
8649 case '1':
8650 case '2':
8651 case '3':
8652 case '4':
8653 case '5':
8654 case '6':
8655 case '7':
8656 case '8':
8657 case '9':
8658 return scan_number();
8659
8660 // end of input (the null byte is needed when parsing from
8661 // string literals)
8662 case '\0':
8664 return token_type::end_of_input;
8665
8666 // error
8667 default:
8668 error_message = "invalid literal";
8669 return token_type::parse_error;
8670 }
8671 }
8672
8673 private:
8675 InputAdapterType ia;
8676
8678 const bool ignore_comments = false;
8679
8681 char_int_type current = char_traits<char_type>::eof();
8682
8684 bool next_unget = false;
8685
8687 position_t position {};
8688
8690 std::vector<char_type> token_string {};
8691
8693 string_t token_buffer {};
8694
8696 const char* error_message = "";
8697
8698 // number values
8699 number_integer_t value_integer = 0;
8700 number_unsigned_t value_unsigned = 0;
8701 number_float_t value_float = 0;
8702
8704 const char_int_type decimal_point_char = '.';
8706 std::size_t decimal_point_position = std::string::npos;
8707};
8708
8709} // namespace detail
8711
8712// #include <nlohmann/detail/macro_scope.hpp>
8713
8714// #include <nlohmann/detail/string_concat.hpp>
8715
8717
8726template<typename BasicJsonType>
8728{
8729 using number_integer_t = typename BasicJsonType::number_integer_t;
8730 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8731 using number_float_t = typename BasicJsonType::number_float_t;
8732 using string_t = typename BasicJsonType::string_t;
8733 using binary_t = typename BasicJsonType::binary_t;
8734
8739 virtual bool null() = 0;
8740
8746 virtual bool boolean(bool val) = 0;
8747
8753 virtual bool number_integer(number_integer_t val) = 0;
8754
8760 virtual bool number_unsigned(number_unsigned_t val) = 0;
8761
8768 virtual bool number_float(number_float_t val, const string_t& s) = 0;
8769
8776 virtual bool string(string_t& val) = 0;
8777
8784 virtual bool binary(binary_t& val) = 0;
8785
8792 virtual bool start_object(std::size_t elements) = 0;
8793
8800 virtual bool key(string_t& val) = 0;
8801
8806 virtual bool end_object() = 0;
8807
8814 virtual bool start_array(std::size_t elements) = 0;
8815
8820 virtual bool end_array() = 0;
8821
8829 virtual bool parse_error(std::size_t position,
8830 const std::string& last_token,
8831 const detail::exception& ex) = 0;
8832
8833 json_sax() = default;
8834 json_sax(const json_sax&) = default;
8835 json_sax(json_sax&&) noexcept = default;
8836 json_sax& operator=(const json_sax&) = default;
8837 json_sax& operator=(json_sax&&) noexcept = default;
8838 virtual ~json_sax() = default;
8839};
8840
8841namespace detail
8842{
8843constexpr std::size_t unknown_size()
8844{
8845 return (std::numeric_limits<std::size_t>::max)();
8846}
8847
8861template<typename BasicJsonType, typename InputAdapterType>
8863{
8864 public:
8865 using number_integer_t = typename BasicJsonType::number_integer_t;
8866 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8867 using number_float_t = typename BasicJsonType::number_float_t;
8868 using string_t = typename BasicJsonType::string_t;
8869 using binary_t = typename BasicJsonType::binary_t;
8871
8877 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr)
8878 : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
8879 {}
8880
8881 // make class move-only
8883 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8885 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8887
8888 bool null()
8889 {
8890 handle_value(nullptr);
8891 return true;
8892 }
8893
8894 bool boolean(bool val)
8895 {
8896 handle_value(val);
8897 return true;
8898 }
8899
8901 {
8902 handle_value(val);
8903 return true;
8904 }
8905
8907 {
8908 handle_value(val);
8909 return true;
8910 }
8911
8912 bool number_float(number_float_t val, const string_t& /*unused*/)
8913 {
8914 handle_value(val);
8915 return true;
8916 }
8917
8918 bool string(string_t& val)
8919 {
8920 handle_value(val);
8921 return true;
8922 }
8923
8924 bool binary(binary_t& val)
8925 {
8926 handle_value(std::move(val));
8927 return true;
8928 }
8929
8930 bool start_object(std::size_t len)
8931 {
8932 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
8933
8934#if JSON_DIAGNOSTIC_POSITIONS
8935 // Manually set the start position of the object here.
8936 // Ensure this is after the call to handle_value to ensure correct start position.
8937 if (m_lexer_ref)
8938 {
8939 // Lexer has read the first character of the object, so
8940 // subtract 1 from the position to get the correct start position.
8941 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8942 }
8943#endif
8944
8945 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
8946 {
8947 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
8948 }
8949
8950 return true;
8951 }
8952
8953 bool key(string_t& val)
8954 {
8955 JSON_ASSERT(!ref_stack.empty());
8956 JSON_ASSERT(ref_stack.back()->is_object());
8957
8958 // add null at the given key and store the reference for later
8959 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
8960 return true;
8961 }
8962
8964 {
8965 JSON_ASSERT(!ref_stack.empty());
8966 JSON_ASSERT(ref_stack.back()->is_object());
8967
8968#if JSON_DIAGNOSTIC_POSITIONS
8969 if (m_lexer_ref)
8970 {
8971 // Lexer's position is past the closing brace, so set that as the end position.
8972 ref_stack.back()->end_position = m_lexer_ref->get_position();
8973 }
8974#endif
8975
8976 ref_stack.back()->set_parents();
8977 ref_stack.pop_back();
8978 return true;
8979 }
8980
8981 bool start_array(std::size_t len)
8982 {
8983 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
8984
8985#if JSON_DIAGNOSTIC_POSITIONS
8986 // Manually set the start position of the array here.
8987 // Ensure this is after the call to handle_value to ensure correct start position.
8988 if (m_lexer_ref)
8989 {
8990 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8991 }
8992#endif
8993
8994 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
8995 {
8996 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
8997 }
8998
8999 return true;
9000 }
9001
9003 {
9004 JSON_ASSERT(!ref_stack.empty());
9005 JSON_ASSERT(ref_stack.back()->is_array());
9006
9007#if JSON_DIAGNOSTIC_POSITIONS
9008 if (m_lexer_ref)
9009 {
9010 // Lexer's position is past the closing bracket, so set that as the end position.
9011 ref_stack.back()->end_position = m_lexer_ref->get_position();
9012 }
9013#endif
9014
9015 ref_stack.back()->set_parents();
9016 ref_stack.pop_back();
9017 return true;
9018 }
9019
9020 template<class Exception>
9021 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9022 const Exception& ex)
9023 {
9024 errored = true;
9025 static_cast<void>(ex);
9026 if (allow_exceptions)
9027 {
9028 JSON_THROW(ex);
9029 }
9030 return false;
9031 }
9032
9033 constexpr bool is_errored() const
9034 {
9035 return errored;
9036 }
9037
9038 private:
9039
9040#if JSON_DIAGNOSTIC_POSITIONS
9041 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9042 {
9043 if (m_lexer_ref)
9044 {
9045 // Lexer has read past the current field value, so set the end position to the current position.
9046 // The start position will be set below based on the length of the string representation
9047 // of the value.
9048 v.end_position = m_lexer_ref->get_position();
9049
9050 switch (v.type())
9051 {
9052 case value_t::boolean:
9053 {
9054 // 4 and 5 are the string length of "true" and "false"
9055 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9056 break;
9057 }
9058
9059 case value_t::null:
9060 {
9061 // 4 is the string length of "null"
9062 v.start_position = v.end_position - 4;
9063 break;
9064 }
9065
9066 case value_t::string:
9067 {
9068 // include the length of the quotes, which is 2
9069 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9070 break;
9071 }
9072
9073 // As we handle the start and end positions for values created during parsing,
9074 // we do not expect the following value type to be called. Regardless, set the positions
9075 // in case this is created manually or through a different constructor. Exclude from lcov
9076 // since the exact condition of this switch is esoteric.
9077 // LCOV_EXCL_START
9078 case value_t::discarded:
9079 {
9080 v.end_position = std::string::npos;
9081 v.start_position = v.end_position;
9082 break;
9083 }
9084 // LCOV_EXCL_STOP
9085 case value_t::binary:
9086 case value_t::number_integer:
9087 case value_t::number_unsigned:
9088 case value_t::number_float:
9089 {
9090 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9091 break;
9092 }
9093 case value_t::object:
9094 case value_t::array:
9095 {
9096 // object and array are handled in start_object() and start_array() handlers
9097 // skip setting the values here.
9098 break;
9099 }
9100 default: // LCOV_EXCL_LINE
9101 // Handle all possible types discretely, default handler should never be reached.
9102 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9103 }
9104 }
9105 }
9106#endif
9107
9114 template<typename Value>
9116 BasicJsonType* handle_value(Value&& v)
9117 {
9118 if (ref_stack.empty())
9119 {
9120 root = BasicJsonType(std::forward<Value>(v));
9121
9122#if JSON_DIAGNOSTIC_POSITIONS
9123 handle_diagnostic_positions_for_json_value(root);
9124#endif
9125
9126 return &root;
9127 }
9128
9129 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9130
9131 if (ref_stack.back()->is_array())
9132 {
9133 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
9134
9135#if JSON_DIAGNOSTIC_POSITIONS
9136 handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back());
9137#endif
9138
9139 return &(ref_stack.back()->m_data.m_value.array->back());
9140 }
9141
9142 JSON_ASSERT(ref_stack.back()->is_object());
9143 JSON_ASSERT(object_element);
9144 *object_element = BasicJsonType(std::forward<Value>(v));
9145
9146#if JSON_DIAGNOSTIC_POSITIONS
9147 handle_diagnostic_positions_for_json_value(*object_element);
9148#endif
9149
9150 return object_element;
9151 }
9152
9154 BasicJsonType& root;
9156 std::vector<BasicJsonType*> ref_stack {};
9158 BasicJsonType* object_element = nullptr;
9160 bool errored = false;
9162 const bool allow_exceptions = true;
9164 lexer_t* m_lexer_ref = nullptr;
9165};
9166
9167template<typename BasicJsonType, typename InputAdapterType>
9169{
9170 public:
9171 using number_integer_t = typename BasicJsonType::number_integer_t;
9172 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9173 using number_float_t = typename BasicJsonType::number_float_t;
9174 using string_t = typename BasicJsonType::string_t;
9175 using binary_t = typename BasicJsonType::binary_t;
9176 using parser_callback_t = typename BasicJsonType::parser_callback_t;
9177 using parse_event_t = typename BasicJsonType::parse_event_t;
9179
9182 const bool allow_exceptions_ = true,
9183 lexer_t* lexer_ = nullptr)
9184 : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
9185 {
9186 keep_stack.push_back(true);
9187 }
9188
9189 // make class move-only
9191 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9193 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9195
9196 bool null()
9197 {
9198 handle_value(nullptr);
9199 return true;
9200 }
9201
9202 bool boolean(bool val)
9203 {
9204 handle_value(val);
9205 return true;
9206 }
9207
9209 {
9210 handle_value(val);
9211 return true;
9212 }
9213
9215 {
9216 handle_value(val);
9217 return true;
9218 }
9219
9220 bool number_float(number_float_t val, const string_t& /*unused*/)
9221 {
9222 handle_value(val);
9223 return true;
9224 }
9225
9226 bool string(string_t& val)
9227 {
9228 handle_value(val);
9229 return true;
9230 }
9231
9232 bool binary(binary_t& val)
9233 {
9234 handle_value(std::move(val));
9235 return true;
9236 }
9237
9238 bool start_object(std::size_t len)
9239 {
9240 // check callback for object start
9241 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
9242 keep_stack.push_back(keep);
9243
9244 auto val = handle_value(BasicJsonType::value_t::object, true);
9245 ref_stack.push_back(val.second);
9246
9247 if (ref_stack.back())
9248 {
9249
9250#if JSON_DIAGNOSTIC_POSITIONS
9251 // Manually set the start position of the object here.
9252 // Ensure this is after the call to handle_value to ensure correct start position.
9253 if (m_lexer_ref)
9254 {
9255 // Lexer has read the first character of the object, so
9256 // subtract 1 from the position to get the correct start position.
9257 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9258 }
9259#endif
9260
9261 // check object limit
9262 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9263 {
9264 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
9265 }
9266 }
9267 return true;
9268 }
9269
9270 bool key(string_t& val)
9271 {
9272 BasicJsonType k = BasicJsonType(val);
9273
9274 // check callback for the key
9275 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
9276 key_keep_stack.push_back(keep);
9277
9278 // add discarded value at the given key and store the reference for later
9279 if (keep && ref_stack.back())
9280 {
9281 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
9282 }
9283
9284 return true;
9285 }
9286
9288 {
9289 if (ref_stack.back())
9290 {
9291 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
9292 {
9293 // discard object
9294 *ref_stack.back() = discarded;
9295
9296#if JSON_DIAGNOSTIC_POSITIONS
9297 // Set start/end positions for discarded object.
9298 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9299#endif
9300 }
9301 else
9302 {
9303
9304#if JSON_DIAGNOSTIC_POSITIONS
9305 if (m_lexer_ref)
9306 {
9307 // Lexer's position is past the closing brace, so set that as the end position.
9308 ref_stack.back()->end_position = m_lexer_ref->get_position();
9309 }
9310#endif
9311
9312 ref_stack.back()->set_parents();
9313 }
9314 }
9315
9316 JSON_ASSERT(!ref_stack.empty());
9317 JSON_ASSERT(!keep_stack.empty());
9318 ref_stack.pop_back();
9319 keep_stack.pop_back();
9320
9321 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
9322 {
9323 // remove discarded value
9324 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
9325 {
9326 if (it->is_discarded())
9327 {
9328 ref_stack.back()->erase(it);
9329 break;
9330 }
9331 }
9332 }
9333
9334 return true;
9335 }
9336
9337 bool start_array(std::size_t len)
9338 {
9339 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
9340 keep_stack.push_back(keep);
9341
9342 auto val = handle_value(BasicJsonType::value_t::array, true);
9343 ref_stack.push_back(val.second);
9344
9345 if (ref_stack.back())
9346 {
9347
9348#if JSON_DIAGNOSTIC_POSITIONS
9349 // Manually set the start position of the array here.
9350 // Ensure this is after the call to handle_value to ensure correct start position.
9351 if (m_lexer_ref)
9352 {
9353 // Lexer has read the first character of the array, so
9354 // subtract 1 from the position to get the correct start position.
9355 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9356 }
9357#endif
9358
9359 // check array limit
9360 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9361 {
9362 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
9363 }
9364 }
9365
9366 return true;
9367 }
9368
9370 {
9371 bool keep = true;
9372
9373 if (ref_stack.back())
9374 {
9375 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
9376 if (keep)
9377 {
9378
9379#if JSON_DIAGNOSTIC_POSITIONS
9380 if (m_lexer_ref)
9381 {
9382 // Lexer's position is past the closing bracket, so set that as the end position.
9383 ref_stack.back()->end_position = m_lexer_ref->get_position();
9384 }
9385#endif
9386
9387 ref_stack.back()->set_parents();
9388 }
9389 else
9390 {
9391 // discard array
9392 *ref_stack.back() = discarded;
9393
9394#if JSON_DIAGNOSTIC_POSITIONS
9395 // Set start/end positions for discarded array.
9396 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9397#endif
9398 }
9399 }
9400
9401 JSON_ASSERT(!ref_stack.empty());
9402 JSON_ASSERT(!keep_stack.empty());
9403 ref_stack.pop_back();
9404 keep_stack.pop_back();
9405
9406 // remove discarded value
9407 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
9408 {
9409 ref_stack.back()->m_data.m_value.array->pop_back();
9410 }
9411
9412 return true;
9413 }
9414
9415 template<class Exception>
9416 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9417 const Exception& ex)
9418 {
9419 errored = true;
9420 static_cast<void>(ex);
9421 if (allow_exceptions)
9422 {
9423 JSON_THROW(ex);
9424 }
9425 return false;
9426 }
9427
9428 constexpr bool is_errored() const
9429 {
9430 return errored;
9431 }
9432
9433 private:
9434
9435#if JSON_DIAGNOSTIC_POSITIONS
9436 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9437 {
9438 if (m_lexer_ref)
9439 {
9440 // Lexer has read past the current field value, so set the end position to the current position.
9441 // The start position will be set below based on the length of the string representation
9442 // of the value.
9443 v.end_position = m_lexer_ref->get_position();
9444
9445 switch (v.type())
9446 {
9447 case value_t::boolean:
9448 {
9449 // 4 and 5 are the string length of "true" and "false"
9450 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9451 break;
9452 }
9453
9454 case value_t::null:
9455 {
9456 // 4 is the string length of "null"
9457 v.start_position = v.end_position - 4;
9458 break;
9459 }
9460
9461 case value_t::string:
9462 {
9463 // include the length of the quotes, which is 2
9464 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9465 break;
9466 }
9467
9468 case value_t::discarded:
9469 {
9470 v.end_position = std::string::npos;
9471 v.start_position = v.end_position;
9472 break;
9473 }
9474
9475 case value_t::binary:
9476 case value_t::number_integer:
9477 case value_t::number_unsigned:
9478 case value_t::number_float:
9479 {
9480 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9481 break;
9482 }
9483
9484 case value_t::object:
9485 case value_t::array:
9486 {
9487 // object and array are handled in start_object() and start_array() handlers
9488 // skip setting the values here.
9489 break;
9490 }
9491 default: // LCOV_EXCL_LINE
9492 // Handle all possible types discretely, default handler should never be reached.
9493 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9494 }
9495 }
9496 }
9497#endif
9498
9514 template<typename Value>
9515 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
9516 {
9517 JSON_ASSERT(!keep_stack.empty());
9518
9519 // do not handle this value if we know it would be added to a discarded
9520 // container
9521 if (!keep_stack.back())
9522 {
9523 return {false, nullptr};
9524 }
9525
9526 // create value
9527 auto value = BasicJsonType(std::forward<Value>(v));
9528
9529#if JSON_DIAGNOSTIC_POSITIONS
9530 handle_diagnostic_positions_for_json_value(value);
9531#endif
9532
9533 // check callback
9534 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
9535
9536 // do not handle this value if we just learnt it shall be discarded
9537 if (!keep)
9538 {
9539 return {false, nullptr};
9540 }
9541
9542 if (ref_stack.empty())
9543 {
9544 root = std::move(value);
9545 return {true, & root};
9546 }
9547
9548 // skip this value if we already decided to skip the parent
9549 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
9550 if (!ref_stack.back())
9551 {
9552 return {false, nullptr};
9553 }
9554
9555 // we now only expect arrays and objects
9556 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9557
9558 // array
9559 if (ref_stack.back()->is_array())
9560 {
9561 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
9562 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
9563 }
9564
9565 // object
9566 JSON_ASSERT(ref_stack.back()->is_object());
9567 // check if we should store an element for the current key
9568 JSON_ASSERT(!key_keep_stack.empty());
9569 const bool store_element = key_keep_stack.back();
9570 key_keep_stack.pop_back();
9571
9572 if (!store_element)
9573 {
9574 return {false, nullptr};
9575 }
9576
9577 JSON_ASSERT(object_element);
9578 *object_element = std::move(value);
9579 return {true, object_element};
9580 }
9581
9583 BasicJsonType& root;
9585 std::vector<BasicJsonType*> ref_stack {};
9587 std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
9589 std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
9591 BasicJsonType* object_element = nullptr;
9593 bool errored = false;
9595 const parser_callback_t callback = nullptr;
9597 const bool allow_exceptions = true;
9599 BasicJsonType discarded = BasicJsonType::value_t::discarded;
9601 lexer_t* m_lexer_ref = nullptr;
9602};
9603
9604template<typename BasicJsonType>
9606{
9607 public:
9608 using number_integer_t = typename BasicJsonType::number_integer_t;
9609 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9610 using number_float_t = typename BasicJsonType::number_float_t;
9611 using string_t = typename BasicJsonType::string_t;
9612 using binary_t = typename BasicJsonType::binary_t;
9613
9614 bool null()
9615 {
9616 return true;
9617 }
9618
9619 bool boolean(bool /*unused*/)
9620 {
9621 return true;
9622 }
9623
9625 {
9626 return true;
9627 }
9628
9630 {
9631 return true;
9632 }
9633
9634 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
9635 {
9636 return true;
9637 }
9638
9639 bool string(string_t& /*unused*/)
9640 {
9641 return true;
9642 }
9643
9644 bool binary(binary_t& /*unused*/)
9645 {
9646 return true;
9647 }
9648
9649 bool start_object(std::size_t /*unused*/ = detail::unknown_size())
9650 {
9651 return true;
9652 }
9653
9654 bool key(string_t& /*unused*/)
9655 {
9656 return true;
9657 }
9658
9660 {
9661 return true;
9662 }
9663
9664 bool start_array(std::size_t /*unused*/ = detail::unknown_size())
9665 {
9666 return true;
9667 }
9668
9670 {
9671 return true;
9672 }
9673
9674 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
9675 {
9676 return false;
9677 }
9678};
9679
9680} // namespace detail
9682
9683// #include <nlohmann/detail/input/lexer.hpp>
9684
9685// #include <nlohmann/detail/macro_scope.hpp>
9686
9687// #include <nlohmann/detail/meta/is_sax.hpp>
9688// __ _____ _____ _____
9689// __| | __| | | | JSON for Modern C++
9690// | | |__ | | | | | | version 3.12.0
9691// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9692//
9693// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
9694// SPDX-License-Identifier: MIT
9695
9696
9697
9698#include <cstdint> // size_t
9699#include <utility> // declval
9700#include <string> // string
9701
9702// #include <nlohmann/detail/abi_macros.hpp>
9703
9704// #include <nlohmann/detail/meta/detected.hpp>
9705
9706// #include <nlohmann/detail/meta/type_traits.hpp>
9707
9708
9710namespace detail
9711{
9712
9713template<typename T>
9714using null_function_t = decltype(std::declval<T&>().null());
9715
9716template<typename T>
9718 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9719
9720template<typename T, typename Integer>
9722 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9723
9724template<typename T, typename Unsigned>
9726 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9727
9728template<typename T, typename Float, typename String>
9729using number_float_function_t = decltype(std::declval<T&>().number_float(
9730 std::declval<Float>(), std::declval<const String&>()));
9731
9732template<typename T, typename String>
9734 decltype(std::declval<T&>().string(std::declval<String&>()));
9735
9736template<typename T, typename Binary>
9738 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9739
9740template<typename T>
9742 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9743
9744template<typename T, typename String>
9746 decltype(std::declval<T&>().key(std::declval<String&>()));
9747
9748template<typename T>
9749using end_object_function_t = decltype(std::declval<T&>().end_object());
9750
9751template<typename T>
9753 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9754
9755template<typename T>
9756using end_array_function_t = decltype(std::declval<T&>().end_array());
9757
9758template<typename T, typename Exception>
9759using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9760 std::declval<std::size_t>(), std::declval<const std::string&>(),
9761 std::declval<const Exception&>()));
9762
9763template<typename SAX, typename BasicJsonType>
9765{
9766 private:
9768 "BasicJsonType must be of type basic_json<...>");
9769
9770 using number_integer_t = typename BasicJsonType::number_integer_t;
9771 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9772 using number_float_t = typename BasicJsonType::number_float_t;
9773 using string_t = typename BasicJsonType::string_t;
9774 using binary_t = typename BasicJsonType::binary_t;
9775 using exception_t = typename BasicJsonType::exception;
9776
9777 public:
9778 static constexpr bool value =
9792};
9793
9794template<typename SAX, typename BasicJsonType>
9796{
9797 private:
9799 "BasicJsonType must be of type basic_json<...>");
9800
9801 using number_integer_t = typename BasicJsonType::number_integer_t;
9802 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9803 using number_float_t = typename BasicJsonType::number_float_t;
9804 using string_t = typename BasicJsonType::string_t;
9805 using binary_t = typename BasicJsonType::binary_t;
9806 using exception_t = typename BasicJsonType::exception;
9807
9808 public:
9810 "Missing/invalid function: bool null()");
9812 "Missing/invalid function: bool boolean(bool)");
9814 "Missing/invalid function: bool boolean(bool)");
9815 static_assert(
9817 number_integer_t>::value,
9818 "Missing/invalid function: bool number_integer(number_integer_t)");
9819 static_assert(
9821 number_unsigned_t>::value,
9822 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9823 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9824 number_float_t, string_t>::value,
9825 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9826 static_assert(
9828 "Missing/invalid function: bool string(string_t&)");
9829 static_assert(
9831 "Missing/invalid function: bool binary(binary_t&)");
9833 "Missing/invalid function: bool start_object(std::size_t)");
9835 "Missing/invalid function: bool key(string_t&)");
9837 "Missing/invalid function: bool end_object()");
9839 "Missing/invalid function: bool start_array(std::size_t)");
9841 "Missing/invalid function: bool end_array()");
9842 static_assert(
9844 "Missing/invalid function: bool parse_error(std::size_t, const "
9845 "std::string&, const exception&)");
9846};
9847
9848} // namespace detail
9850
9851// #include <nlohmann/detail/meta/type_traits.hpp>
9852
9853// #include <nlohmann/detail/string_concat.hpp>
9854
9855// #include <nlohmann/detail/value_t.hpp>
9856
9857
9859namespace detail
9860{
9861
9864{
9865 error,
9866 ignore,
9867 store
9868};
9869
9877inline bool little_endianness(int num = 1) noexcept
9878{
9879 return *reinterpret_cast<char*>(&num) == 1;
9880}
9881
9883// binary reader //
9885
9889template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType, InputAdapterType>>
9891{
9892 using number_integer_t = typename BasicJsonType::number_integer_t;
9893 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9894 using number_float_t = typename BasicJsonType::number_float_t;
9895 using string_t = typename BasicJsonType::string_t;
9896 using binary_t = typename BasicJsonType::binary_t;
9897 using json_sax_t = SAX;
9898 using char_type = typename InputAdapterType::char_type;
9899 using char_int_type = typename char_traits<char_type>::int_type;
9900
9901 public:
9907 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9908 {
9910 }
9911
9912 // make class move-only
9914 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9916 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9917 ~binary_reader() = default;
9918
9928 bool sax_parse(const input_format_t format,
9929 json_sax_t* sax_,
9930 const bool strict = true,
9931 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9932 {
9933 sax = sax_;
9934 bool result = false;
9935
9936 switch (format)
9937 {
9938 case input_format_t::bson:
9939 result = parse_bson_internal();
9940 break;
9941
9942 case input_format_t::cbor:
9943 result = parse_cbor_internal(true, tag_handler);
9944 break;
9945
9946 case input_format_t::msgpack:
9947 result = parse_msgpack_internal();
9948 break;
9949
9950 case input_format_t::ubjson:
9951 case input_format_t::bjdata:
9952 result = parse_ubjson_internal();
9953 break;
9954
9955 case input_format_t::json: // LCOV_EXCL_LINE
9956 default: // LCOV_EXCL_LINE
9957 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9958 }
9959
9960 // strict mode: next byte must be EOF
9961 if (result && strict)
9962 {
9963 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9964 {
9965 get_ignore_noop();
9966 }
9967 else
9968 {
9969 get();
9970 }
9971
9973 {
9974 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9975 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9976 }
9977 }
9978
9979 return result;
9980 }
9981
9982 private:
9984 // BSON //
9986
9991 bool parse_bson_internal()
9992 {
9993 std::int32_t document_size{};
9994 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9995
9996 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
9997 {
9998 return false;
9999 }
10000
10001 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
10002 {
10003 return false;
10004 }
10005
10006 return sax->end_object();
10007 }
10008
10016 bool get_bson_cstr(string_t& result)
10017 {
10018 auto out = std::back_inserter(result);
10019 while (true)
10020 {
10021 get();
10022 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
10023 {
10024 return false;
10025 }
10026 if (current == 0x00)
10027 {
10028 return true;
10029 }
10030 *out++ = static_cast<typename string_t::value_type>(current);
10031 }
10032 }
10033
10045 template<typename NumberType>
10046 bool get_bson_string(const NumberType len, string_t& result)
10047 {
10048 if (JSON_HEDLEY_UNLIKELY(len < 1))
10049 {
10050 auto last_token = get_token_string();
10051 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10052 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
10053 }
10054
10055 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
10056 }
10057
10067 template<typename NumberType>
10068 bool get_bson_binary(const NumberType len, binary_t& result)
10069 {
10070 if (JSON_HEDLEY_UNLIKELY(len < 0))
10071 {
10072 auto last_token = get_token_string();
10073 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10074 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
10075 }
10076
10077 // All BSON binary values have a subtype
10078 std::uint8_t subtype{};
10079 get_number<std::uint8_t>(input_format_t::bson, subtype);
10080 result.set_subtype(subtype);
10081
10082 return get_binary(input_format_t::bson, len, result);
10083 }
10084
10095 bool parse_bson_element_internal(const char_int_type element_type,
10096 const std::size_t element_type_parse_position)
10097 {
10098 switch (element_type)
10099 {
10100 case 0x01: // double
10101 {
10102 double number{};
10103 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10104 }
10105
10106 case 0x02: // string
10107 {
10108 std::int32_t len{};
10109 string_t value;
10110 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
10111 }
10112
10113 case 0x03: // object
10114 {
10115 return parse_bson_internal();
10116 }
10117
10118 case 0x04: // array
10119 {
10120 return parse_bson_array();
10121 }
10122
10123 case 0x05: // binary
10124 {
10125 std::int32_t len{};
10126 binary_t value;
10127 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
10128 }
10129
10130 case 0x08: // boolean
10131 {
10132 return sax->boolean(get() != 0);
10133 }
10134
10135 case 0x0A: // null
10136 {
10137 return sax->null();
10138 }
10139
10140 case 0x10: // int32
10141 {
10142 std::int32_t value{};
10143 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10144 }
10145
10146 case 0x12: // int64
10147 {
10148 std::int64_t value{};
10149 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10150 }
10151
10152 case 0x11: // uint64
10153 {
10154 std::uint64_t value{};
10155 return get_number<std::uint64_t, true>(input_format_t::bson, value) && sax->number_unsigned(value);
10156 }
10157
10158 default: // anything else is not supported (yet)
10159 {
10160 std::array<char, 3> cr{{}};
10161 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10162 const std::string cr_str{cr.data()};
10163 return sax->parse_error(element_type_parse_position, cr_str,
10164 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
10165 }
10166 }
10167 }
10168
10181 bool parse_bson_element_list(const bool is_array)
10182 {
10183 string_t key;
10184
10185 while (auto element_type = get())
10186 {
10187 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
10188 {
10189 return false;
10190 }
10191
10192 const std::size_t element_type_parse_position = chars_read;
10193 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
10194 {
10195 return false;
10196 }
10197
10198 if (!is_array && !sax->key(key))
10199 {
10200 return false;
10201 }
10202
10203 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
10204 {
10205 return false;
10206 }
10207
10208 // get_bson_cstr only appends
10209 key.clear();
10210 }
10211
10212 return true;
10213 }
10214
10219 bool parse_bson_array()
10220 {
10221 std::int32_t document_size{};
10222 get_number<std::int32_t, true>(input_format_t::bson, document_size);
10223
10224 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
10225 {
10226 return false;
10227 }
10228
10229 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
10230 {
10231 return false;
10232 }
10233
10234 return sax->end_array();
10235 }
10236
10238 // CBOR //
10240
10249 bool parse_cbor_internal(const bool get_char,
10250 const cbor_tag_handler_t tag_handler)
10251 {
10252 switch (get_char ? get() : current)
10253 {
10254 // EOF
10255 case char_traits<char_type>::eof():
10256 return unexpect_eof(input_format_t::cbor, "value");
10257
10258 // Integer 0x00..0x17 (0..23)
10259 case 0x00:
10260 case 0x01:
10261 case 0x02:
10262 case 0x03:
10263 case 0x04:
10264 case 0x05:
10265 case 0x06:
10266 case 0x07:
10267 case 0x08:
10268 case 0x09:
10269 case 0x0A:
10270 case 0x0B:
10271 case 0x0C:
10272 case 0x0D:
10273 case 0x0E:
10274 case 0x0F:
10275 case 0x10:
10276 case 0x11:
10277 case 0x12:
10278 case 0x13:
10279 case 0x14:
10280 case 0x15:
10281 case 0x16:
10282 case 0x17:
10283 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10284
10285 case 0x18: // Unsigned integer (one-byte uint8_t follows)
10286 {
10287 std::uint8_t number{};
10288 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10289 }
10290
10291 case 0x19: // Unsigned integer (two-byte uint16_t follows)
10292 {
10293 std::uint16_t number{};
10294 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10295 }
10296
10297 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
10298 {
10299 std::uint32_t number{};
10300 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10301 }
10302
10303 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
10304 {
10305 std::uint64_t number{};
10306 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10307 }
10308
10309 // Negative integer -1-0x00..-1-0x17 (-1..-24)
10310 case 0x20:
10311 case 0x21:
10312 case 0x22:
10313 case 0x23:
10314 case 0x24:
10315 case 0x25:
10316 case 0x26:
10317 case 0x27:
10318 case 0x28:
10319 case 0x29:
10320 case 0x2A:
10321 case 0x2B:
10322 case 0x2C:
10323 case 0x2D:
10324 case 0x2E:
10325 case 0x2F:
10326 case 0x30:
10327 case 0x31:
10328 case 0x32:
10329 case 0x33:
10330 case 0x34:
10331 case 0x35:
10332 case 0x36:
10333 case 0x37:
10334 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
10335
10336 case 0x38: // Negative integer (one-byte uint8_t follows)
10337 {
10338 std::uint8_t number{};
10339 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10340 }
10341
10342 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
10343 {
10344 std::uint16_t number{};
10345 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10346 }
10347
10348 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
10349 {
10350 std::uint32_t number{};
10351 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10352 }
10353
10354 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
10355 {
10356 std::uint64_t number{};
10357 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
10358 - static_cast<number_integer_t>(number));
10359 }
10360
10361 // Binary data (0x00..0x17 bytes follow)
10362 case 0x40:
10363 case 0x41:
10364 case 0x42:
10365 case 0x43:
10366 case 0x44:
10367 case 0x45:
10368 case 0x46:
10369 case 0x47:
10370 case 0x48:
10371 case 0x49:
10372 case 0x4A:
10373 case 0x4B:
10374 case 0x4C:
10375 case 0x4D:
10376 case 0x4E:
10377 case 0x4F:
10378 case 0x50:
10379 case 0x51:
10380 case 0x52:
10381 case 0x53:
10382 case 0x54:
10383 case 0x55:
10384 case 0x56:
10385 case 0x57:
10386 case 0x58: // Binary data (one-byte uint8_t for n follows)
10387 case 0x59: // Binary data (two-byte uint16_t for n follow)
10388 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10389 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10390 case 0x5F: // Binary data (indefinite length)
10391 {
10392 binary_t b;
10393 return get_cbor_binary(b) && sax->binary(b);
10394 }
10395
10396 // UTF-8 string (0x00..0x17 bytes follow)
10397 case 0x60:
10398 case 0x61:
10399 case 0x62:
10400 case 0x63:
10401 case 0x64:
10402 case 0x65:
10403 case 0x66:
10404 case 0x67:
10405 case 0x68:
10406 case 0x69:
10407 case 0x6A:
10408 case 0x6B:
10409 case 0x6C:
10410 case 0x6D:
10411 case 0x6E:
10412 case 0x6F:
10413 case 0x70:
10414 case 0x71:
10415 case 0x72:
10416 case 0x73:
10417 case 0x74:
10418 case 0x75:
10419 case 0x76:
10420 case 0x77:
10421 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10422 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10423 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10424 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10425 case 0x7F: // UTF-8 string (indefinite length)
10426 {
10427 string_t s;
10428 return get_cbor_string(s) && sax->string(s);
10429 }
10430
10431 // array (0x00..0x17 data items follow)
10432 case 0x80:
10433 case 0x81:
10434 case 0x82:
10435 case 0x83:
10436 case 0x84:
10437 case 0x85:
10438 case 0x86:
10439 case 0x87:
10440 case 0x88:
10441 case 0x89:
10442 case 0x8A:
10443 case 0x8B:
10444 case 0x8C:
10445 case 0x8D:
10446 case 0x8E:
10447 case 0x8F:
10448 case 0x90:
10449 case 0x91:
10450 case 0x92:
10451 case 0x93:
10452 case 0x94:
10453 case 0x95:
10454 case 0x96:
10455 case 0x97:
10456 return get_cbor_array(
10457 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10458
10459 case 0x98: // array (one-byte uint8_t for n follows)
10460 {
10461 std::uint8_t len{};
10462 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10463 }
10464
10465 case 0x99: // array (two-byte uint16_t for n follow)
10466 {
10467 std::uint16_t len{};
10468 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10469 }
10470
10471 case 0x9A: // array (four-byte uint32_t for n follow)
10472 {
10473 std::uint32_t len{};
10474 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10475 }
10476
10477 case 0x9B: // array (eight-byte uint64_t for n follow)
10478 {
10479 std::uint64_t len{};
10480 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10481 }
10482
10483 case 0x9F: // array (indefinite length)
10484 return get_cbor_array(detail::unknown_size(), tag_handler);
10485
10486 // map (0x00..0x17 pairs of data items follow)
10487 case 0xA0:
10488 case 0xA1:
10489 case 0xA2:
10490 case 0xA3:
10491 case 0xA4:
10492 case 0xA5:
10493 case 0xA6:
10494 case 0xA7:
10495 case 0xA8:
10496 case 0xA9:
10497 case 0xAA:
10498 case 0xAB:
10499 case 0xAC:
10500 case 0xAD:
10501 case 0xAE:
10502 case 0xAF:
10503 case 0xB0:
10504 case 0xB1:
10505 case 0xB2:
10506 case 0xB3:
10507 case 0xB4:
10508 case 0xB5:
10509 case 0xB6:
10510 case 0xB7:
10511 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10512
10513 case 0xB8: // map (one-byte uint8_t for n follows)
10514 {
10515 std::uint8_t len{};
10516 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10517 }
10518
10519 case 0xB9: // map (two-byte uint16_t for n follow)
10520 {
10521 std::uint16_t len{};
10522 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10523 }
10524
10525 case 0xBA: // map (four-byte uint32_t for n follow)
10526 {
10527 std::uint32_t len{};
10528 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10529 }
10530
10531 case 0xBB: // map (eight-byte uint64_t for n follow)
10532 {
10533 std::uint64_t len{};
10534 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10535 }
10536
10537 case 0xBF: // map (indefinite length)
10538 return get_cbor_object(detail::unknown_size(), tag_handler);
10539
10540 case 0xC6: // tagged item
10541 case 0xC7:
10542 case 0xC8:
10543 case 0xC9:
10544 case 0xCA:
10545 case 0xCB:
10546 case 0xCC:
10547 case 0xCD:
10548 case 0xCE:
10549 case 0xCF:
10550 case 0xD0:
10551 case 0xD1:
10552 case 0xD2:
10553 case 0xD3:
10554 case 0xD4:
10555 case 0xD8: // tagged item (1 byte follows)
10556 case 0xD9: // tagged item (2 bytes follow)
10557 case 0xDA: // tagged item (4 bytes follow)
10558 case 0xDB: // tagged item (8 bytes follow)
10559 {
10560 switch (tag_handler)
10561 {
10562 case cbor_tag_handler_t::error:
10563 {
10564 auto last_token = get_token_string();
10565 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10566 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10567 }
10568
10569 case cbor_tag_handler_t::ignore:
10570 {
10571 // ignore binary subtype
10572 switch (current)
10573 {
10574 case 0xD8:
10575 {
10576 std::uint8_t subtype_to_ignore{};
10577 get_number(input_format_t::cbor, subtype_to_ignore);
10578 break;
10579 }
10580 case 0xD9:
10581 {
10582 std::uint16_t subtype_to_ignore{};
10583 get_number(input_format_t::cbor, subtype_to_ignore);
10584 break;
10585 }
10586 case 0xDA:
10587 {
10588 std::uint32_t subtype_to_ignore{};
10589 get_number(input_format_t::cbor, subtype_to_ignore);
10590 break;
10591 }
10592 case 0xDB:
10593 {
10594 std::uint64_t subtype_to_ignore{};
10595 get_number(input_format_t::cbor, subtype_to_ignore);
10596 break;
10597 }
10598 default:
10599 break;
10600 }
10601 return parse_cbor_internal(true, tag_handler);
10602 }
10603
10604 case cbor_tag_handler_t::store:
10605 {
10606 binary_t b;
10607 // use binary subtype and store in a binary container
10608 switch (current)
10609 {
10610 case 0xD8:
10611 {
10612 std::uint8_t subtype{};
10613 get_number(input_format_t::cbor, subtype);
10615 break;
10616 }
10617 case 0xD9:
10618 {
10619 std::uint16_t subtype{};
10620 get_number(input_format_t::cbor, subtype);
10622 break;
10623 }
10624 case 0xDA:
10625 {
10626 std::uint32_t subtype{};
10627 get_number(input_format_t::cbor, subtype);
10629 break;
10630 }
10631 case 0xDB:
10632 {
10633 std::uint64_t subtype{};
10634 get_number(input_format_t::cbor, subtype);
10636 break;
10637 }
10638 default:
10639 return parse_cbor_internal(true, tag_handler);
10640 }
10641 get();
10642 return get_cbor_binary(b) && sax->binary(b);
10643 }
10644
10645 default: // LCOV_EXCL_LINE
10646 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10647 return false; // LCOV_EXCL_LINE
10648 }
10649 }
10650
10651 case 0xF4: // false
10652 return sax->boolean(false);
10653
10654 case 0xF5: // true
10655 return sax->boolean(true);
10656
10657 case 0xF6: // null
10658 return sax->null();
10659
10660 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10661 {
10662 const auto byte1_raw = get();
10663 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10664 {
10665 return false;
10666 }
10667 const auto byte2_raw = get();
10668 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10669 {
10670 return false;
10671 }
10672
10673 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10674 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10675
10676 // Code from RFC 7049, Appendix D, Figure 3:
10677 // As half-precision floating-point numbers were only added
10678 // to IEEE 754 in 2008, today's programming platforms often
10679 // still only have limited support for them. It is very
10680 // easy to include at least decoding support for them even
10681 // without such support. An example of a small decoder for
10682 // half-precision floating-point numbers in the C language
10683 // is shown in Fig. 3.
10684 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10685 const double val = [&half]
10686 {
10687 const int exp = (half >> 10u) & 0x1Fu;
10688 const unsigned int mant = half & 0x3FFu;
10689 JSON_ASSERT(0 <= exp&& exp <= 32);
10690 JSON_ASSERT(mant <= 1024);
10691 switch (exp)
10692 {
10693 case 0:
10694 return std::ldexp(mant, -24);
10695 case 31:
10696 return (mant == 0)
10697 ? std::numeric_limits<double>::infinity()
10698 : std::numeric_limits<double>::quiet_NaN();
10699 default:
10700 return std::ldexp(mant + 1024, exp - 25);
10701 }
10702 }();
10703 return sax->number_float((half & 0x8000u) != 0
10704 ? static_cast<number_float_t>(-val)
10705 : static_cast<number_float_t>(val), "");
10706 }
10707
10708 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10709 {
10710 float number{};
10711 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10712 }
10713
10714 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10715 {
10716 double number{};
10717 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10718 }
10719
10720 default: // anything else (0xFF is handled inside the other types)
10721 {
10722 auto last_token = get_token_string();
10723 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10724 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10725 }
10726 }
10727 }
10728
10740 bool get_cbor_string(string_t& result)
10741 {
10742 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10743 {
10744 return false;
10745 }
10746
10747 switch (current)
10748 {
10749 // UTF-8 string (0x00..0x17 bytes follow)
10750 case 0x60:
10751 case 0x61:
10752 case 0x62:
10753 case 0x63:
10754 case 0x64:
10755 case 0x65:
10756 case 0x66:
10757 case 0x67:
10758 case 0x68:
10759 case 0x69:
10760 case 0x6A:
10761 case 0x6B:
10762 case 0x6C:
10763 case 0x6D:
10764 case 0x6E:
10765 case 0x6F:
10766 case 0x70:
10767 case 0x71:
10768 case 0x72:
10769 case 0x73:
10770 case 0x74:
10771 case 0x75:
10772 case 0x76:
10773 case 0x77:
10774 {
10775 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10776 }
10777
10778 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10779 {
10780 std::uint8_t len{};
10781 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10782 }
10783
10784 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10785 {
10786 std::uint16_t len{};
10787 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10788 }
10789
10790 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10791 {
10792 std::uint32_t len{};
10793 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10794 }
10795
10796 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10797 {
10798 std::uint64_t len{};
10799 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10800 }
10801
10802 case 0x7F: // UTF-8 string (indefinite length)
10803 {
10804 while (get() != 0xFF)
10805 {
10806 string_t chunk;
10807 if (!get_cbor_string(chunk))
10808 {
10809 return false;
10810 }
10811 result.append(chunk);
10812 }
10813 return true;
10814 }
10815
10816 default:
10817 {
10818 auto last_token = get_token_string();
10819 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10820 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10821 }
10822 }
10823 }
10824
10836 bool get_cbor_binary(binary_t& result)
10837 {
10838 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10839 {
10840 return false;
10841 }
10842
10843 switch (current)
10844 {
10845 // Binary data (0x00..0x17 bytes follow)
10846 case 0x40:
10847 case 0x41:
10848 case 0x42:
10849 case 0x43:
10850 case 0x44:
10851 case 0x45:
10852 case 0x46:
10853 case 0x47:
10854 case 0x48:
10855 case 0x49:
10856 case 0x4A:
10857 case 0x4B:
10858 case 0x4C:
10859 case 0x4D:
10860 case 0x4E:
10861 case 0x4F:
10862 case 0x50:
10863 case 0x51:
10864 case 0x52:
10865 case 0x53:
10866 case 0x54:
10867 case 0x55:
10868 case 0x56:
10869 case 0x57:
10870 {
10871 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10872 }
10873
10874 case 0x58: // Binary data (one-byte uint8_t for n follows)
10875 {
10876 std::uint8_t len{};
10877 return get_number(input_format_t::cbor, len) &&
10878 get_binary(input_format_t::cbor, len, result);
10879 }
10880
10881 case 0x59: // Binary data (two-byte uint16_t for n follow)
10882 {
10883 std::uint16_t len{};
10884 return get_number(input_format_t::cbor, len) &&
10885 get_binary(input_format_t::cbor, len, result);
10886 }
10887
10888 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10889 {
10890 std::uint32_t len{};
10891 return get_number(input_format_t::cbor, len) &&
10892 get_binary(input_format_t::cbor, len, result);
10893 }
10894
10895 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10896 {
10897 std::uint64_t len{};
10898 return get_number(input_format_t::cbor, len) &&
10899 get_binary(input_format_t::cbor, len, result);
10900 }
10901
10902 case 0x5F: // Binary data (indefinite length)
10903 {
10904 while (get() != 0xFF)
10905 {
10906 binary_t chunk;
10907 if (!get_cbor_binary(chunk))
10908 {
10909 return false;
10910 }
10911 result.insert(result.end(), chunk.begin(), chunk.end());
10912 }
10913 return true;
10914 }
10915
10916 default:
10917 {
10918 auto last_token = get_token_string();
10919 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10920 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));
10921 }
10922 }
10923 }
10924
10931 bool get_cbor_array(const std::size_t len,
10932 const cbor_tag_handler_t tag_handler)
10933 {
10934 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10935 {
10936 return false;
10937 }
10938
10939 if (len != detail::unknown_size())
10940 {
10941 for (std::size_t i = 0; i < len; ++i)
10942 {
10943 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10944 {
10945 return false;
10946 }
10947 }
10948 }
10949 else
10950 {
10951 while (get() != 0xFF)
10952 {
10953 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10954 {
10955 return false;
10956 }
10957 }
10958 }
10959
10960 return sax->end_array();
10961 }
10962
10969 bool get_cbor_object(const std::size_t len,
10970 const cbor_tag_handler_t tag_handler)
10971 {
10972 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10973 {
10974 return false;
10975 }
10976
10977 if (len != 0)
10978 {
10979 string_t key;
10980 if (len != detail::unknown_size())
10981 {
10982 for (std::size_t i = 0; i < len; ++i)
10983 {
10984 get();
10985 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10986 {
10987 return false;
10988 }
10989
10990 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10991 {
10992 return false;
10993 }
10994 key.clear();
10995 }
10996 }
10997 else
10998 {
10999 while (get() != 0xFF)
11000 {
11001 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
11002 {
11003 return false;
11004 }
11005
11006 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
11007 {
11008 return false;
11009 }
11010 key.clear();
11011 }
11012 }
11013 }
11014
11015 return sax->end_object();
11016 }
11017
11019 // MsgPack //
11021
11025 bool parse_msgpack_internal()
11026 {
11027 switch (get())
11028 {
11029 // EOF
11030 case char_traits<char_type>::eof():
11031 return unexpect_eof(input_format_t::msgpack, "value");
11032
11033 // positive fixint
11034 case 0x00:
11035 case 0x01:
11036 case 0x02:
11037 case 0x03:
11038 case 0x04:
11039 case 0x05:
11040 case 0x06:
11041 case 0x07:
11042 case 0x08:
11043 case 0x09:
11044 case 0x0A:
11045 case 0x0B:
11046 case 0x0C:
11047 case 0x0D:
11048 case 0x0E:
11049 case 0x0F:
11050 case 0x10:
11051 case 0x11:
11052 case 0x12:
11053 case 0x13:
11054 case 0x14:
11055 case 0x15:
11056 case 0x16:
11057 case 0x17:
11058 case 0x18:
11059 case 0x19:
11060 case 0x1A:
11061 case 0x1B:
11062 case 0x1C:
11063 case 0x1D:
11064 case 0x1E:
11065 case 0x1F:
11066 case 0x20:
11067 case 0x21:
11068 case 0x22:
11069 case 0x23:
11070 case 0x24:
11071 case 0x25:
11072 case 0x26:
11073 case 0x27:
11074 case 0x28:
11075 case 0x29:
11076 case 0x2A:
11077 case 0x2B:
11078 case 0x2C:
11079 case 0x2D:
11080 case 0x2E:
11081 case 0x2F:
11082 case 0x30:
11083 case 0x31:
11084 case 0x32:
11085 case 0x33:
11086 case 0x34:
11087 case 0x35:
11088 case 0x36:
11089 case 0x37:
11090 case 0x38:
11091 case 0x39:
11092 case 0x3A:
11093 case 0x3B:
11094 case 0x3C:
11095 case 0x3D:
11096 case 0x3E:
11097 case 0x3F:
11098 case 0x40:
11099 case 0x41:
11100 case 0x42:
11101 case 0x43:
11102 case 0x44:
11103 case 0x45:
11104 case 0x46:
11105 case 0x47:
11106 case 0x48:
11107 case 0x49:
11108 case 0x4A:
11109 case 0x4B:
11110 case 0x4C:
11111 case 0x4D:
11112 case 0x4E:
11113 case 0x4F:
11114 case 0x50:
11115 case 0x51:
11116 case 0x52:
11117 case 0x53:
11118 case 0x54:
11119 case 0x55:
11120 case 0x56:
11121 case 0x57:
11122 case 0x58:
11123 case 0x59:
11124 case 0x5A:
11125 case 0x5B:
11126 case 0x5C:
11127 case 0x5D:
11128 case 0x5E:
11129 case 0x5F:
11130 case 0x60:
11131 case 0x61:
11132 case 0x62:
11133 case 0x63:
11134 case 0x64:
11135 case 0x65:
11136 case 0x66:
11137 case 0x67:
11138 case 0x68:
11139 case 0x69:
11140 case 0x6A:
11141 case 0x6B:
11142 case 0x6C:
11143 case 0x6D:
11144 case 0x6E:
11145 case 0x6F:
11146 case 0x70:
11147 case 0x71:
11148 case 0x72:
11149 case 0x73:
11150 case 0x74:
11151 case 0x75:
11152 case 0x76:
11153 case 0x77:
11154 case 0x78:
11155 case 0x79:
11156 case 0x7A:
11157 case 0x7B:
11158 case 0x7C:
11159 case 0x7D:
11160 case 0x7E:
11161 case 0x7F:
11162 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
11163
11164 // fixmap
11165 case 0x80:
11166 case 0x81:
11167 case 0x82:
11168 case 0x83:
11169 case 0x84:
11170 case 0x85:
11171 case 0x86:
11172 case 0x87:
11173 case 0x88:
11174 case 0x89:
11175 case 0x8A:
11176 case 0x8B:
11177 case 0x8C:
11178 case 0x8D:
11179 case 0x8E:
11180 case 0x8F:
11181 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11182
11183 // fixarray
11184 case 0x90:
11185 case 0x91:
11186 case 0x92:
11187 case 0x93:
11188 case 0x94:
11189 case 0x95:
11190 case 0x96:
11191 case 0x97:
11192 case 0x98:
11193 case 0x99:
11194 case 0x9A:
11195 case 0x9B:
11196 case 0x9C:
11197 case 0x9D:
11198 case 0x9E:
11199 case 0x9F:
11200 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11201
11202 // fixstr
11203 case 0xA0:
11204 case 0xA1:
11205 case 0xA2:
11206 case 0xA3:
11207 case 0xA4:
11208 case 0xA5:
11209 case 0xA6:
11210 case 0xA7:
11211 case 0xA8:
11212 case 0xA9:
11213 case 0xAA:
11214 case 0xAB:
11215 case 0xAC:
11216 case 0xAD:
11217 case 0xAE:
11218 case 0xAF:
11219 case 0xB0:
11220 case 0xB1:
11221 case 0xB2:
11222 case 0xB3:
11223 case 0xB4:
11224 case 0xB5:
11225 case 0xB6:
11226 case 0xB7:
11227 case 0xB8:
11228 case 0xB9:
11229 case 0xBA:
11230 case 0xBB:
11231 case 0xBC:
11232 case 0xBD:
11233 case 0xBE:
11234 case 0xBF:
11235 case 0xD9: // str 8
11236 case 0xDA: // str 16
11237 case 0xDB: // str 32
11238 {
11239 string_t s;
11240 return get_msgpack_string(s) && sax->string(s);
11241 }
11242
11243 case 0xC0: // nil
11244 return sax->null();
11245
11246 case 0xC2: // false
11247 return sax->boolean(false);
11248
11249 case 0xC3: // true
11250 return sax->boolean(true);
11251
11252 case 0xC4: // bin 8
11253 case 0xC5: // bin 16
11254 case 0xC6: // bin 32
11255 case 0xC7: // ext 8
11256 case 0xC8: // ext 16
11257 case 0xC9: // ext 32
11258 case 0xD4: // fixext 1
11259 case 0xD5: // fixext 2
11260 case 0xD6: // fixext 4
11261 case 0xD7: // fixext 8
11262 case 0xD8: // fixext 16
11263 {
11264 binary_t b;
11265 return get_msgpack_binary(b) && sax->binary(b);
11266 }
11267
11268 case 0xCA: // float 32
11269 {
11270 float number{};
11271 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11272 }
11273
11274 case 0xCB: // float 64
11275 {
11276 double number{};
11277 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11278 }
11279
11280 case 0xCC: // uint 8
11281 {
11282 std::uint8_t number{};
11283 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11284 }
11285
11286 case 0xCD: // uint 16
11287 {
11288 std::uint16_t number{};
11289 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11290 }
11291
11292 case 0xCE: // uint 32
11293 {
11294 std::uint32_t number{};
11295 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11296 }
11297
11298 case 0xCF: // uint 64
11299 {
11300 std::uint64_t number{};
11301 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11302 }
11303
11304 case 0xD0: // int 8
11305 {
11306 std::int8_t number{};
11307 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11308 }
11309
11310 case 0xD1: // int 16
11311 {
11312 std::int16_t number{};
11313 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11314 }
11315
11316 case 0xD2: // int 32
11317 {
11318 std::int32_t number{};
11319 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11320 }
11321
11322 case 0xD3: // int 64
11323 {
11324 std::int64_t number{};
11325 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11326 }
11327
11328 case 0xDC: // array 16
11329 {
11330 std::uint16_t len{};
11331 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
11332 }
11333
11334 case 0xDD: // array 32
11335 {
11336 std::uint32_t len{};
11337 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
11338 }
11339
11340 case 0xDE: // map 16
11341 {
11342 std::uint16_t len{};
11343 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
11344 }
11345
11346 case 0xDF: // map 32
11347 {
11348 std::uint32_t len{};
11349 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
11350 }
11351
11352 // negative fixint
11353 case 0xE0:
11354 case 0xE1:
11355 case 0xE2:
11356 case 0xE3:
11357 case 0xE4:
11358 case 0xE5:
11359 case 0xE6:
11360 case 0xE7:
11361 case 0xE8:
11362 case 0xE9:
11363 case 0xEA:
11364 case 0xEB:
11365 case 0xEC:
11366 case 0xED:
11367 case 0xEE:
11368 case 0xEF:
11369 case 0xF0:
11370 case 0xF1:
11371 case 0xF2:
11372 case 0xF3:
11373 case 0xF4:
11374 case 0xF5:
11375 case 0xF6:
11376 case 0xF7:
11377 case 0xF8:
11378 case 0xF9:
11379 case 0xFA:
11380 case 0xFB:
11381 case 0xFC:
11382 case 0xFD:
11383 case 0xFE:
11384 case 0xFF:
11385 return sax->number_integer(static_cast<std::int8_t>(current));
11386
11387 default: // anything else
11388 {
11389 auto last_token = get_token_string();
11390 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11391 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
11392 }
11393 }
11394 }
11395
11406 bool get_msgpack_string(string_t& result)
11407 {
11408 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
11409 {
11410 return false;
11411 }
11412
11413 switch (current)
11414 {
11415 // fixstr
11416 case 0xA0:
11417 case 0xA1:
11418 case 0xA2:
11419 case 0xA3:
11420 case 0xA4:
11421 case 0xA5:
11422 case 0xA6:
11423 case 0xA7:
11424 case 0xA8:
11425 case 0xA9:
11426 case 0xAA:
11427 case 0xAB:
11428 case 0xAC:
11429 case 0xAD:
11430 case 0xAE:
11431 case 0xAF:
11432 case 0xB0:
11433 case 0xB1:
11434 case 0xB2:
11435 case 0xB3:
11436 case 0xB4:
11437 case 0xB5:
11438 case 0xB6:
11439 case 0xB7:
11440 case 0xB8:
11441 case 0xB9:
11442 case 0xBA:
11443 case 0xBB:
11444 case 0xBC:
11445 case 0xBD:
11446 case 0xBE:
11447 case 0xBF:
11448 {
11449 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
11450 }
11451
11452 case 0xD9: // str 8
11453 {
11454 std::uint8_t len{};
11455 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11456 }
11457
11458 case 0xDA: // str 16
11459 {
11460 std::uint16_t len{};
11461 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11462 }
11463
11464 case 0xDB: // str 32
11465 {
11466 std::uint32_t len{};
11467 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11468 }
11469
11470 default:
11471 {
11472 auto last_token = get_token_string();
11473 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11474 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
11475 }
11476 }
11477 }
11478
11489 bool get_msgpack_binary(binary_t& result)
11490 {
11491 // helper function to set the subtype
11492 auto assign_and_return_true = [&result](std::int8_t subtype)
11493 {
11494 result.set_subtype(static_cast<std::uint8_t>(subtype));
11495 return true;
11496 };
11497
11498 switch (current)
11499 {
11500 case 0xC4: // bin 8
11501 {
11502 std::uint8_t len{};
11503 return get_number(input_format_t::msgpack, len) &&
11504 get_binary(input_format_t::msgpack, len, result);
11505 }
11506
11507 case 0xC5: // bin 16
11508 {
11509 std::uint16_t len{};
11510 return get_number(input_format_t::msgpack, len) &&
11511 get_binary(input_format_t::msgpack, len, result);
11512 }
11513
11514 case 0xC6: // bin 32
11515 {
11516 std::uint32_t len{};
11517 return get_number(input_format_t::msgpack, len) &&
11518 get_binary(input_format_t::msgpack, len, result);
11519 }
11520
11521 case 0xC7: // ext 8
11522 {
11523 std::uint8_t len{};
11524 std::int8_t subtype{};
11525 return get_number(input_format_t::msgpack, len) &&
11526 get_number(input_format_t::msgpack, subtype) &&
11527 get_binary(input_format_t::msgpack, len, result) &&
11528 assign_and_return_true(subtype);
11529 }
11530
11531 case 0xC8: // ext 16
11532 {
11533 std::uint16_t len{};
11534 std::int8_t subtype{};
11535 return get_number(input_format_t::msgpack, len) &&
11536 get_number(input_format_t::msgpack, subtype) &&
11537 get_binary(input_format_t::msgpack, len, result) &&
11538 assign_and_return_true(subtype);
11539 }
11540
11541 case 0xC9: // ext 32
11542 {
11543 std::uint32_t len{};
11544 std::int8_t subtype{};
11545 return get_number(input_format_t::msgpack, len) &&
11546 get_number(input_format_t::msgpack, subtype) &&
11547 get_binary(input_format_t::msgpack, len, result) &&
11548 assign_and_return_true(subtype);
11549 }
11550
11551 case 0xD4: // fixext 1
11552 {
11553 std::int8_t subtype{};
11554 return get_number(input_format_t::msgpack, subtype) &&
11555 get_binary(input_format_t::msgpack, 1, result) &&
11556 assign_and_return_true(subtype);
11557 }
11558
11559 case 0xD5: // fixext 2
11560 {
11561 std::int8_t subtype{};
11562 return get_number(input_format_t::msgpack, subtype) &&
11563 get_binary(input_format_t::msgpack, 2, result) &&
11564 assign_and_return_true(subtype);
11565 }
11566
11567 case 0xD6: // fixext 4
11568 {
11569 std::int8_t subtype{};
11570 return get_number(input_format_t::msgpack, subtype) &&
11571 get_binary(input_format_t::msgpack, 4, result) &&
11572 assign_and_return_true(subtype);
11573 }
11574
11575 case 0xD7: // fixext 8
11576 {
11577 std::int8_t subtype{};
11578 return get_number(input_format_t::msgpack, subtype) &&
11579 get_binary(input_format_t::msgpack, 8, result) &&
11580 assign_and_return_true(subtype);
11581 }
11582
11583 case 0xD8: // fixext 16
11584 {
11585 std::int8_t subtype{};
11586 return get_number(input_format_t::msgpack, subtype) &&
11587 get_binary(input_format_t::msgpack, 16, result) &&
11588 assign_and_return_true(subtype);
11589 }
11590
11591 default: // LCOV_EXCL_LINE
11592 return false; // LCOV_EXCL_LINE
11593 }
11594 }
11595
11600 bool get_msgpack_array(const std::size_t len)
11601 {
11602 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
11603 {
11604 return false;
11605 }
11606
11607 for (std::size_t i = 0; i < len; ++i)
11608 {
11609 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11610 {
11611 return false;
11612 }
11613 }
11614
11615 return sax->end_array();
11616 }
11617
11622 bool get_msgpack_object(const std::size_t len)
11623 {
11624 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
11625 {
11626 return false;
11627 }
11628
11629 string_t key;
11630 for (std::size_t i = 0; i < len; ++i)
11631 {
11632 get();
11633 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
11634 {
11635 return false;
11636 }
11637
11638 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11639 {
11640 return false;
11641 }
11642 key.clear();
11643 }
11644
11645 return sax->end_object();
11646 }
11647
11649 // UBJSON //
11651
11659 bool parse_ubjson_internal(const bool get_char = true)
11660 {
11661 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11662 }
11663
11678 bool get_ubjson_string(string_t& result, const bool get_char = true)
11679 {
11680 if (get_char)
11681 {
11682 get(); // TODO(niels): may we ignore N here?
11683 }
11684
11685 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11686 {
11687 return false;
11688 }
11689
11690 switch (current)
11691 {
11692 case 'U':
11693 {
11694 std::uint8_t len{};
11695 return get_number(input_format, len) && get_string(input_format, len, result);
11696 }
11697
11698 case 'i':
11699 {
11700 std::int8_t len{};
11701 return get_number(input_format, len) && get_string(input_format, len, result);
11702 }
11703
11704 case 'I':
11705 {
11706 std::int16_t len{};
11707 return get_number(input_format, len) && get_string(input_format, len, result);
11708 }
11709
11710 case 'l':
11711 {
11712 std::int32_t len{};
11713 return get_number(input_format, len) && get_string(input_format, len, result);
11714 }
11715
11716 case 'L':
11717 {
11718 std::int64_t len{};
11719 return get_number(input_format, len) && get_string(input_format, len, result);
11720 }
11721
11722 case 'u':
11723 {
11724 if (input_format != input_format_t::bjdata)
11725 {
11726 break;
11727 }
11728 std::uint16_t len{};
11729 return get_number(input_format, len) && get_string(input_format, len, result);
11730 }
11731
11732 case 'm':
11733 {
11734 if (input_format != input_format_t::bjdata)
11735 {
11736 break;
11737 }
11738 std::uint32_t len{};
11739 return get_number(input_format, len) && get_string(input_format, len, result);
11740 }
11741
11742 case 'M':
11743 {
11744 if (input_format != input_format_t::bjdata)
11745 {
11746 break;
11747 }
11748 std::uint64_t len{};
11749 return get_number(input_format, len) && get_string(input_format, len, result);
11750 }
11751
11752 default:
11753 break;
11754 }
11755 auto last_token = get_token_string();
11756 std::string message;
11757
11758 if (input_format != input_format_t::bjdata)
11759 {
11760 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11761 }
11762 else
11763 {
11764 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11765 }
11766 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11767 }
11768
11773 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11774 {
11775 std::pair<std::size_t, char_int_type> size_and_type;
11776 size_t dimlen = 0;
11777 bool no_ndarray = true;
11778
11779 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11780 {
11781 return false;
11782 }
11783
11784 if (size_and_type.first != npos)
11785 {
11786 if (size_and_type.second != 0)
11787 {
11788 if (size_and_type.second != 'N')
11789 {
11790 for (std::size_t i = 0; i < size_and_type.first; ++i)
11791 {
11792 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11793 {
11794 return false;
11795 }
11796 dim.push_back(dimlen);
11797 }
11798 }
11799 }
11800 else
11801 {
11802 for (std::size_t i = 0; i < size_and_type.first; ++i)
11803 {
11804 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11805 {
11806 return false;
11807 }
11808 dim.push_back(dimlen);
11809 }
11810 }
11811 }
11812 else
11813 {
11814 while (current != ']')
11815 {
11816 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11817 {
11818 return false;
11819 }
11820 dim.push_back(dimlen);
11821 get_ignore_noop();
11822 }
11823 }
11824 return true;
11825 }
11826
11838 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11839 {
11840 if (prefix == 0)
11841 {
11842 prefix = get_ignore_noop();
11843 }
11844
11845 switch (prefix)
11846 {
11847 case 'U':
11848 {
11849 std::uint8_t number{};
11850 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11851 {
11852 return false;
11853 }
11854 result = static_cast<std::size_t>(number);
11855 return true;
11856 }
11857
11858 case 'i':
11859 {
11860 std::int8_t number{};
11861 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11862 {
11863 return false;
11864 }
11865 if (number < 0)
11866 {
11867 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11868 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11869 }
11870 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11871 return true;
11872 }
11873
11874 case 'I':
11875 {
11876 std::int16_t number{};
11877 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11878 {
11879 return false;
11880 }
11881 if (number < 0)
11882 {
11883 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11884 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11885 }
11886 result = static_cast<std::size_t>(number);
11887 return true;
11888 }
11889
11890 case 'l':
11891 {
11892 std::int32_t number{};
11893 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11894 {
11895 return false;
11896 }
11897 if (number < 0)
11898 {
11899 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11900 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11901 }
11902 result = static_cast<std::size_t>(number);
11903 return true;
11904 }
11905
11906 case 'L':
11907 {
11908 std::int64_t number{};
11909 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11910 {
11911 return false;
11912 }
11913 if (number < 0)
11914 {
11915 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11916 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11917 }
11918 if (!value_in_range_of<std::size_t>(number))
11919 {
11920 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11921 exception_message(input_format, "integer value overflow", "size"), nullptr));
11922 }
11923 result = static_cast<std::size_t>(number);
11924 return true;
11925 }
11926
11927 case 'u':
11928 {
11929 if (input_format != input_format_t::bjdata)
11930 {
11931 break;
11932 }
11933 std::uint16_t number{};
11934 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11935 {
11936 return false;
11937 }
11938 result = static_cast<std::size_t>(number);
11939 return true;
11940 }
11941
11942 case 'm':
11943 {
11944 if (input_format != input_format_t::bjdata)
11945 {
11946 break;
11947 }
11948 std::uint32_t number{};
11949 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11950 {
11951 return false;
11952 }
11953 result = conditional_static_cast<std::size_t>(number);
11954 return true;
11955 }
11956
11957 case 'M':
11958 {
11959 if (input_format != input_format_t::bjdata)
11960 {
11961 break;
11962 }
11963 std::uint64_t number{};
11964 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11965 {
11966 return false;
11967 }
11968 if (!value_in_range_of<std::size_t>(number))
11969 {
11970 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11971 exception_message(input_format, "integer value overflow", "size"), nullptr));
11972 }
11974 return true;
11975 }
11976
11977 case '[':
11978 {
11979 if (input_format != input_format_t::bjdata)
11980 {
11981 break;
11982 }
11983 if (is_ndarray) // ndarray dimensional vector can only contain integers and cannot embed another array
11984 {
11985 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));
11986 }
11987 std::vector<size_t> dim;
11988 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11989 {
11990 return false;
11991 }
11992 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11993 {
11994 result = dim.at(dim.size() - 1);
11995 return true;
11996 }
11997 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11998 {
11999 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
12000 {
12001 if ( i == 0 )
12002 {
12003 result = 0;
12004 return true;
12005 }
12006 }
12007
12008 string_t key = "_ArraySize_";
12009 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
12010 {
12011 return false;
12012 }
12013 result = 1;
12014 for (auto i : dim)
12015 {
12016 // Pre-multiplication overflow check: if i > 0 and result > SIZE_MAX/i, then result*i would overflow.
12017 // This check must happen before multiplication since overflow detection after the fact is unreliable
12018 // as modular arithmetic can produce any value, not just 0 or SIZE_MAX.
12019 if (JSON_HEDLEY_UNLIKELY(i > 0 && result > (std::numeric_limits<std::size_t>::max)() / i))
12020 {
12021 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));
12022 }
12023 result *= i;
12024 // Additional post-multiplication check to catch any edge cases the pre-check might miss
12025 if (result == 0 || result == npos)
12026 {
12027 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));
12028 }
12029 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
12030 {
12031 return false;
12032 }
12033 }
12034 is_ndarray = true;
12035 return sax->end_array();
12036 }
12037 result = 0;
12038 return true;
12039 }
12040
12041 default:
12042 break;
12043 }
12044 auto last_token = get_token_string();
12045 std::string message;
12046
12047 if (input_format != input_format_t::bjdata)
12048 {
12049 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
12050 }
12051 else
12052 {
12053 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
12054 }
12055 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
12056 }
12057
12069 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
12070 {
12071 result.first = npos; // size
12072 result.second = 0; // type
12073 bool is_ndarray = false;
12074
12075 get_ignore_noop();
12076
12077 if (current == '$')
12078 {
12079 result.second = get(); // must not ignore 'N', because 'N' maybe the type
12080 if (input_format == input_format_t::bjdata
12081 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
12082 {
12083 auto last_token = get_token_string();
12084 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12085 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
12086 }
12087
12088 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
12089 {
12090 return false;
12091 }
12092
12093 get_ignore_noop();
12094 if (JSON_HEDLEY_UNLIKELY(current != '#'))
12095 {
12096 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
12097 {
12098 return false;
12099 }
12100 auto last_token = get_token_string();
12101 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12102 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
12103 }
12104
12105 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12106 if (input_format == input_format_t::bjdata && is_ndarray)
12107 {
12108 if (inside_ndarray)
12109 {
12110 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12111 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
12112 }
12113 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
12114 }
12115 return is_error;
12116 }
12117
12118 if (current == '#')
12119 {
12120 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12121 if (input_format == input_format_t::bjdata && is_ndarray)
12122 {
12123 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12124 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
12125 }
12126 return is_error;
12127 }
12128
12129 return true;
12130 }
12131
12136 bool get_ubjson_value(const char_int_type prefix)
12137 {
12138 switch (prefix)
12139 {
12140 case char_traits<char_type>::eof(): // EOF
12141 return unexpect_eof(input_format, "value");
12142
12143 case 'T': // true
12144 return sax->boolean(true);
12145 case 'F': // false
12146 return sax->boolean(false);
12147
12148 case 'Z': // null
12149 return sax->null();
12150
12151 case 'B': // byte
12152 {
12153 if (input_format != input_format_t::bjdata)
12154 {
12155 break;
12156 }
12157 std::uint8_t number{};
12158 return get_number(input_format, number) && sax->number_unsigned(number);
12159 }
12160
12161 case 'U':
12162 {
12163 std::uint8_t number{};
12164 return get_number(input_format, number) && sax->number_unsigned(number);
12165 }
12166
12167 case 'i':
12168 {
12169 std::int8_t number{};
12170 return get_number(input_format, number) && sax->number_integer(number);
12171 }
12172
12173 case 'I':
12174 {
12175 std::int16_t number{};
12176 return get_number(input_format, number) && sax->number_integer(number);
12177 }
12178
12179 case 'l':
12180 {
12181 std::int32_t number{};
12182 return get_number(input_format, number) && sax->number_integer(number);
12183 }
12184
12185 case 'L':
12186 {
12187 std::int64_t number{};
12188 return get_number(input_format, number) && sax->number_integer(number);
12189 }
12190
12191 case 'u':
12192 {
12193 if (input_format != input_format_t::bjdata)
12194 {
12195 break;
12196 }
12197 std::uint16_t number{};
12198 return get_number(input_format, number) && sax->number_unsigned(number);
12199 }
12200
12201 case 'm':
12202 {
12203 if (input_format != input_format_t::bjdata)
12204 {
12205 break;
12206 }
12207 std::uint32_t number{};
12208 return get_number(input_format, number) && sax->number_unsigned(number);
12209 }
12210
12211 case 'M':
12212 {
12213 if (input_format != input_format_t::bjdata)
12214 {
12215 break;
12216 }
12217 std::uint64_t number{};
12218 return get_number(input_format, number) && sax->number_unsigned(number);
12219 }
12220
12221 case 'h':
12222 {
12223 if (input_format != input_format_t::bjdata)
12224 {
12225 break;
12226 }
12227 const auto byte1_raw = get();
12228 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12229 {
12230 return false;
12231 }
12232 const auto byte2_raw = get();
12233 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12234 {
12235 return false;
12236 }
12237
12238 const auto byte1 = static_cast<unsigned char>(byte1_raw);
12239 const auto byte2 = static_cast<unsigned char>(byte2_raw);
12240
12241 // Code from RFC 7049, Appendix D, Figure 3:
12242 // As half-precision floating-point numbers were only added
12243 // to IEEE 754 in 2008, today's programming platforms often
12244 // still only have limited support for them. It is very
12245 // easy to include at least decoding support for them even
12246 // without such support. An example of a small decoder for
12247 // half-precision floating-point numbers in the C language
12248 // is shown in Fig. 3.
12249 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
12250 const double val = [&half]
12251 {
12252 const int exp = (half >> 10u) & 0x1Fu;
12253 const unsigned int mant = half & 0x3FFu;
12254 JSON_ASSERT(0 <= exp&& exp <= 32);
12255 JSON_ASSERT(mant <= 1024);
12256 switch (exp)
12257 {
12258 case 0:
12259 return std::ldexp(mant, -24);
12260 case 31:
12261 return (mant == 0)
12262 ? std::numeric_limits<double>::infinity()
12263 : std::numeric_limits<double>::quiet_NaN();
12264 default:
12265 return std::ldexp(mant + 1024, exp - 25);
12266 }
12267 }();
12268 return sax->number_float((half & 0x8000u) != 0
12269 ? static_cast<number_float_t>(-val)
12270 : static_cast<number_float_t>(val), "");
12271 }
12272
12273 case 'd':
12274 {
12275 float number{};
12276 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12277 }
12278
12279 case 'D':
12280 {
12281 double number{};
12282 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12283 }
12284
12285 case 'H':
12286 {
12287 return get_ubjson_high_precision_number();
12288 }
12289
12290 case 'C': // char
12291 {
12292 get();
12293 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
12294 {
12295 return false;
12296 }
12297 if (JSON_HEDLEY_UNLIKELY(current > 127))
12298 {
12299 auto last_token = get_token_string();
12300 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
12301 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
12302 }
12303 string_t s(1, static_cast<typename string_t::value_type>(current));
12304 return sax->string(s);
12305 }
12306
12307 case 'S': // string
12308 {
12309 string_t s;
12310 return get_ubjson_string(s) && sax->string(s);
12311 }
12312
12313 case '[': // array
12314 return get_ubjson_array();
12315
12316 case '{': // object
12317 return get_ubjson_object();
12318
12319 default: // anything else
12320 break;
12321 }
12322 auto last_token = get_token_string();
12323 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));
12324 }
12325
12329 bool get_ubjson_array()
12330 {
12331 std::pair<std::size_t, char_int_type> size_and_type;
12332 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12333 {
12334 return false;
12335 }
12336
12337 // 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):
12338 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
12339
12340 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12341 {
12342 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
12343 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)
12344 {
12345 return p.first < t;
12346 });
12347 string_t key = "_ArrayType_";
12348 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
12349 {
12350 auto last_token = get_token_string();
12351 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12352 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
12353 }
12354
12355 string_t type = it->second; // sax->string() takes a reference
12356 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
12357 {
12358 return false;
12359 }
12360
12361 if (size_and_type.second == 'C' || size_and_type.second == 'B')
12362 {
12363 size_and_type.second = 'U';
12364 }
12365
12366 key = "_ArrayData_";
12367 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
12368 {
12369 return false;
12370 }
12371
12372 for (std::size_t i = 0; i < size_and_type.first; ++i)
12373 {
12374 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12375 {
12376 return false;
12377 }
12378 }
12379
12380 return (sax->end_array() && sax->end_object());
12381 }
12382
12383 // If BJData type marker is 'B' decode as binary
12384 if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second == 'B')
12385 {
12386 binary_t result;
12387 return get_binary(input_format, size_and_type.first, result) && sax->binary(result);
12388 }
12389
12390 if (size_and_type.first != npos)
12391 {
12392 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
12393 {
12394 return false;
12395 }
12396
12397 if (size_and_type.second != 0)
12398 {
12399 if (size_and_type.second != 'N')
12400 {
12401 for (std::size_t i = 0; i < size_and_type.first; ++i)
12402 {
12403 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12404 {
12405 return false;
12406 }
12407 }
12408 }
12409 }
12410 else
12411 {
12412 for (std::size_t i = 0; i < size_and_type.first; ++i)
12413 {
12414 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12415 {
12416 return false;
12417 }
12418 }
12419 }
12420 }
12421 else
12422 {
12423 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
12424 {
12425 return false;
12426 }
12427
12428 while (current != ']')
12429 {
12430 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
12431 {
12432 return false;
12433 }
12434 get_ignore_noop();
12435 }
12436 }
12437
12438 return sax->end_array();
12439 }
12440
12444 bool get_ubjson_object()
12445 {
12446 std::pair<std::size_t, char_int_type> size_and_type;
12447 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12448 {
12449 return false;
12450 }
12451
12452 // do not accept ND-array size in objects in BJData
12453 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12454 {
12455 auto last_token = get_token_string();
12456 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12457 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
12458 }
12459
12460 string_t key;
12461 if (size_and_type.first != npos)
12462 {
12463 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
12464 {
12465 return false;
12466 }
12467
12468 if (size_and_type.second != 0)
12469 {
12470 for (std::size_t i = 0; i < size_and_type.first; ++i)
12471 {
12472 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12473 {
12474 return false;
12475 }
12476 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12477 {
12478 return false;
12479 }
12480 key.clear();
12481 }
12482 }
12483 else
12484 {
12485 for (std::size_t i = 0; i < size_and_type.first; ++i)
12486 {
12487 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12488 {
12489 return false;
12490 }
12491 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12492 {
12493 return false;
12494 }
12495 key.clear();
12496 }
12497 }
12498 }
12499 else
12500 {
12501 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
12502 {
12503 return false;
12504 }
12505
12506 while (current != '}')
12507 {
12508 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
12509 {
12510 return false;
12511 }
12512 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12513 {
12514 return false;
12515 }
12516 get_ignore_noop();
12517 key.clear();
12518 }
12519 }
12520
12521 return sax->end_object();
12522 }
12523
12524 // Note, no reader for UBJSON binary types is implemented because they do
12525 // not exist
12526
12527 bool get_ubjson_high_precision_number()
12528 {
12529 // get the size of the following number string
12530 std::size_t size{};
12531 bool no_ndarray = true;
12532 auto res = get_ubjson_size_value(size, no_ndarray);
12533 if (JSON_HEDLEY_UNLIKELY(!res))
12534 {
12535 return res;
12536 }
12537
12538 // get number string
12539 std::vector<char> number_vector;
12540 for (std::size_t i = 0; i < size; ++i)
12541 {
12542 get();
12543 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12544 {
12545 return false;
12546 }
12547 number_vector.push_back(static_cast<char>(current));
12548 }
12549
12550 // parse number string
12551 using ia_type = decltype(detail::input_adapter(number_vector));
12552 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
12553 const auto result_number = number_lexer.scan();
12554 const auto number_string = number_lexer.get_token_string();
12555 const auto result_remainder = number_lexer.scan();
12556
12557 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
12558
12559 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
12560 {
12561 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12562 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12563 }
12564
12565 switch (result_number)
12566 {
12567 case token_type::value_integer:
12568 return sax->number_integer(number_lexer.get_number_integer());
12569 case token_type::value_unsigned:
12570 return sax->number_unsigned(number_lexer.get_number_unsigned());
12571 case token_type::value_float:
12572 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
12573 case token_type::uninitialized:
12574 case token_type::literal_true:
12575 case token_type::literal_false:
12576 case token_type::literal_null:
12577 case token_type::value_string:
12578 case token_type::begin_array:
12579 case token_type::begin_object:
12580 case token_type::end_array:
12581 case token_type::end_object:
12582 case token_type::name_separator:
12583 case token_type::value_separator:
12584 case token_type::parse_error:
12585 case token_type::end_of_input:
12586 case token_type::literal_or_value:
12587 default:
12588 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12589 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12590 }
12591 }
12592
12594 // Utility functions //
12596
12606 char_int_type get()
12607 {
12608 ++chars_read;
12609 return current = ia.get_character();
12610 }
12611
12620 template<class T>
12621 bool get_to(T& dest, const input_format_t format, const char* context)
12622 {
12623 auto new_chars_read = ia.get_elements(&dest);
12624 chars_read += new_chars_read;
12625 if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T)))
12626 {
12627 // in case of failure, advance position by 1 to report the failing location
12628 ++chars_read;
12629 sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12630 return false;
12631 }
12632 return true;
12633 }
12634
12638 char_int_type get_ignore_noop()
12639 {
12640 do
12641 {
12642 get();
12643 }
12644 while (current == 'N');
12645
12646 return current;
12647 }
12648
12649 template<class NumberType>
12650 static void byte_swap(NumberType& number)
12651 {
12652 constexpr std::size_t sz = sizeof(number);
12653#ifdef __cpp_lib_byteswap
12654 if constexpr (sz == 1)
12655 {
12656 return;
12657 }
12658 else if constexpr(std::is_integral_v<NumberType>)
12659 {
12660 number = std::byteswap(number);
12661 return;
12662 }
12663 else
12664 {
12665#endif
12666 auto* ptr = reinterpret_cast<std::uint8_t*>(&number);
12667 for (std::size_t i = 0; i < sz / 2; ++i)
12668 {
12669 std::swap(ptr[i], ptr[sz - i - 1]);
12670 }
12671#ifdef __cpp_lib_byteswap
12672 }
12673#endif
12674 }
12675
12676 /*
12677 @brief read a number from the input
12678
12679 @tparam NumberType the type of the number
12680 @param[in] format the current format (for diagnostics)
12681 @param[out] result number of type @a NumberType
12682
12683 @return whether conversion completed
12684
12685 @note This function needs to respect the system's endianness, because
12686 bytes in CBOR, MessagePack, and UBJSON are stored in network order
12687 (big endian) and therefore need reordering on little endian systems.
12688 On the other hand, BSON and BJData use little endian and should reorder
12689 on big endian systems.
12690 */
12691 template<typename NumberType, bool InputIsLittleEndian = false>
12692 bool get_number(const input_format_t format, NumberType& result)
12693 {
12694 // read in the original format
12695
12696 if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number")))
12697 {
12698 return false;
12699 }
12700 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
12701 {
12702 byte_swap(result);
12703 }
12704 return true;
12705 }
12706
12721 template<typename NumberType>
12722 bool get_string(const input_format_t format,
12723 const NumberType len,
12724 string_t& result)
12725 {
12726 bool success = true;
12727 for (NumberType i = 0; i < len; i++)
12728 {
12729 get();
12730 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
12731 {
12732 success = false;
12733 break;
12734 }
12735 result.push_back(static_cast<typename string_t::value_type>(current));
12736 }
12737 return success;
12738 }
12739
12754 template<typename NumberType>
12755 bool get_binary(const input_format_t format,
12756 const NumberType len,
12757 binary_t& result)
12758 {
12759 bool success = true;
12760 for (NumberType i = 0; i < len; i++)
12761 {
12762 get();
12763 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12764 {
12765 success = false;
12766 break;
12767 }
12768 result.push_back(static_cast<std::uint8_t>(current));
12769 }
12770 return success;
12771 }
12772
12779 bool unexpect_eof(const input_format_t format, const char* context) const
12780 {
12781 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12782 {
12783 return sax->parse_error(chars_read, "<end of file>",
12784 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12785 }
12786 return true;
12787 }
12788
12792 std::string get_token_string() const
12793 {
12794 std::array<char, 3> cr{{}};
12795 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12796 return std::string{cr.data()};
12797 }
12798
12805 std::string exception_message(const input_format_t format,
12806 const std::string& detail,
12807 const std::string& context) const
12808 {
12809 std::string error_msg = "syntax error while parsing ";
12810
12811 switch (format)
12812 {
12813 case input_format_t::cbor:
12814 error_msg += "CBOR";
12815 break;
12816
12817 case input_format_t::msgpack:
12818 error_msg += "MessagePack";
12819 break;
12820
12821 case input_format_t::ubjson:
12822 error_msg += "UBJSON";
12823 break;
12824
12825 case input_format_t::bson:
12826 error_msg += "BSON";
12827 break;
12828
12829 case input_format_t::bjdata:
12830 error_msg += "BJData";
12831 break;
12832
12833 case input_format_t::json: // LCOV_EXCL_LINE
12834 default: // LCOV_EXCL_LINE
12835 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12836 }
12837
12838 return concat(error_msg, ' ', context, ": ", detail);
12839 }
12840
12841 private:
12842 static JSON_INLINE_VARIABLE constexpr std::size_t npos = detail::unknown_size();
12843
12845 InputAdapterType ia;
12846
12848 char_int_type current = char_traits<char_type>::eof();
12849
12851 std::size_t chars_read = 0;
12852
12854 const bool is_little_endian = little_endianness();
12855
12857 const input_format_t input_format = input_format_t::json;
12858
12860 json_sax_t* sax = nullptr;
12861
12862 // excluded markers in bjdata optimized type
12863#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12864 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12865
12866#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12867 make_array<bjd_type>( \
12868 bjd_type{'B', "byte"}, \
12869 bjd_type{'C', "char"}, \
12870 bjd_type{'D', "double"}, \
12871 bjd_type{'I', "int16"}, \
12872 bjd_type{'L', "int64"}, \
12873 bjd_type{'M', "uint64"}, \
12874 bjd_type{'U', "uint8"}, \
12875 bjd_type{'d', "single"}, \
12876 bjd_type{'i', "int8"}, \
12877 bjd_type{'l', "int32"}, \
12878 bjd_type{'m', "uint32"}, \
12879 bjd_type{'u', "uint16"})
12880
12882 // lookup tables
12883 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12884 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12886
12887 using bjd_type = std::pair<char_int_type, string_t>;
12888 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12889 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12891
12892#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12893#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12894};
12895
12896#ifndef JSON_HAS_CPP_17
12897 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12898 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12899#endif
12900
12901} // namespace detail
12903
12904// #include <nlohmann/detail/input/input_adapters.hpp>
12905
12906// #include <nlohmann/detail/input/lexer.hpp>
12907
12908// #include <nlohmann/detail/input/parser.hpp>
12909// __ _____ _____ _____
12910// __| | __| | | | JSON for Modern C++
12911// | | |__ | | | | | | version 3.12.0
12912// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12913//
12914// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
12915// SPDX-License-Identifier: MIT
12916
12917
12918
12919#include <cmath> // isfinite
12920#include <cstdint> // uint8_t
12921#include <functional> // function
12922#include <string> // string
12923#include <utility> // move
12924#include <vector> // vector
12925
12926// #include <nlohmann/detail/exceptions.hpp>
12927
12928// #include <nlohmann/detail/input/input_adapters.hpp>
12929
12930// #include <nlohmann/detail/input/json_sax.hpp>
12931
12932// #include <nlohmann/detail/input/lexer.hpp>
12933
12934// #include <nlohmann/detail/macro_scope.hpp>
12935
12936// #include <nlohmann/detail/meta/is_sax.hpp>
12937
12938// #include <nlohmann/detail/string_concat.hpp>
12939
12940// #include <nlohmann/detail/value_t.hpp>
12941
12942
12944namespace detail
12945{
12947// parser //
12949
12950enum class parse_event_t : std::uint8_t
12951{
12955 object_end,
12959 array_end,
12961 key,
12963 value
12964};
12965
12966template<typename BasicJsonType>
12968 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12969
12975template<typename BasicJsonType, typename InputAdapterType>
12977{
12978 using number_integer_t = typename BasicJsonType::number_integer_t;
12979 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12980 using number_float_t = typename BasicJsonType::number_float_t;
12981 using string_t = typename BasicJsonType::string_t;
12983 using token_type = typename lexer_t::token_type;
12984
12985 public:
12987 explicit parser(InputAdapterType&& adapter,
12989 const bool allow_exceptions_ = true,
12990 const bool ignore_comments = false,
12991 const bool ignore_trailing_commas_ = false)
12992 : callback(std::move(cb))
12993 , m_lexer(std::move(adapter), ignore_comments)
12994 , allow_exceptions(allow_exceptions_)
12995 , ignore_trailing_commas(ignore_trailing_commas_)
12996 {
12997 // read first token
12998 get_token();
12999 }
13000
13011 void parse(const bool strict, BasicJsonType& result)
13012 {
13013 if (callback)
13014 {
13015 json_sax_dom_callback_parser<BasicJsonType, InputAdapterType> sdp(result, callback, allow_exceptions, &m_lexer);
13016 sax_parse_internal(&sdp);
13017
13018 // in strict mode, input must be completely read
13019 if (strict && (get_token() != token_type::end_of_input))
13020 {
13021 sdp.parse_error(m_lexer.get_position(),
13022 m_lexer.get_token_string(),
13023 parse_error::create(101, m_lexer.get_position(),
13024 exception_message(token_type::end_of_input, "value"), nullptr));
13025 }
13026
13027 // in case of an error, return a discarded value
13028 if (sdp.is_errored())
13029 {
13030 result = value_t::discarded;
13031 return;
13032 }
13033
13034 // set top-level value to null if it was discarded by the callback
13035 // function
13036 if (result.is_discarded())
13037 {
13038 result = nullptr;
13039 }
13040 }
13041 else
13042 {
13043 json_sax_dom_parser<BasicJsonType, InputAdapterType> sdp(result, allow_exceptions, &m_lexer);
13044 sax_parse_internal(&sdp);
13045
13046 // in strict mode, input must be completely read
13047 if (strict && (get_token() != token_type::end_of_input))
13048 {
13049 sdp.parse_error(m_lexer.get_position(),
13050 m_lexer.get_token_string(),
13051 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13052 }
13053
13054 // in case of an error, return a discarded value
13055 if (sdp.is_errored())
13056 {
13057 result = value_t::discarded;
13058 return;
13059 }
13060 }
13061
13062 result.assert_invariant();
13063 }
13064
13071 bool accept(const bool strict = true)
13072 {
13074 return sax_parse(&sax_acceptor, strict);
13075 }
13076
13077 template<typename SAX>
13079 bool sax_parse(SAX* sax, const bool strict = true)
13080 {
13082 const bool result = sax_parse_internal(sax);
13083
13084 // strict mode: next byte must be EOF
13085 if (result && strict && (get_token() != token_type::end_of_input))
13086 {
13087 return sax->parse_error(m_lexer.get_position(),
13088 m_lexer.get_token_string(),
13089 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13090 }
13091
13092 return result;
13093 }
13094
13095 private:
13096 template<typename SAX>
13098 bool sax_parse_internal(SAX* sax)
13099 {
13100 // stack to remember the hierarchy of structured values we are parsing
13101 // true = array; false = object
13102 std::vector<bool> states;
13103 // value to avoid a goto (see comment where set to true)
13104 bool skip_to_state_evaluation = false;
13105
13106 while (true)
13107 {
13108 if (!skip_to_state_evaluation)
13109 {
13110 // invariant: get_token() was called before each iteration
13111 switch (last_token)
13112 {
13113 case token_type::begin_object:
13114 {
13115 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
13116 {
13117 return false;
13118 }
13119
13120 // closing } -> we are done
13121 if (get_token() == token_type::end_object)
13122 {
13123 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13124 {
13125 return false;
13126 }
13127 break;
13128 }
13129
13130 // parse key
13131 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13132 {
13133 return sax->parse_error(m_lexer.get_position(),
13134 m_lexer.get_token_string(),
13135 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13136 }
13137 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13138 {
13139 return false;
13140 }
13141
13142 // parse separator (:)
13143 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13144 {
13145 return sax->parse_error(m_lexer.get_position(),
13146 m_lexer.get_token_string(),
13147 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13148 }
13149
13150 // remember we are now inside an object
13151 states.push_back(false);
13152
13153 // parse values
13154 get_token();
13155 continue;
13156 }
13157
13158 case token_type::begin_array:
13159 {
13160 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
13161 {
13162 return false;
13163 }
13164
13165 // closing ] -> we are done
13166 if (get_token() == token_type::end_array)
13167 {
13168 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13169 {
13170 return false;
13171 }
13172 break;
13173 }
13174
13175 // remember we are now inside an array
13176 states.push_back(true);
13177
13178 // parse values (no need to call get_token)
13179 continue;
13180 }
13181
13182 case token_type::value_float:
13183 {
13184 const auto res = m_lexer.get_number_float();
13185
13186 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
13187 {
13188 return sax->parse_error(m_lexer.get_position(),
13189 m_lexer.get_token_string(),
13190 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
13191 }
13192
13193 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
13194 {
13195 return false;
13196 }
13197
13198 break;
13199 }
13200
13201 case token_type::literal_false:
13202 {
13203 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
13204 {
13205 return false;
13206 }
13207 break;
13208 }
13209
13210 case token_type::literal_null:
13211 {
13212 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
13213 {
13214 return false;
13215 }
13216 break;
13217 }
13218
13219 case token_type::literal_true:
13220 {
13221 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
13222 {
13223 return false;
13224 }
13225 break;
13226 }
13227
13228 case token_type::value_integer:
13229 {
13230 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
13231 {
13232 return false;
13233 }
13234 break;
13235 }
13236
13237 case token_type::value_string:
13238 {
13239 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
13240 {
13241 return false;
13242 }
13243 break;
13244 }
13245
13246 case token_type::value_unsigned:
13247 {
13248 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
13249 {
13250 return false;
13251 }
13252 break;
13253 }
13254
13255 case token_type::parse_error:
13256 {
13257 // using "uninitialized" to avoid an "expected" message
13258 return sax->parse_error(m_lexer.get_position(),
13259 m_lexer.get_token_string(),
13260 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
13261 }
13262 case token_type::end_of_input:
13263 {
13264 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
13265 {
13266 return sax->parse_error(m_lexer.get_position(),
13267 m_lexer.get_token_string(),
13268 parse_error::create(101, m_lexer.get_position(),
13269 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
13270 }
13271
13272 return sax->parse_error(m_lexer.get_position(),
13273 m_lexer.get_token_string(),
13274 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13275 }
13276 case token_type::uninitialized:
13277 case token_type::end_array:
13278 case token_type::end_object:
13279 case token_type::name_separator:
13280 case token_type::value_separator:
13281 case token_type::literal_or_value:
13282 default: // the last token was unexpected
13283 {
13284 return sax->parse_error(m_lexer.get_position(),
13285 m_lexer.get_token_string(),
13286 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13287 }
13288 }
13289 }
13290 else
13291 {
13292 skip_to_state_evaluation = false;
13293 }
13294
13295 // we reached this line after we successfully parsed a value
13296 if (states.empty())
13297 {
13298 // empty stack: we reached the end of the hierarchy: done
13299 return true;
13300 }
13301
13302 if (states.back()) // array
13303 {
13304 // comma -> next value
13305 // or end of array (ignore_trailing_commas = true)
13306 if (get_token() == token_type::value_separator)
13307 {
13308 // parse a new value
13309 get_token();
13310
13311 // if ignore_trailing_commas and last_token is ], we can continue to "closing ]"
13312 if (!(ignore_trailing_commas && last_token == token_type::end_array))
13313 {
13314 continue;
13315 }
13316 }
13317
13318 // closing ]
13319 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
13320 {
13321 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13322 {
13323 return false;
13324 }
13325
13326 // We are done with this array. Before we can parse a
13327 // new value, we need to evaluate the new state first.
13328 // By setting skip_to_state_evaluation to false, we
13329 // are effectively jumping to the beginning of this if.
13330 JSON_ASSERT(!states.empty());
13331 states.pop_back();
13332 skip_to_state_evaluation = true;
13333 continue;
13334 }
13335
13336 return sax->parse_error(m_lexer.get_position(),
13337 m_lexer.get_token_string(),
13338 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
13339 }
13340
13341 // states.back() is false -> object
13342
13343 // comma -> next value
13344 // or end of object (ignore_trailing_commas = true)
13345 if (get_token() == token_type::value_separator)
13346 {
13347 get_token();
13348
13349 // if ignore_trailing_commas and last_token is }, we can continue to "closing }"
13350 if (!(ignore_trailing_commas && last_token == token_type::end_object))
13351 {
13352 // parse key
13353 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13354 {
13355 return sax->parse_error(m_lexer.get_position(),
13356 m_lexer.get_token_string(),
13357 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13358 }
13359
13360 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13361 {
13362 return false;
13363 }
13364
13365 // parse separator (:)
13366 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13367 {
13368 return sax->parse_error(m_lexer.get_position(),
13369 m_lexer.get_token_string(),
13370 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13371 }
13372
13373 // parse values
13374 get_token();
13375 continue;
13376 }
13377 }
13378
13379 // closing }
13380 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
13381 {
13382 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13383 {
13384 return false;
13385 }
13386
13387 // We are done with this object. Before we can parse a
13388 // new value, we need to evaluate the new state first.
13389 // By setting skip_to_state_evaluation to false, we
13390 // are effectively jumping to the beginning of this if.
13391 JSON_ASSERT(!states.empty());
13392 states.pop_back();
13393 skip_to_state_evaluation = true;
13394 continue;
13395 }
13396
13397 return sax->parse_error(m_lexer.get_position(),
13398 m_lexer.get_token_string(),
13399 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
13400 }
13401 }
13402
13404 token_type get_token()
13405 {
13406 return last_token = m_lexer.scan();
13407 }
13408
13409 std::string exception_message(const token_type expected, const std::string& context)
13410 {
13411 std::string error_msg = "syntax error ";
13412
13413 if (!context.empty())
13414 {
13415 error_msg += concat("while parsing ", context, ' ');
13416 }
13417
13418 error_msg += "- ";
13419
13420 if (last_token == token_type::parse_error)
13421 {
13422 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
13423 m_lexer.get_token_string(), '\'');
13424 }
13425 else
13426 {
13427 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
13428 }
13429
13430 if (expected != token_type::uninitialized)
13431 {
13432 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
13433 }
13434
13435 return error_msg;
13436 }
13437
13438 private:
13440 const parser_callback_t<BasicJsonType> callback = nullptr;
13442 token_type last_token = token_type::uninitialized;
13444 lexer_t m_lexer;
13446 const bool allow_exceptions = true;
13448 const bool ignore_trailing_commas = false;
13449};
13450
13451} // namespace detail
13453
13454// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13455// __ _____ _____ _____
13456// __| | __| | | | JSON for Modern C++
13457// | | |__ | | | | | | version 3.12.0
13458// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13459//
13460// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13461// SPDX-License-Identifier: MIT
13462
13463
13464
13465// #include <nlohmann/detail/abi_macros.hpp>
13466
13467// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13468// __ _____ _____ _____
13469// __| | __| | | | JSON for Modern C++
13470// | | |__ | | | | | | version 3.12.0
13471// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13472//
13473// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13474// SPDX-License-Identifier: MIT
13475
13476
13477
13478#include <cstddef> // ptrdiff_t
13479#include <limits> // numeric_limits
13480
13481// #include <nlohmann/detail/macro_scope.hpp>
13482
13483
13485namespace detail
13486{
13487
13488/*
13489@brief an iterator for primitive JSON types
13490
13491This class models an iterator for primitive JSON types (boolean, number,
13492string). Its only purpose is to allow the iterator/const_iterator classes
13493to "iterate" over primitive values. Internally, the iterator is modeled by
13494a `difference_type` variable. Value begin_value (`0`) models the begin and
13495end_value (`1`) models past the end.
13496*/
13498{
13499 private:
13500 using difference_type = std::ptrdiff_t;
13501 static constexpr difference_type begin_value = 0;
13502 static constexpr difference_type end_value = begin_value + 1;
13503
13506 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
13507
13508 public:
13509 constexpr difference_type get_value() const noexcept
13510 {
13511 return m_it;
13512 }
13513
13515 void set_begin() noexcept
13516 {
13517 m_it = begin_value;
13518 }
13519
13521 void set_end() noexcept
13522 {
13523 m_it = end_value;
13524 }
13525
13527 constexpr bool is_begin() const noexcept
13528 {
13529 return m_it == begin_value;
13530 }
13531
13533 constexpr bool is_end() const noexcept
13534 {
13535 return m_it == end_value;
13536 }
13537
13538 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13539 {
13540 return lhs.m_it == rhs.m_it;
13541 }
13542
13543 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13544 {
13545 return lhs.m_it < rhs.m_it;
13546 }
13547
13548 primitive_iterator_t operator+(difference_type n) noexcept
13549 {
13550 auto result = *this;
13551 result += n;
13552 return result;
13553 }
13554
13555 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13556 {
13557 return lhs.m_it - rhs.m_it;
13558 }
13559
13561 {
13562 ++m_it;
13563 return *this;
13564 }
13565
13566 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
13567 {
13568 auto result = *this;
13569 ++m_it;
13570 return result;
13571 }
13572
13574 {
13575 --m_it;
13576 return *this;
13577 }
13578
13579 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
13580 {
13581 auto result = *this;
13582 --m_it;
13583 return result;
13584 }
13585
13586 primitive_iterator_t& operator+=(difference_type n) noexcept
13587 {
13588 m_it += n;
13589 return *this;
13590 }
13591
13592 primitive_iterator_t& operator-=(difference_type n) noexcept
13593 {
13594 m_it -= n;
13595 return *this;
13596 }
13597};
13598
13599} // namespace detail
13601
13602
13604namespace detail
13605{
13606
13613template<typename BasicJsonType> struct internal_iterator
13614{
13616 typename BasicJsonType::object_t::iterator object_iterator {};
13618 typename BasicJsonType::array_t::iterator array_iterator {};
13620 primitive_iterator_t primitive_iterator {};
13621};
13622
13623} // namespace detail
13625
13626// #include <nlohmann/detail/iterators/iter_impl.hpp>
13627// __ _____ _____ _____
13628// __| | __| | | | JSON for Modern C++
13629// | | |__ | | | | | | version 3.12.0
13630// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13631//
13632// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13633// SPDX-License-Identifier: MIT
13634
13635
13636
13637#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
13638#include <type_traits> // conditional, is_const, remove_const
13639
13640// #include <nlohmann/detail/exceptions.hpp>
13641
13642// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13643
13644// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13645
13646// #include <nlohmann/detail/macro_scope.hpp>
13647
13648// #include <nlohmann/detail/meta/cpp_future.hpp>
13649
13650// #include <nlohmann/detail/meta/type_traits.hpp>
13651
13652// #include <nlohmann/detail/value_t.hpp>
13653
13654
13656namespace detail
13657{
13658
13659// forward declare to be able to friend it later on
13660template<typename IteratorType> class iteration_proxy;
13661template<typename IteratorType> class iteration_proxy_value;
13662
13679template<typename BasicJsonType>
13680class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
13681{
13683 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
13685 friend other_iter_impl;
13686 friend BasicJsonType;
13689
13690 using object_t = typename BasicJsonType::object_t;
13691 using array_t = typename BasicJsonType::array_t;
13692 // make sure BasicJsonType is basic_json or const basic_json
13694 "iter_impl only accepts (const) basic_json");
13695 // superficial check for the LegacyBidirectionalIterator named requirement
13696 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
13697 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
13698 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
13699
13700 public:
13706 using iterator_category = std::bidirectional_iterator_tag;
13707
13709 using value_type = typename BasicJsonType::value_type;
13711 using difference_type = typename BasicJsonType::difference_type;
13713 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
13714 typename BasicJsonType::const_pointer,
13715 typename BasicJsonType::pointer>::type;
13718 typename std::conditional<std::is_const<BasicJsonType>::value,
13719 typename BasicJsonType::const_reference,
13720 typename BasicJsonType::reference>::type;
13721
13722 iter_impl() = default;
13723 ~iter_impl() = default;
13724 iter_impl(iter_impl&&) noexcept = default;
13725 iter_impl& operator=(iter_impl&&) noexcept = default;
13726
13733 explicit iter_impl(pointer object) noexcept : m_object(object)
13734 {
13735 JSON_ASSERT(m_object != nullptr);
13736
13737 switch (m_object->m_data.m_type)
13738 {
13739 case value_t::object:
13740 {
13741 m_it.object_iterator = typename object_t::iterator();
13742 break;
13743 }
13744
13745 case value_t::array:
13746 {
13747 m_it.array_iterator = typename array_t::iterator();
13748 break;
13749 }
13750
13751 case value_t::null:
13752 case value_t::string:
13753 case value_t::boolean:
13754 case value_t::number_integer:
13755 case value_t::number_unsigned:
13756 case value_t::number_float:
13757 case value_t::binary:
13758 case value_t::discarded:
13759 default:
13760 {
13761 m_it.primitive_iterator = primitive_iterator_t();
13762 break;
13763 }
13764 }
13765 }
13766
13784 : m_object(other.m_object), m_it(other.m_it)
13785 {}
13786
13794 {
13795 if (&other != this)
13796 {
13797 m_object = other.m_object;
13798 m_it = other.m_it;
13799 }
13800 return *this;
13801 }
13802
13808 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13809 : m_object(other.m_object), m_it(other.m_it)
13810 {}
13811
13818 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13819 {
13820 m_object = other.m_object;
13821 m_it = other.m_it;
13822 return *this;
13823 }
13824
13830 void set_begin() noexcept
13831 {
13832 JSON_ASSERT(m_object != nullptr);
13833
13834 switch (m_object->m_data.m_type)
13835 {
13836 case value_t::object:
13837 {
13838 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13839 break;
13840 }
13841
13842 case value_t::array:
13843 {
13844 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13845 break;
13846 }
13847
13848 case value_t::null:
13849 {
13850 // set to end so begin()==end() is true: null is empty
13851 m_it.primitive_iterator.set_end();
13852 break;
13853 }
13854
13855 case value_t::string:
13856 case value_t::boolean:
13857 case value_t::number_integer:
13858 case value_t::number_unsigned:
13859 case value_t::number_float:
13860 case value_t::binary:
13861 case value_t::discarded:
13862 default:
13863 {
13864 m_it.primitive_iterator.set_begin();
13865 break;
13866 }
13867 }
13868 }
13869
13874 void set_end() noexcept
13875 {
13876 JSON_ASSERT(m_object != nullptr);
13877
13878 switch (m_object->m_data.m_type)
13879 {
13880 case value_t::object:
13881 {
13882 m_it.object_iterator = m_object->m_data.m_value.object->end();
13883 break;
13884 }
13885
13886 case value_t::array:
13887 {
13888 m_it.array_iterator = m_object->m_data.m_value.array->end();
13889 break;
13890 }
13891
13892 case value_t::null:
13893 case value_t::string:
13894 case value_t::boolean:
13895 case value_t::number_integer:
13896 case value_t::number_unsigned:
13897 case value_t::number_float:
13898 case value_t::binary:
13899 case value_t::discarded:
13900 default:
13901 {
13902 m_it.primitive_iterator.set_end();
13903 break;
13904 }
13905 }
13906 }
13907
13908 public:
13914 {
13915 JSON_ASSERT(m_object != nullptr);
13916
13917 switch (m_object->m_data.m_type)
13918 {
13919 case value_t::object:
13920 {
13921 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13922 return m_it.object_iterator->second;
13923 }
13924
13925 case value_t::array:
13926 {
13927 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13928 return *m_it.array_iterator;
13929 }
13930
13931 case value_t::null:
13932 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13933
13934 case value_t::string:
13935 case value_t::boolean:
13936 case value_t::number_integer:
13937 case value_t::number_unsigned:
13938 case value_t::number_float:
13939 case value_t::binary:
13940 case value_t::discarded:
13941 default:
13942 {
13943 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13944 {
13945 return *m_object;
13946 }
13947
13948 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13949 }
13950 }
13951 }
13952
13958 {
13959 JSON_ASSERT(m_object != nullptr);
13960
13961 switch (m_object->m_data.m_type)
13962 {
13963 case value_t::object:
13964 {
13965 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13966 return &(m_it.object_iterator->second);
13967 }
13968
13969 case value_t::array:
13970 {
13971 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13972 return &*m_it.array_iterator;
13973 }
13974
13975 case value_t::null:
13976 case value_t::string:
13977 case value_t::boolean:
13978 case value_t::number_integer:
13979 case value_t::number_unsigned:
13980 case value_t::number_float:
13981 case value_t::binary:
13982 case value_t::discarded:
13983 default:
13984 {
13985 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13986 {
13987 return m_object;
13988 }
13989
13990 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13991 }
13992 }
13993 }
13994
13999 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
14000 {
14001 auto result = *this;
14002 ++(*this);
14003 return result;
14004 }
14005
14011 {
14012 JSON_ASSERT(m_object != nullptr);
14013
14014 switch (m_object->m_data.m_type)
14015 {
14016 case value_t::object:
14017 {
14018 std::advance(m_it.object_iterator, 1);
14019 break;
14020 }
14021
14022 case value_t::array:
14023 {
14024 std::advance(m_it.array_iterator, 1);
14025 break;
14026 }
14027
14028 case value_t::null:
14029 case value_t::string:
14030 case value_t::boolean:
14031 case value_t::number_integer:
14032 case value_t::number_unsigned:
14033 case value_t::number_float:
14034 case value_t::binary:
14035 case value_t::discarded:
14036 default:
14037 {
14038 ++m_it.primitive_iterator;
14039 break;
14040 }
14041 }
14042
14043 return *this;
14044 }
14045
14050 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
14051 {
14052 auto result = *this;
14053 --(*this);
14054 return result;
14055 }
14056
14062 {
14063 JSON_ASSERT(m_object != nullptr);
14064
14065 switch (m_object->m_data.m_type)
14066 {
14067 case value_t::object:
14068 {
14069 std::advance(m_it.object_iterator, -1);
14070 break;
14071 }
14072
14073 case value_t::array:
14074 {
14075 std::advance(m_it.array_iterator, -1);
14076 break;
14077 }
14078
14079 case value_t::null:
14080 case value_t::string:
14081 case value_t::boolean:
14082 case value_t::number_integer:
14083 case value_t::number_unsigned:
14084 case value_t::number_float:
14085 case value_t::binary:
14086 case value_t::discarded:
14087 default:
14088 {
14089 --m_it.primitive_iterator;
14090 break;
14091 }
14092 }
14093
14094 return *this;
14095 }
14096
14101 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 >
14102 bool operator==(const IterImpl& other) const
14103 {
14104 // if objects are not the same, the comparison is undefined
14105 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14106 {
14107 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14108 }
14109
14110 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14111 if (m_object == nullptr)
14112 {
14113 return true;
14114 }
14115
14116 switch (m_object->m_data.m_type)
14117 {
14118 case value_t::object:
14119 return (m_it.object_iterator == other.m_it.object_iterator);
14120
14121 case value_t::array:
14122 return (m_it.array_iterator == other.m_it.array_iterator);
14123
14124 case value_t::null:
14125 case value_t::string:
14126 case value_t::boolean:
14127 case value_t::number_integer:
14128 case value_t::number_unsigned:
14129 case value_t::number_float:
14130 case value_t::binary:
14131 case value_t::discarded:
14132 default:
14133 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
14134 }
14135 }
14136
14141 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 >
14142 bool operator!=(const IterImpl& other) const
14143 {
14144 return !operator==(other);
14145 }
14146
14151 bool operator<(const iter_impl& other) const
14152 {
14153 // if objects are not the same, the comparison is undefined
14154 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14155 {
14156 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14157 }
14158
14159 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14160 if (m_object == nullptr)
14161 {
14162 // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false
14163 return false;
14164 }
14165
14166 switch (m_object->m_data.m_type)
14167 {
14168 case value_t::object:
14169 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
14170
14171 case value_t::array:
14172 return (m_it.array_iterator < other.m_it.array_iterator);
14173
14174 case value_t::null:
14175 case value_t::string:
14176 case value_t::boolean:
14177 case value_t::number_integer:
14178 case value_t::number_unsigned:
14179 case value_t::number_float:
14180 case value_t::binary:
14181 case value_t::discarded:
14182 default:
14183 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
14184 }
14185 }
14186
14191 bool operator<=(const iter_impl& other) const
14192 {
14193 return !other.operator < (*this);
14194 }
14195
14200 bool operator>(const iter_impl& other) const
14201 {
14202 return !operator<=(other);
14203 }
14204
14209 bool operator>=(const iter_impl& other) const
14210 {
14211 return !operator<(other);
14212 }
14213
14219 {
14220 JSON_ASSERT(m_object != nullptr);
14221
14222 switch (m_object->m_data.m_type)
14223 {
14224 case value_t::object:
14225 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14226
14227 case value_t::array:
14228 {
14229 std::advance(m_it.array_iterator, i);
14230 break;
14231 }
14232
14233 case value_t::null:
14234 case value_t::string:
14235 case value_t::boolean:
14236 case value_t::number_integer:
14237 case value_t::number_unsigned:
14238 case value_t::number_float:
14239 case value_t::binary:
14240 case value_t::discarded:
14241 default:
14242 {
14243 m_it.primitive_iterator += i;
14244 break;
14245 }
14246 }
14247
14248 return *this;
14249 }
14250
14256 {
14257 return operator+=(-i);
14258 }
14259
14265 {
14266 auto result = *this;
14267 result += i;
14268 return result;
14269 }
14270
14276 {
14277 auto result = it;
14278 result += i;
14279 return result;
14280 }
14281
14287 {
14288 auto result = *this;
14289 result -= i;
14290 return result;
14291 }
14292
14298 {
14299 JSON_ASSERT(m_object != nullptr);
14300
14301 switch (m_object->m_data.m_type)
14302 {
14303 case value_t::object:
14304 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with 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
14327 {
14328 JSON_ASSERT(m_object != nullptr);
14329
14330 switch (m_object->m_data.m_type)
14331 {
14332 case value_t::object:
14333 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
14334
14335 case value_t::array:
14336 return *std::next(m_it.array_iterator, n);
14337
14338 case value_t::null:
14339 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14340
14341 case value_t::string:
14342 case value_t::boolean:
14343 case value_t::number_integer:
14344 case value_t::number_unsigned:
14345 case value_t::number_float:
14346 case value_t::binary:
14347 case value_t::discarded:
14348 default:
14349 {
14350 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
14351 {
14352 return *m_object;
14353 }
14354
14355 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14356 }
14357 }
14358 }
14359
14364 const typename object_t::key_type& key() const
14365 {
14366 JSON_ASSERT(m_object != nullptr);
14367
14368 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
14369 {
14370 return m_it.object_iterator->first;
14371 }
14372
14373 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
14374 }
14375
14381 {
14382 return operator*();
14383 }
14384
14387 pointer m_object = nullptr;
14390};
14391
14392} // namespace detail
14394
14395// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
14396
14397// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
14398// __ _____ _____ _____
14399// __| | __| | | | JSON for Modern C++
14400// | | |__ | | | | | | version 3.12.0
14401// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14402//
14403// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14404// SPDX-License-Identifier: MIT
14405
14406
14407
14408#include <cstddef> // ptrdiff_t
14409#include <iterator> // reverse_iterator
14410#include <utility> // declval
14411
14412// #include <nlohmann/detail/abi_macros.hpp>
14413
14414
14416namespace detail
14417{
14418
14420// reverse_iterator //
14422
14441template<typename Base>
14442class json_reverse_iterator : public std::reverse_iterator<Base>
14443{
14444 public:
14445 using difference_type = std::ptrdiff_t;
14447 using base_iterator = std::reverse_iterator<Base>;
14449 using reference = typename Base::reference;
14450
14452 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
14453 : base_iterator(it) {}
14454
14456 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
14457
14459 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
14460 {
14461 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
14462 }
14463
14466 {
14467 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
14468 }
14469
14471 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
14472 {
14473 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
14474 }
14475
14478 {
14479 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
14480 }
14481
14484 {
14485 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
14486 }
14487
14490 {
14491 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
14492 }
14493
14496 {
14497 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
14498 }
14499
14502 {
14503 return base_iterator(*this) - base_iterator(other);
14504 }
14505
14508 {
14509 return *(this->operator+(n));
14510 }
14511
14513 auto key() const -> decltype(std::declval<Base>().key())
14514 {
14515 auto it = --this->base();
14516 return it.key();
14517 }
14518
14521 {
14522 auto it = --this->base();
14523 return it.operator * ();
14524 }
14525};
14526
14527} // namespace detail
14529
14530// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
14531
14532// #include <nlohmann/detail/json_custom_base_class.hpp>
14533// __ _____ _____ _____
14534// __| | __| | | | JSON for Modern C++
14535// | | |__ | | | | | | version 3.12.0
14536// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14537//
14538// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14539// SPDX-License-Identifier: MIT
14540
14541
14542
14543#include <type_traits> // conditional, is_same
14544
14545// #include <nlohmann/detail/abi_macros.hpp>
14546
14547
14549namespace detail
14550{
14551
14563
14564template<class T>
14565using json_base_class = typename std::conditional <
14566 std::is_same<T, void>::value,
14568 T
14569 >::type;
14570
14571} // namespace detail
14573
14574// #include <nlohmann/detail/json_pointer.hpp>
14575// __ _____ _____ _____
14576// __| | __| | | | JSON for Modern C++
14577// | | |__ | | | | | | version 3.12.0
14578// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14579//
14580// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14581// SPDX-License-Identifier: MIT
14582
14583
14584
14585#include <algorithm> // all_of
14586#include <cctype> // isdigit
14587#include <cerrno> // errno, ERANGE
14588#include <cstdlib> // strtoull
14589#ifndef JSON_NO_IO
14590 #include <iosfwd> // ostream
14591#endif // JSON_NO_IO
14592#include <limits> // max
14593#include <numeric> // accumulate
14594#include <string> // string
14595#include <utility> // move
14596#include <vector> // vector
14597
14598// #include <nlohmann/detail/exceptions.hpp>
14599
14600// #include <nlohmann/detail/macro_scope.hpp>
14601
14602// #include <nlohmann/detail/string_concat.hpp>
14603
14604// #include <nlohmann/detail/string_escape.hpp>
14605
14606// #include <nlohmann/detail/value_t.hpp>
14607
14608
14610
14613template<typename RefStringType>
14615{
14616 // allow basic_json to access private members
14618 friend class basic_json;
14619
14620 template<typename>
14621 friend class json_pointer;
14622
14623 template<typename T>
14624 struct string_t_helper
14625 {
14626 using type = T;
14627 };
14628
14630 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
14631 {
14632 using type = StringType;
14633 };
14634
14635 public:
14636 // for backwards compatibility accept BasicJsonType
14637 using string_t = typename string_t_helper<RefStringType>::type;
14638
14641 explicit json_pointer(const string_t& s = "")
14642 : reference_tokens(split(s))
14643 {}
14644
14648 {
14649 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
14650 string_t{},
14651 [](const string_t& a, const string_t& b)
14652 {
14653 return detail::concat(a, '/', detail::escape(b));
14654 });
14655 }
14656
14660 operator string_t() const
14661 {
14662 return to_string();
14663 }
14664
14665#ifndef JSON_NO_IO
14668 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
14669 {
14670 o << ptr.to_string();
14671 return o;
14672 }
14673#endif
14674
14678 {
14679 reference_tokens.insert(reference_tokens.end(),
14680 ptr.reference_tokens.begin(),
14681 ptr.reference_tokens.end());
14682 return *this;
14683 }
14684
14688 {
14689 push_back(std::move(token));
14690 return *this;
14691 }
14692
14695 json_pointer& operator/=(std::size_t array_idx)
14696 {
14697 return *this /= std::to_string(array_idx);
14698 }
14699
14703 const json_pointer& rhs)
14704 {
14705 return json_pointer(lhs) /= rhs;
14706 }
14707
14710 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
14711 {
14712 return json_pointer(lhs) /= std::move(token);
14713 }
14714
14717 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
14718 {
14719 return json_pointer(lhs) /= array_idx;
14720 }
14721
14725 {
14726 if (empty())
14727 {
14728 return *this;
14729 }
14730
14731 json_pointer res = *this;
14732 res.pop_back();
14733 return res;
14734 }
14735
14739 {
14740 if (JSON_HEDLEY_UNLIKELY(empty()))
14741 {
14742 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14743 }
14744
14745 reference_tokens.pop_back();
14746 }
14747
14750 const string_t& back() const
14751 {
14752 if (JSON_HEDLEY_UNLIKELY(empty()))
14753 {
14754 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14755 }
14756
14757 return reference_tokens.back();
14758 }
14759
14762 void push_back(const string_t& token)
14763 {
14764 reference_tokens.push_back(token);
14765 }
14766
14769 void push_back(string_t&& token)
14770 {
14771 reference_tokens.push_back(std::move(token));
14772 }
14773
14776 bool empty() const noexcept
14777 {
14778 return reference_tokens.empty();
14779 }
14780
14781 private:
14792 template<typename BasicJsonType>
14793 static typename BasicJsonType::size_type array_index(const string_t& s)
14794 {
14795 using size_type = typename BasicJsonType::size_type;
14796
14797 // error condition (cf. RFC 6901, Sect. 4)
14798 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14799 {
14800 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14801 }
14802
14803 // error condition (cf. RFC 6901, Sect. 4)
14804 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14805 {
14806 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14807 }
14808
14809 const char* p = s.c_str();
14810 char* p_end = nullptr; // NOLINT(misc-const-correctness)
14811 errno = 0; // strtoull doesn't reset errno
14812 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14813 if (p == p_end // invalid input or empty string
14814 || errno == ERANGE // out of range
14815 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14816 {
14817 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14818 }
14819
14820 // only triggered on special platforms (like 32bit), see also
14821 // https://github.com/nlohmann/json/pull/2203
14822 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14823 {
14824 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14825 }
14826
14827 return static_cast<size_type>(res);
14828 }
14829
14831 json_pointer top() const
14832 {
14833 if (JSON_HEDLEY_UNLIKELY(empty()))
14834 {
14835 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14836 }
14837
14838 json_pointer result = *this;
14839 result.reference_tokens = {reference_tokens[0]};
14840 return result;
14841 }
14842
14843 private:
14852 template<typename BasicJsonType>
14853 BasicJsonType& get_and_create(BasicJsonType& j) const
14854 {
14855 auto* result = &j;
14856
14857 // in case no reference tokens exist, return a reference to the JSON value
14858 // j which will be overwritten by a primitive value
14859 for (const auto& reference_token : reference_tokens)
14860 {
14861 switch (result->type())
14862 {
14864 {
14865 if (reference_token == "0")
14866 {
14867 // start a new array if the reference token is 0
14868 result = &result->operator[](0);
14869 }
14870 else
14871 {
14872 // start a new object otherwise
14873 result = &result->operator[](reference_token);
14874 }
14875 break;
14876 }
14877
14879 {
14880 // create an entry in the object
14881 result = &result->operator[](reference_token);
14882 break;
14883 }
14884
14886 {
14887 // create an entry in the array
14888 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14889 break;
14890 }
14891
14892 /*
14893 The following code is only reached if there exists a reference
14894 token _and_ the current value is primitive. In this case, we have
14895 an error situation, because primitive values may only occur as
14896 a single value; that is, with an empty list of reference tokens.
14897 */
14905 default:
14906 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14907 }
14908 }
14909
14910 return *result;
14911 }
14912
14932 template<typename BasicJsonType>
14933 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14934 {
14935 for (const auto& reference_token : reference_tokens)
14936 {
14937 // convert null values to arrays or objects before continuing
14938 if (ptr->is_null())
14939 {
14940 // check if the reference token is a number
14941 const bool nums =
14942 std::all_of(reference_token.begin(), reference_token.end(),
14943 [](const unsigned char x)
14944 {
14945 return std::isdigit(x);
14946 });
14947
14948 // change value to an array for numbers or "-" or to object otherwise
14949 *ptr = (nums || reference_token == "-")
14951 : detail::value_t::object;
14952 }
14953
14954 switch (ptr->type())
14955 {
14957 {
14958 // use unchecked object access
14959 ptr = &ptr->operator[](reference_token);
14960 break;
14961 }
14962
14964 {
14965 if (reference_token == "-")
14966 {
14967 // explicitly treat "-" as index beyond the end
14968 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14969 }
14970 else
14971 {
14972 // convert array index to number; unchecked access
14973 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14974 }
14975 break;
14976 }
14977
14986 default:
14987 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14988 }
14989 }
14990
14991 return *ptr;
14992 }
14993
15000 template<typename BasicJsonType>
15001 BasicJsonType& get_checked(BasicJsonType* ptr) const
15002 {
15003 for (const auto& reference_token : reference_tokens)
15004 {
15005 switch (ptr->type())
15006 {
15008 {
15009 // note: at performs range check
15010 ptr = &ptr->at(reference_token);
15011 break;
15012 }
15013
15015 {
15016 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15017 {
15018 // "-" always fails the range check
15020 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15021 ") is out of range"), ptr));
15022 }
15023
15024 // note: at performs range check
15025 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15026 break;
15027 }
15028
15037 default:
15038 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15039 }
15040 }
15041
15042 return *ptr;
15043 }
15044
15058 template<typename BasicJsonType>
15059 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
15060 {
15061 for (const auto& reference_token : reference_tokens)
15062 {
15063 switch (ptr->type())
15064 {
15066 {
15067 // use unchecked object access
15068 ptr = &ptr->operator[](reference_token);
15069 break;
15070 }
15071
15073 {
15074 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15075 {
15076 // "-" cannot be used for const access
15077 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));
15078 }
15079
15080 // use unchecked array access
15081 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
15082 break;
15083 }
15084
15093 default:
15094 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15095 }
15096 }
15097
15098 return *ptr;
15099 }
15100
15107 template<typename BasicJsonType>
15108 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
15109 {
15110 for (const auto& reference_token : reference_tokens)
15111 {
15112 switch (ptr->type())
15113 {
15115 {
15116 // note: at performs range check
15117 ptr = &ptr->at(reference_token);
15118 break;
15119 }
15120
15122 {
15123 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15124 {
15125 // "-" always fails the range check
15127 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15128 ") is out of range"), ptr));
15129 }
15130
15131 // note: at performs range check
15132 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15133 break;
15134 }
15135
15144 default:
15145 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15146 }
15147 }
15148
15149 return *ptr;
15150 }
15151
15156 template<typename BasicJsonType>
15157 bool contains(const BasicJsonType* ptr) const
15158 {
15159 for (const auto& reference_token : reference_tokens)
15160 {
15161 switch (ptr->type())
15162 {
15164 {
15165 if (!ptr->contains(reference_token))
15166 {
15167 // we did not find the key in the object
15168 return false;
15169 }
15170
15171 ptr = &ptr->operator[](reference_token);
15172 break;
15173 }
15174
15176 {
15177 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15178 {
15179 // "-" always fails the range check
15180 return false;
15181 }
15182 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
15183 {
15184 // invalid char
15185 return false;
15186 }
15187 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
15188 {
15189 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
15190 {
15191 // the first char should be between '1' and '9'
15192 return false;
15193 }
15194 for (std::size_t i = 1; i < reference_token.size(); i++)
15195 {
15196 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
15197 {
15198 // other char should be between '0' and '9'
15199 return false;
15200 }
15201 }
15202 }
15203
15204 const auto idx = array_index<BasicJsonType>(reference_token);
15205 if (idx >= ptr->size())
15206 {
15207 // index out of range
15208 return false;
15209 }
15210
15211 ptr = &ptr->operator[](idx);
15212 break;
15213 }
15214
15223 default:
15224 {
15225 // we do not expect primitive values if there is still a
15226 // reference token to process
15227 return false;
15228 }
15229 }
15230 }
15231
15232 // no reference token left means we found a primitive value
15233 return true;
15234 }
15235
15245 static std::vector<string_t> split(const string_t& reference_string)
15246 {
15247 std::vector<string_t> result;
15248
15249 // special case: empty reference string -> no reference tokens
15250 if (reference_string.empty())
15251 {
15252 return result;
15253 }
15254
15255 // check if a nonempty reference string begins with slash
15256 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
15257 {
15258 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
15259 }
15260
15261 // extract the reference tokens:
15262 // - slash: position of the last read slash (or end of string)
15263 // - start: position after the previous slash
15264 for (
15265 // search for the first slash after the first character
15266 std::size_t slash = reference_string.find_first_of('/', 1),
15267 // set the beginning of the first reference token
15268 start = 1;
15269 // we can stop if start == 0 (if slash == string_t::npos)
15270 start != 0;
15271 // set the beginning of the next reference token
15272 // (will eventually be 0 if slash == string_t::npos)
15273 start = (slash == string_t::npos) ? 0 : slash + 1,
15274 // find next slash
15275 slash = reference_string.find_first_of('/', start))
15276 {
15277 // use the text between the beginning of the reference token
15278 // (start) and the last slash (slash).
15279 auto reference_token = reference_string.substr(start, slash - start);
15280
15281 // check reference tokens are properly escaped
15282 for (std::size_t pos = reference_token.find_first_of('~');
15283 pos != string_t::npos;
15284 pos = reference_token.find_first_of('~', pos + 1))
15285 {
15286 JSON_ASSERT(reference_token[pos] == '~');
15287
15288 // ~ must be followed by 0 or 1
15289 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
15290 (reference_token[pos + 1] != '0' &&
15291 reference_token[pos + 1] != '1')))
15292 {
15293 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
15294 }
15295 }
15296
15297 // finally, store the reference token
15298 detail::unescape(reference_token);
15299 result.push_back(reference_token);
15300 }
15301
15302 return result;
15303 }
15304
15305 private:
15313 template<typename BasicJsonType>
15314 static void flatten(const string_t& reference_string,
15315 const BasicJsonType& value,
15316 BasicJsonType& result)
15317 {
15318 switch (value.type())
15319 {
15321 {
15322 if (value.m_data.m_value.array->empty())
15323 {
15324 // flatten empty array as null
15325 result[reference_string] = nullptr;
15326 }
15327 else
15328 {
15329 // iterate array and use index as a reference string
15330 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
15331 {
15332 flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
15333 value.m_data.m_value.array->operator[](i), result);
15334 }
15335 }
15336 break;
15337 }
15338
15340 {
15341 if (value.m_data.m_value.object->empty())
15342 {
15343 // flatten empty object as null
15344 result[reference_string] = nullptr;
15345 }
15346 else
15347 {
15348 // iterate object and use keys as reference string
15349 for (const auto& element : *value.m_data.m_value.object)
15350 {
15351 flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
15352 }
15353 }
15354 break;
15355 }
15356
15365 default:
15366 {
15367 // add a primitive value with its reference string
15368 result[reference_string] = value;
15369 break;
15370 }
15371 }
15372 }
15373
15384 template<typename BasicJsonType>
15385 static BasicJsonType
15386 unflatten(const BasicJsonType& value)
15387 {
15388 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
15389 {
15390 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
15391 }
15392
15393 BasicJsonType result;
15394
15395 // iterate the JSON object values
15396 for (const auto& element : *value.m_data.m_value.object)
15397 {
15398 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
15399 {
15400 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
15401 }
15402
15403 // Assign the value to the reference pointed to by JSON pointer. Note
15404 // that if the JSON pointer is "" (i.e., points to the whole value),
15405 // function get_and_create returns a reference to the result itself.
15406 // An assignment will then create a primitive value.
15407 json_pointer(element.first).get_and_create(result) = element.second;
15408 }
15409
15410 return result;
15411 }
15412
15413 // can't use the conversion operator because of ambiguity
15414 json_pointer<string_t> convert() const&
15415 {
15417 result.reference_tokens = reference_tokens;
15418 return result;
15419 }
15420
15421 json_pointer<string_t> convert()&&
15422 {
15424 result.reference_tokens = std::move(reference_tokens);
15425 return result;
15426 }
15427
15428 public:
15429#if JSON_HAS_THREE_WAY_COMPARISON
15432 template<typename RefStringTypeRhs>
15433 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
15434 {
15435 return reference_tokens == rhs.reference_tokens;
15436 }
15437
15440 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
15441 bool operator==(const string_t& rhs) const
15442 {
15443 return *this == json_pointer(rhs);
15444 }
15445
15447 template<typename RefStringTypeRhs>
15448 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
15449 {
15450 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
15451 }
15452#else
15455 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15456 // NOLINTNEXTLINE(readability-redundant-declaration)
15457 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15458 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15459
15462 template<typename RefStringTypeLhs, typename StringType>
15463 // NOLINTNEXTLINE(readability-redundant-declaration)
15464 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15465 const StringType& rhs);
15466
15469 template<typename RefStringTypeRhs, typename StringType>
15470 // NOLINTNEXTLINE(readability-redundant-declaration)
15471 friend bool operator==(const StringType& lhs,
15473
15476 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15477 // NOLINTNEXTLINE(readability-redundant-declaration)
15478 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15479 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15480
15483 template<typename RefStringTypeLhs, typename StringType>
15484 // NOLINTNEXTLINE(readability-redundant-declaration)
15485 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15486 const StringType& rhs);
15487
15490 template<typename RefStringTypeRhs, typename StringType>
15491 // NOLINTNEXTLINE(readability-redundant-declaration)
15492 friend bool operator!=(const StringType& lhs,
15494
15496 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15497 // NOLINTNEXTLINE(readability-redundant-declaration)
15498 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
15499 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15500#endif
15501
15502 private:
15504 std::vector<string_t> reference_tokens;
15505};
15506
15507#if !JSON_HAS_THREE_WAY_COMPARISON
15508// functions cannot be defined inside the class due to ODR violations
15509template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15511 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15512{
15513 return lhs.reference_tokens == rhs.reference_tokens;
15514}
15515
15516template<typename RefStringTypeLhs,
15517 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15519inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15520 const StringType& rhs)
15521{
15522 return lhs == json_pointer<RefStringTypeLhs>(rhs);
15523}
15524
15525template<typename RefStringTypeRhs,
15526 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15528inline bool operator==(const StringType& lhs,
15529 const json_pointer<RefStringTypeRhs>& rhs)
15530{
15531 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
15532}
15533
15534template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15536 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15537{
15538 return !(lhs == rhs);
15539}
15540
15541template<typename RefStringTypeLhs,
15542 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15544inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15545 const StringType& rhs)
15546{
15547 return !(lhs == rhs);
15548}
15549
15550template<typename RefStringTypeRhs,
15551 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15553inline bool operator!=(const StringType& lhs,
15554 const json_pointer<RefStringTypeRhs>& rhs)
15555{
15556 return !(lhs == rhs);
15557}
15558
15559template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15561 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15562{
15563 return lhs.reference_tokens < rhs.reference_tokens;
15564}
15565#endif
15566
15568
15569// #include <nlohmann/detail/json_ref.hpp>
15570// __ _____ _____ _____
15571// __| | __| | | | JSON for Modern C++
15572// | | |__ | | | | | | version 3.12.0
15573// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15574//
15575// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15576// SPDX-License-Identifier: MIT
15577
15578
15579
15580#include <initializer_list>
15581#include <utility>
15582
15583// #include <nlohmann/detail/abi_macros.hpp>
15584
15585// #include <nlohmann/detail/meta/type_traits.hpp>
15586
15587
15589namespace detail
15590{
15591
15592template<typename BasicJsonType>
15594{
15595 public:
15596 using value_type = BasicJsonType;
15597
15599 : owned_value(std::move(value))
15600 {}
15601
15602 json_ref(const value_type& value)
15603 : value_ref(&value)
15604 {}
15605
15606 json_ref(std::initializer_list<json_ref> init)
15607 : owned_value(init)
15608 {}
15609
15610 template <
15611 class... Args,
15612 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
15613 json_ref(Args && ... args)
15614 : owned_value(std::forward<Args>(args)...)
15615 {}
15616
15617 // class should be movable only
15618 json_ref(json_ref&&) noexcept = default;
15619 json_ref(const json_ref&) = delete;
15620 json_ref& operator=(const json_ref&) = delete;
15621 json_ref& operator=(json_ref&&) = delete;
15622 ~json_ref() = default;
15623
15624 value_type moved_or_copied() const
15625 {
15626 if (value_ref == nullptr)
15627 {
15628 return std::move(owned_value);
15629 }
15630 return *value_ref;
15631 }
15632
15633 value_type const& operator*() const
15634 {
15635 return value_ref ? *value_ref : owned_value;
15636 }
15637
15638 value_type const* operator->() const
15639 {
15640 return &** this;
15641 }
15642
15643 private:
15644 mutable value_type owned_value = nullptr;
15645 value_type const* value_ref = nullptr;
15646};
15647
15648} // namespace detail
15650
15651// #include <nlohmann/detail/macro_scope.hpp>
15652
15653// #include <nlohmann/detail/string_concat.hpp>
15654
15655// #include <nlohmann/detail/string_escape.hpp>
15656
15657// #include <nlohmann/detail/string_utils.hpp>
15658
15659// #include <nlohmann/detail/meta/cpp_future.hpp>
15660
15661// #include <nlohmann/detail/meta/type_traits.hpp>
15662
15663// #include <nlohmann/detail/output/binary_writer.hpp>
15664// __ _____ _____ _____
15665// __| | __| | | | JSON for Modern C++
15666// | | |__ | | | | | | version 3.12.0
15667// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15668//
15669// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15670// SPDX-License-Identifier: MIT
15671
15672
15673
15674#include <algorithm> // reverse
15675#include <array> // array
15676#include <map> // map
15677#include <cmath> // isnan, isinf
15678#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
15679#include <cstring> // memcpy
15680#include <limits> // numeric_limits
15681#include <string> // string
15682#include <utility> // move
15683#include <vector> // vector
15684
15685// #include <nlohmann/detail/input/binary_reader.hpp>
15686
15687// #include <nlohmann/detail/macro_scope.hpp>
15688
15689// #include <nlohmann/detail/output/output_adapters.hpp>
15690// __ _____ _____ _____
15691// __| | __| | | | JSON for Modern C++
15692// | | |__ | | | | | | version 3.12.0
15693// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15694//
15695// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15696// SPDX-License-Identifier: MIT
15697
15698
15699
15700#include <algorithm> // copy
15701#include <cstddef> // size_t
15702#include <iterator> // back_inserter
15703#include <memory> // shared_ptr, make_shared
15704#include <string> // basic_string
15705#include <vector> // vector
15706
15707#ifndef JSON_NO_IO
15708 #include <ios> // streamsize
15709 #include <ostream> // basic_ostream
15710#endif // JSON_NO_IO
15711
15712// #include <nlohmann/detail/macro_scope.hpp>
15713
15714
15716namespace detail
15717{
15718
15720template<typename CharType> struct output_adapter_protocol
15721{
15722 virtual void write_character(CharType c) = 0;
15723 virtual void write_characters(const CharType* s, std::size_t length) = 0;
15724 virtual ~output_adapter_protocol() = default;
15725
15730 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
15731};
15732
15734template<typename CharType>
15735using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
15736
15738template<typename CharType, typename AllocatorType = std::allocator<CharType>>
15740{
15741 public:
15742 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
15743 : v(vec)
15744 {}
15745
15746 void write_character(CharType c) override
15747 {
15748 v.push_back(c);
15749 }
15750
15752 void write_characters(const CharType* s, std::size_t length) override
15753 {
15754 v.insert(v.end(), s, s + length);
15755 }
15756
15757 private:
15758 std::vector<CharType, AllocatorType>& v;
15759};
15760
15761#ifndef JSON_NO_IO
15763template<typename CharType>
15765{
15766 public:
15767 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15768 : stream(s)
15769 {}
15770
15771 void write_character(CharType c) override
15772 {
15773 stream.put(c);
15774 }
15775
15777 void write_characters(const CharType* s, std::size_t length) override
15778 {
15779 stream.write(s, static_cast<std::streamsize>(length));
15780 }
15781
15782 private:
15783 std::basic_ostream<CharType>& stream;
15784};
15785#endif // JSON_NO_IO
15786
15788template<typename CharType, typename StringType = std::basic_string<CharType>>
15790{
15791 public:
15792 explicit output_string_adapter(StringType& s) noexcept
15793 : str(s)
15794 {}
15795
15796 void write_character(CharType c) override
15797 {
15798 str.push_back(c);
15799 }
15800
15802 void write_characters(const CharType* s, std::size_t length) override
15803 {
15804 str.append(s, length);
15805 }
15806
15807 private:
15808 StringType& str;
15809};
15810
15811template<typename CharType, typename StringType = std::basic_string<CharType>>
15813{
15814 public:
15815 template<typename AllocatorType = std::allocator<CharType>>
15816 output_adapter(std::vector<CharType, AllocatorType>& vec)
15817 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15818
15819#ifndef JSON_NO_IO
15820 output_adapter(std::basic_ostream<CharType>& s)
15821 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15822#endif // JSON_NO_IO
15823
15824 output_adapter(StringType& s)
15825 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15826
15828 {
15829 return oa;
15830 }
15831
15832 private:
15833 output_adapter_t<CharType> oa = nullptr;
15834};
15835
15836} // namespace detail
15838
15839// #include <nlohmann/detail/string_concat.hpp>
15840
15841
15843namespace detail
15844{
15845
15848{
15849 draft2,
15850 draft3,
15851};
15852
15854// binary writer //
15856
15860template<typename BasicJsonType, typename CharType>
15862{
15863 using string_t = typename BasicJsonType::string_t;
15864 using binary_t = typename BasicJsonType::binary_t;
15865 using number_float_t = typename BasicJsonType::number_float_t;
15866
15867 public:
15873 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15874 {
15875 JSON_ASSERT(oa);
15876 }
15877
15882 void write_bson(const BasicJsonType& j)
15883 {
15884 switch (j.type())
15885 {
15886 case value_t::object:
15887 {
15888 write_bson_object(*j.m_data.m_value.object);
15889 break;
15890 }
15891
15892 case value_t::null:
15893 case value_t::array:
15894 case value_t::string:
15895 case value_t::boolean:
15896 case value_t::number_integer:
15897 case value_t::number_unsigned:
15898 case value_t::number_float:
15899 case value_t::binary:
15900 case value_t::discarded:
15901 default:
15902 {
15903 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15904 }
15905 }
15906 }
15907
15911 void write_cbor(const BasicJsonType& j)
15912 {
15913 switch (j.type())
15914 {
15915 case value_t::null:
15916 {
15917 oa->write_character(to_char_type(0xF6));
15918 break;
15919 }
15920
15921 case value_t::boolean:
15922 {
15923 oa->write_character(j.m_data.m_value.boolean
15924 ? to_char_type(0xF5)
15925 : to_char_type(0xF4));
15926 break;
15927 }
15928
15929 case value_t::number_integer:
15930 {
15931 if (j.m_data.m_value.number_integer >= 0)
15932 {
15933 // CBOR does not differentiate between positive signed
15934 // integers and unsigned integers. Therefore, we used the
15935 // code from the value_t::number_unsigned case here.
15936 if (j.m_data.m_value.number_integer <= 0x17)
15937 {
15938 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15939 }
15940 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15941 {
15942 oa->write_character(to_char_type(0x18));
15943 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15944 }
15945 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15946 {
15947 oa->write_character(to_char_type(0x19));
15948 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15949 }
15950 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15951 {
15952 oa->write_character(to_char_type(0x1A));
15953 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15954 }
15955 else
15956 {
15957 oa->write_character(to_char_type(0x1B));
15958 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15959 }
15960 }
15961 else
15962 {
15963 // The conversions below encode the sign in the first
15964 // byte, and the value is converted to a positive number.
15965 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15966 if (j.m_data.m_value.number_integer >= -24)
15967 {
15968 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15969 }
15970 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15971 {
15972 oa->write_character(to_char_type(0x38));
15973 write_number(static_cast<std::uint8_t>(positive_number));
15974 }
15975 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15976 {
15977 oa->write_character(to_char_type(0x39));
15978 write_number(static_cast<std::uint16_t>(positive_number));
15979 }
15980 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15981 {
15982 oa->write_character(to_char_type(0x3A));
15983 write_number(static_cast<std::uint32_t>(positive_number));
15984 }
15985 else
15986 {
15987 oa->write_character(to_char_type(0x3B));
15988 write_number(static_cast<std::uint64_t>(positive_number));
15989 }
15990 }
15991 break;
15992 }
15993
15994 case value_t::number_unsigned:
15995 {
15996 if (j.m_data.m_value.number_unsigned <= 0x17)
15997 {
15998 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15999 }
16000 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16001 {
16002 oa->write_character(to_char_type(0x18));
16003 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
16004 }
16005 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16006 {
16007 oa->write_character(to_char_type(0x19));
16008 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
16009 }
16010 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16011 {
16012 oa->write_character(to_char_type(0x1A));
16013 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
16014 }
16015 else
16016 {
16017 oa->write_character(to_char_type(0x1B));
16018 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
16019 }
16020 break;
16021 }
16022
16023 case value_t::number_float:
16024 {
16025 if (std::isnan(j.m_data.m_value.number_float))
16026 {
16027 // NaN is 0xf97e00 in CBOR
16028 oa->write_character(to_char_type(0xF9));
16029 oa->write_character(to_char_type(0x7E));
16030 oa->write_character(to_char_type(0x00));
16031 }
16032 else if (std::isinf(j.m_data.m_value.number_float))
16033 {
16034 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
16035 oa->write_character(to_char_type(0xf9));
16036 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
16037 oa->write_character(to_char_type(0x00));
16038 }
16039 else
16040 {
16041 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
16042 }
16043 break;
16044 }
16045
16046 case value_t::string:
16047 {
16048 // step 1: write control byte and the string length
16049 const auto N = j.m_data.m_value.string->size();
16050 if (N <= 0x17)
16051 {
16052 write_number(static_cast<std::uint8_t>(0x60 + N));
16053 }
16054 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16055 {
16056 oa->write_character(to_char_type(0x78));
16057 write_number(static_cast<std::uint8_t>(N));
16058 }
16059 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16060 {
16061 oa->write_character(to_char_type(0x79));
16062 write_number(static_cast<std::uint16_t>(N));
16063 }
16064 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16065 {
16066 oa->write_character(to_char_type(0x7A));
16067 write_number(static_cast<std::uint32_t>(N));
16068 }
16069 // LCOV_EXCL_START
16070 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16071 {
16072 oa->write_character(to_char_type(0x7B));
16073 write_number(static_cast<std::uint64_t>(N));
16074 }
16075 // LCOV_EXCL_STOP
16076
16077 // step 2: write the string
16078 oa->write_characters(
16079 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16080 j.m_data.m_value.string->size());
16081 break;
16082 }
16083
16084 case value_t::array:
16085 {
16086 // step 1: write control byte and the array size
16087 const auto N = j.m_data.m_value.array->size();
16088 if (N <= 0x17)
16089 {
16090 write_number(static_cast<std::uint8_t>(0x80 + N));
16091 }
16092 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16093 {
16094 oa->write_character(to_char_type(0x98));
16095 write_number(static_cast<std::uint8_t>(N));
16096 }
16097 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16098 {
16099 oa->write_character(to_char_type(0x99));
16100 write_number(static_cast<std::uint16_t>(N));
16101 }
16102 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16103 {
16104 oa->write_character(to_char_type(0x9A));
16105 write_number(static_cast<std::uint32_t>(N));
16106 }
16107 // LCOV_EXCL_START
16108 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16109 {
16110 oa->write_character(to_char_type(0x9B));
16111 write_number(static_cast<std::uint64_t>(N));
16112 }
16113 // LCOV_EXCL_STOP
16114
16115 // step 2: write each element
16116 for (const auto& el : *j.m_data.m_value.array)
16117 {
16118 write_cbor(el);
16119 }
16120 break;
16121 }
16122
16123 case value_t::binary:
16124 {
16125 if (j.m_data.m_value.binary->has_subtype())
16126 {
16127 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
16128 {
16129 write_number(static_cast<std::uint8_t>(0xd8));
16130 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
16131 }
16132 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
16133 {
16134 write_number(static_cast<std::uint8_t>(0xd9));
16135 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
16136 }
16137 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
16138 {
16139 write_number(static_cast<std::uint8_t>(0xda));
16140 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
16141 }
16142 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
16143 {
16144 write_number(static_cast<std::uint8_t>(0xdb));
16145 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
16146 }
16147 }
16148
16149 // step 1: write control byte and the binary array size
16150 const auto N = j.m_data.m_value.binary->size();
16151 if (N <= 0x17)
16152 {
16153 write_number(static_cast<std::uint8_t>(0x40 + N));
16154 }
16155 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16156 {
16157 oa->write_character(to_char_type(0x58));
16158 write_number(static_cast<std::uint8_t>(N));
16159 }
16160 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16161 {
16162 oa->write_character(to_char_type(0x59));
16163 write_number(static_cast<std::uint16_t>(N));
16164 }
16165 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16166 {
16167 oa->write_character(to_char_type(0x5A));
16168 write_number(static_cast<std::uint32_t>(N));
16169 }
16170 // LCOV_EXCL_START
16171 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16172 {
16173 oa->write_character(to_char_type(0x5B));
16174 write_number(static_cast<std::uint64_t>(N));
16175 }
16176 // LCOV_EXCL_STOP
16177
16178 // step 2: write each element
16179 oa->write_characters(
16180 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16181 N);
16182
16183 break;
16184 }
16185
16186 case value_t::object:
16187 {
16188 // step 1: write control byte and the object size
16189 const auto N = j.m_data.m_value.object->size();
16190 if (N <= 0x17)
16191 {
16192 write_number(static_cast<std::uint8_t>(0xA0 + N));
16193 }
16194 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16195 {
16196 oa->write_character(to_char_type(0xB8));
16197 write_number(static_cast<std::uint8_t>(N));
16198 }
16199 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16200 {
16201 oa->write_character(to_char_type(0xB9));
16202 write_number(static_cast<std::uint16_t>(N));
16203 }
16204 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16205 {
16206 oa->write_character(to_char_type(0xBA));
16207 write_number(static_cast<std::uint32_t>(N));
16208 }
16209 // LCOV_EXCL_START
16210 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16211 {
16212 oa->write_character(to_char_type(0xBB));
16213 write_number(static_cast<std::uint64_t>(N));
16214 }
16215 // LCOV_EXCL_STOP
16216
16217 // step 2: write each element
16218 for (const auto& el : *j.m_data.m_value.object)
16219 {
16220 write_cbor(el.first);
16221 write_cbor(el.second);
16222 }
16223 break;
16224 }
16225
16226 case value_t::discarded:
16227 default:
16228 break;
16229 }
16230 }
16231
16235 void write_msgpack(const BasicJsonType& j)
16236 {
16237 switch (j.type())
16238 {
16239 case value_t::null: // nil
16240 {
16241 oa->write_character(to_char_type(0xC0));
16242 break;
16243 }
16244
16245 case value_t::boolean: // true and false
16246 {
16247 oa->write_character(j.m_data.m_value.boolean
16248 ? to_char_type(0xC3)
16249 : to_char_type(0xC2));
16250 break;
16251 }
16252
16253 case value_t::number_integer:
16254 {
16255 if (j.m_data.m_value.number_integer >= 0)
16256 {
16257 // MessagePack does not differentiate between positive
16258 // signed integers and unsigned integers. Therefore, we used
16259 // the code from the value_t::number_unsigned case here.
16260 if (j.m_data.m_value.number_unsigned < 128)
16261 {
16262 // positive fixnum
16263 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16264 }
16265 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16266 {
16267 // uint 8
16268 oa->write_character(to_char_type(0xCC));
16269 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16270 }
16271 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16272 {
16273 // uint 16
16274 oa->write_character(to_char_type(0xCD));
16275 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16276 }
16277 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16278 {
16279 // uint 32
16280 oa->write_character(to_char_type(0xCE));
16281 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16282 }
16283 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16284 {
16285 // uint 64
16286 oa->write_character(to_char_type(0xCF));
16287 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16288 }
16289 }
16290 else
16291 {
16292 if (j.m_data.m_value.number_integer >= -32)
16293 {
16294 // negative fixnum
16295 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16296 }
16297 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
16298 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16299 {
16300 // int 8
16301 oa->write_character(to_char_type(0xD0));
16302 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16303 }
16304 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
16305 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16306 {
16307 // int 16
16308 oa->write_character(to_char_type(0xD1));
16309 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
16310 }
16311 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
16312 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16313 {
16314 // int 32
16315 oa->write_character(to_char_type(0xD2));
16316 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
16317 }
16318 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
16319 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16320 {
16321 // int 64
16322 oa->write_character(to_char_type(0xD3));
16323 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
16324 }
16325 }
16326 break;
16327 }
16328
16329 case value_t::number_unsigned:
16330 {
16331 if (j.m_data.m_value.number_unsigned < 128)
16332 {
16333 // positive fixnum
16334 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16335 }
16336 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16337 {
16338 // uint 8
16339 oa->write_character(to_char_type(0xCC));
16340 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16341 }
16342 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16343 {
16344 // uint 16
16345 oa->write_character(to_char_type(0xCD));
16346 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16347 }
16348 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16349 {
16350 // uint 32
16351 oa->write_character(to_char_type(0xCE));
16352 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16353 }
16354 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16355 {
16356 // uint 64
16357 oa->write_character(to_char_type(0xCF));
16358 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16359 }
16360 break;
16361 }
16362
16363 case value_t::number_float:
16364 {
16365 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
16366 break;
16367 }
16368
16369 case value_t::string:
16370 {
16371 // step 1: write control byte and the string length
16372 const auto N = j.m_data.m_value.string->size();
16373 if (N <= 31)
16374 {
16375 // fixstr
16376 write_number(static_cast<std::uint8_t>(0xA0 | N));
16377 }
16378 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16379 {
16380 // str 8
16381 oa->write_character(to_char_type(0xD9));
16382 write_number(static_cast<std::uint8_t>(N));
16383 }
16384 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16385 {
16386 // str 16
16387 oa->write_character(to_char_type(0xDA));
16388 write_number(static_cast<std::uint16_t>(N));
16389 }
16390 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16391 {
16392 // str 32
16393 oa->write_character(to_char_type(0xDB));
16394 write_number(static_cast<std::uint32_t>(N));
16395 }
16396
16397 // step 2: write the string
16398 oa->write_characters(
16399 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16400 j.m_data.m_value.string->size());
16401 break;
16402 }
16403
16404 case value_t::array:
16405 {
16406 // step 1: write control byte and the array size
16407 const auto N = j.m_data.m_value.array->size();
16408 if (N <= 15)
16409 {
16410 // fixarray
16411 write_number(static_cast<std::uint8_t>(0x90 | N));
16412 }
16413 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16414 {
16415 // array 16
16416 oa->write_character(to_char_type(0xDC));
16417 write_number(static_cast<std::uint16_t>(N));
16418 }
16419 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16420 {
16421 // array 32
16422 oa->write_character(to_char_type(0xDD));
16423 write_number(static_cast<std::uint32_t>(N));
16424 }
16425
16426 // step 2: write each element
16427 for (const auto& el : *j.m_data.m_value.array)
16428 {
16429 write_msgpack(el);
16430 }
16431 break;
16432 }
16433
16434 case value_t::binary:
16435 {
16436 // step 0: determine if the binary type has a set subtype to
16437 // determine whether to use the ext or fixext types
16438 const bool use_ext = j.m_data.m_value.binary->has_subtype();
16439
16440 // step 1: write control byte and the byte string length
16441 const auto N = j.m_data.m_value.binary->size();
16442 if (N <= (std::numeric_limits<std::uint8_t>::max)())
16443 {
16444 std::uint8_t output_type{};
16445 bool fixed = true;
16446 if (use_ext)
16447 {
16448 switch (N)
16449 {
16450 case 1:
16451 output_type = 0xD4; // fixext 1
16452 break;
16453 case 2:
16454 output_type = 0xD5; // fixext 2
16455 break;
16456 case 4:
16457 output_type = 0xD6; // fixext 4
16458 break;
16459 case 8:
16460 output_type = 0xD7; // fixext 8
16461 break;
16462 case 16:
16463 output_type = 0xD8; // fixext 16
16464 break;
16465 default:
16466 output_type = 0xC7; // ext 8
16467 fixed = false;
16468 break;
16469 }
16470
16471 }
16472 else
16473 {
16474 output_type = 0xC4; // bin 8
16475 fixed = false;
16476 }
16477
16478 oa->write_character(to_char_type(output_type));
16479 if (!fixed)
16480 {
16481 write_number(static_cast<std::uint8_t>(N));
16482 }
16483 }
16484 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16485 {
16486 const std::uint8_t output_type = use_ext
16487 ? 0xC8 // ext 16
16488 : 0xC5; // bin 16
16489
16490 oa->write_character(to_char_type(output_type));
16491 write_number(static_cast<std::uint16_t>(N));
16492 }
16493 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16494 {
16495 const std::uint8_t output_type = use_ext
16496 ? 0xC9 // ext 32
16497 : 0xC6; // bin 32
16498
16499 oa->write_character(to_char_type(output_type));
16500 write_number(static_cast<std::uint32_t>(N));
16501 }
16502
16503 // step 1.5: if this is an ext type, write the subtype
16504 if (use_ext)
16505 {
16506 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
16507 }
16508
16509 // step 2: write the byte string
16510 oa->write_characters(
16511 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16512 N);
16513
16514 break;
16515 }
16516
16517 case value_t::object:
16518 {
16519 // step 1: write control byte and the object size
16520 const auto N = j.m_data.m_value.object->size();
16521 if (N <= 15)
16522 {
16523 // fixmap
16524 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
16525 }
16526 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16527 {
16528 // map 16
16529 oa->write_character(to_char_type(0xDE));
16530 write_number(static_cast<std::uint16_t>(N));
16531 }
16532 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16533 {
16534 // map 32
16535 oa->write_character(to_char_type(0xDF));
16536 write_number(static_cast<std::uint32_t>(N));
16537 }
16538
16539 // step 2: write each element
16540 for (const auto& el : *j.m_data.m_value.object)
16541 {
16542 write_msgpack(el.first);
16543 write_msgpack(el.second);
16544 }
16545 break;
16546 }
16547
16548 case value_t::discarded:
16549 default:
16550 break;
16551 }
16552 }
16553
16562 void write_ubjson(const BasicJsonType& j, const bool use_count,
16563 const bool use_type, const bool add_prefix = true,
16564 const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2)
16565 {
16566 const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3;
16567
16568 switch (j.type())
16569 {
16570 case value_t::null:
16571 {
16572 if (add_prefix)
16573 {
16574 oa->write_character(to_char_type('Z'));
16575 }
16576 break;
16577 }
16578
16579 case value_t::boolean:
16580 {
16581 if (add_prefix)
16582 {
16583 oa->write_character(j.m_data.m_value.boolean
16584 ? to_char_type('T')
16585 : to_char_type('F'));
16586 }
16587 break;
16588 }
16589
16590 case value_t::number_integer:
16591 {
16592 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
16593 break;
16594 }
16595
16596 case value_t::number_unsigned:
16597 {
16598 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
16599 break;
16600 }
16601
16602 case value_t::number_float:
16603 {
16604 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
16605 break;
16606 }
16607
16608 case value_t::string:
16609 {
16610 if (add_prefix)
16611 {
16612 oa->write_character(to_char_type('S'));
16613 }
16614 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
16615 oa->write_characters(
16616 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16617 j.m_data.m_value.string->size());
16618 break;
16619 }
16620
16621 case value_t::array:
16622 {
16623 if (add_prefix)
16624 {
16625 oa->write_character(to_char_type('['));
16626 }
16627
16628 bool prefix_required = true;
16629 if (use_type && !j.m_data.m_value.array->empty())
16630 {
16631 JSON_ASSERT(use_count);
16632 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16633 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
16634 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16635 {
16636 return ubjson_prefix(v, use_bjdata) == first_prefix;
16637 });
16638
16639 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16640
16641 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16642 {
16643 prefix_required = false;
16644 oa->write_character(to_char_type('$'));
16645 oa->write_character(first_prefix);
16646 }
16647 }
16648
16649 if (use_count)
16650 {
16651 oa->write_character(to_char_type('#'));
16652 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
16653 }
16654
16655 for (const auto& el : *j.m_data.m_value.array)
16656 {
16657 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16658 }
16659
16660 if (!use_count)
16661 {
16662 oa->write_character(to_char_type(']'));
16663 }
16664
16665 break;
16666 }
16667
16668 case value_t::binary:
16669 {
16670 if (add_prefix)
16671 {
16672 oa->write_character(to_char_type('['));
16673 }
16674
16675 if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
16676 {
16677 JSON_ASSERT(use_count);
16678 oa->write_character(to_char_type('$'));
16679 oa->write_character(bjdata_draft3 ? 'B' : 'U');
16680 }
16681
16682 if (use_count)
16683 {
16684 oa->write_character(to_char_type('#'));
16685 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
16686 }
16687
16688 if (use_type)
16689 {
16690 oa->write_characters(
16691 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16692 j.m_data.m_value.binary->size());
16693 }
16694 else
16695 {
16696 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
16697 {
16698 oa->write_character(to_char_type(bjdata_draft3 ? 'B' : 'U'));
16699 oa->write_character(j.m_data.m_value.binary->data()[i]);
16700 }
16701 }
16702
16703 if (!use_count)
16704 {
16705 oa->write_character(to_char_type(']'));
16706 }
16707
16708 break;
16709 }
16710
16711 case value_t::object:
16712 {
16713 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())
16714 {
16715 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)
16716 {
16717 break;
16718 }
16719 }
16720
16721 if (add_prefix)
16722 {
16723 oa->write_character(to_char_type('{'));
16724 }
16725
16726 bool prefix_required = true;
16727 if (use_type && !j.m_data.m_value.object->empty())
16728 {
16729 JSON_ASSERT(use_count);
16730 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16731 const bool same_prefix = std::all_of(j.begin(), j.end(),
16732 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16733 {
16734 return ubjson_prefix(v, use_bjdata) == first_prefix;
16735 });
16736
16737 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16738
16739 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16740 {
16741 prefix_required = false;
16742 oa->write_character(to_char_type('$'));
16743 oa->write_character(first_prefix);
16744 }
16745 }
16746
16747 if (use_count)
16748 {
16749 oa->write_character(to_char_type('#'));
16750 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
16751 }
16752
16753 for (const auto& el : *j.m_data.m_value.object)
16754 {
16755 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
16756 oa->write_characters(
16757 reinterpret_cast<const CharType*>(el.first.c_str()),
16758 el.first.size());
16759 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16760 }
16761
16762 if (!use_count)
16763 {
16764 oa->write_character(to_char_type('}'));
16765 }
16766
16767 break;
16768 }
16769
16770 case value_t::discarded:
16771 default:
16772 break;
16773 }
16774 }
16775
16776 private:
16778 // BSON //
16780
16785 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16786 {
16787 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16788 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16789 {
16790 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16791 }
16792
16793 static_cast<void>(j);
16794 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16795 }
16796
16800 void write_bson_entry_header(const string_t& name,
16801 const std::uint8_t element_type)
16802 {
16803 oa->write_character(to_char_type(element_type)); // boolean
16804 oa->write_characters(
16805 reinterpret_cast<const CharType*>(name.c_str()),
16806 name.size() + 1u);
16807 }
16808
16812 void write_bson_boolean(const string_t& name,
16813 const bool value)
16814 {
16815 write_bson_entry_header(name, 0x08);
16816 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16817 }
16818
16822 void write_bson_double(const string_t& name,
16823 const double value)
16824 {
16825 write_bson_entry_header(name, 0x01);
16826 write_number<double>(value, true);
16827 }
16828
16832 static std::size_t calc_bson_string_size(const string_t& value)
16833 {
16834 return sizeof(std::int32_t) + value.size() + 1ul;
16835 }
16836
16840 void write_bson_string(const string_t& name,
16841 const string_t& value)
16842 {
16843 write_bson_entry_header(name, 0x02);
16844
16845 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16846 oa->write_characters(
16847 reinterpret_cast<const CharType*>(value.c_str()),
16848 value.size() + 1);
16849 }
16850
16854 void write_bson_null(const string_t& name)
16855 {
16856 write_bson_entry_header(name, 0x0A);
16857 }
16858
16862 static std::size_t calc_bson_integer_size(const std::int64_t value)
16863 {
16864 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16865 ? sizeof(std::int32_t)
16866 : sizeof(std::int64_t);
16867 }
16868
16872 void write_bson_integer(const string_t& name,
16873 const std::int64_t value)
16874 {
16875 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16876 {
16877 write_bson_entry_header(name, 0x10); // int32
16878 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16879 }
16880 else
16881 {
16882 write_bson_entry_header(name, 0x12); // int64
16883 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16884 }
16885 }
16886
16890 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16891 {
16892 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16893 ? sizeof(std::int32_t)
16894 : sizeof(std::int64_t);
16895 }
16896
16900 void write_bson_unsigned(const string_t& name,
16901 const BasicJsonType& j)
16902 {
16903 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16904 {
16905 write_bson_entry_header(name, 0x10 /* int32 */);
16906 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16907 }
16908 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16909 {
16910 write_bson_entry_header(name, 0x12 /* int64 */);
16911 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16912 }
16913 else
16914 {
16915 write_bson_entry_header(name, 0x11 /* uint64 */);
16916 write_number<std::uint64_t>(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned), true);
16917 }
16918 }
16919
16923 void write_bson_object_entry(const string_t& name,
16924 const typename BasicJsonType::object_t& value)
16925 {
16926 write_bson_entry_header(name, 0x03); // object
16927 write_bson_object(value);
16928 }
16929
16933 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16934 {
16935 std::size_t array_index = 0ul;
16936
16937 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)
16938 {
16939 return result + calc_bson_element_size(std::to_string(array_index++), el);
16940 });
16941
16942 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16943 }
16944
16948 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16949 {
16950 return sizeof(std::int32_t) + value.size() + 1ul;
16951 }
16952
16956 void write_bson_array(const string_t& name,
16957 const typename BasicJsonType::array_t& value)
16958 {
16959 write_bson_entry_header(name, 0x04); // array
16960 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16961
16962 std::size_t array_index = 0ul;
16963
16964 for (const auto& el : value)
16965 {
16966 write_bson_element(std::to_string(array_index++), el);
16967 }
16968
16969 oa->write_character(to_char_type(0x00));
16970 }
16971
16975 void write_bson_binary(const string_t& name,
16976 const binary_t& value)
16977 {
16978 write_bson_entry_header(name, 0x05);
16979
16980 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16981 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16982
16983 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16984 }
16985
16990 static std::size_t calc_bson_element_size(const string_t& name,
16991 const BasicJsonType& j)
16992 {
16993 const auto header_size = calc_bson_entry_header_size(name, j);
16994 switch (j.type())
16995 {
16996 case value_t::object:
16997 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16998
16999 case value_t::array:
17000 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
17001
17002 case value_t::binary:
17003 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
17004
17005 case value_t::boolean:
17006 return header_size + 1ul;
17007
17008 case value_t::number_float:
17009 return header_size + 8ul;
17010
17011 case value_t::number_integer:
17012 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
17013
17014 case value_t::number_unsigned:
17015 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
17016
17017 case value_t::string:
17018 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
17019
17020 case value_t::null:
17021 return header_size + 0ul;
17022
17023 // LCOV_EXCL_START
17024 case value_t::discarded:
17025 default:
17026 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17027 return 0ul;
17028 // LCOV_EXCL_STOP
17029 }
17030 }
17031
17038 void write_bson_element(const string_t& name,
17039 const BasicJsonType& j)
17040 {
17041 switch (j.type())
17042 {
17043 case value_t::object:
17044 return write_bson_object_entry(name, *j.m_data.m_value.object);
17045
17046 case value_t::array:
17047 return write_bson_array(name, *j.m_data.m_value.array);
17048
17049 case value_t::binary:
17050 return write_bson_binary(name, *j.m_data.m_value.binary);
17051
17052 case value_t::boolean:
17053 return write_bson_boolean(name, j.m_data.m_value.boolean);
17054
17055 case value_t::number_float:
17056 return write_bson_double(name, j.m_data.m_value.number_float);
17057
17058 case value_t::number_integer:
17059 return write_bson_integer(name, j.m_data.m_value.number_integer);
17060
17061 case value_t::number_unsigned:
17062 return write_bson_unsigned(name, j);
17063
17064 case value_t::string:
17065 return write_bson_string(name, *j.m_data.m_value.string);
17066
17067 case value_t::null:
17068 return write_bson_null(name);
17069
17070 // LCOV_EXCL_START
17071 case value_t::discarded:
17072 default:
17073 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17074 return;
17075 // LCOV_EXCL_STOP
17076 }
17077 }
17078
17085 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
17086 {
17087 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
17088 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
17089 {
17090 return result += calc_bson_element_size(el.first, el.second);
17091 });
17092
17093 return sizeof(std::int32_t) + document_size + 1ul;
17094 }
17095
17100 void write_bson_object(const typename BasicJsonType::object_t& value)
17101 {
17102 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
17103
17104 for (const auto& el : value)
17105 {
17106 write_bson_element(el.first, el.second);
17107 }
17108
17109 oa->write_character(to_char_type(0x00));
17110 }
17111
17113 // CBOR //
17115
17116 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
17117 {
17118 return to_char_type(0xFA); // Single-Precision Float
17119 }
17120
17121 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
17122 {
17123 return to_char_type(0xFB); // Double-Precision Float
17124 }
17125
17127 // MsgPack //
17129
17130 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
17131 {
17132 return to_char_type(0xCA); // float 32
17133 }
17134
17135 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
17136 {
17137 return to_char_type(0xCB); // float 64
17138 }
17139
17141 // UBJSON //
17143
17144 // UBJSON: write number (floating point)
17145 template<typename NumberType, typename std::enable_if<
17146 std::is_floating_point<NumberType>::value, int>::type = 0>
17147 void write_number_with_ubjson_prefix(const NumberType n,
17148 const bool add_prefix,
17149 const bool use_bjdata)
17150 {
17151 if (add_prefix)
17152 {
17153 oa->write_character(get_ubjson_float_prefix(n));
17154 }
17155 write_number(n, use_bjdata);
17156 }
17157
17158 // UBJSON: write number (unsigned integer)
17159 template<typename NumberType, typename std::enable_if<
17160 std::is_unsigned<NumberType>::value, int>::type = 0>
17161 void write_number_with_ubjson_prefix(const NumberType n,
17162 const bool add_prefix,
17163 const bool use_bjdata)
17164 {
17165 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17166 {
17167 if (add_prefix)
17168 {
17169 oa->write_character(to_char_type('i')); // int8
17170 }
17171 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17172 }
17173 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
17174 {
17175 if (add_prefix)
17176 {
17177 oa->write_character(to_char_type('U')); // uint8
17178 }
17179 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17180 }
17181 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17182 {
17183 if (add_prefix)
17184 {
17185 oa->write_character(to_char_type('I')); // int16
17186 }
17187 write_number(static_cast<std::int16_t>(n), use_bjdata);
17188 }
17189 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
17190 {
17191 if (add_prefix)
17192 {
17193 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17194 }
17195 write_number(static_cast<std::uint16_t>(n), use_bjdata);
17196 }
17197 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17198 {
17199 if (add_prefix)
17200 {
17201 oa->write_character(to_char_type('l')); // int32
17202 }
17203 write_number(static_cast<std::int32_t>(n), use_bjdata);
17204 }
17205 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
17206 {
17207 if (add_prefix)
17208 {
17209 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17210 }
17211 write_number(static_cast<std::uint32_t>(n), use_bjdata);
17212 }
17213 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17214 {
17215 if (add_prefix)
17216 {
17217 oa->write_character(to_char_type('L')); // int64
17218 }
17219 write_number(static_cast<std::int64_t>(n), use_bjdata);
17220 }
17221 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
17222 {
17223 if (add_prefix)
17224 {
17225 oa->write_character(to_char_type('M')); // uint64 - bjdata only
17226 }
17227 write_number(static_cast<std::uint64_t>(n), use_bjdata);
17228 }
17229 else
17230 {
17231 if (add_prefix)
17232 {
17233 oa->write_character(to_char_type('H')); // high-precision number
17234 }
17235
17236 const auto number = BasicJsonType(n).dump();
17237 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17238 for (std::size_t i = 0; i < number.size(); ++i)
17239 {
17240 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17241 }
17242 }
17243 }
17244
17245 // UBJSON: write number (signed integer)
17246 template < typename NumberType, typename std::enable_if <
17247 std::is_signed<NumberType>::value&&
17248 !std::is_floating_point<NumberType>::value, int >::type = 0 >
17249 void write_number_with_ubjson_prefix(const NumberType n,
17250 const bool add_prefix,
17251 const bool use_bjdata)
17252 {
17253 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
17254 {
17255 if (add_prefix)
17256 {
17257 oa->write_character(to_char_type('i')); // int8
17258 }
17259 write_number(static_cast<std::int8_t>(n), use_bjdata);
17260 }
17261 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)()))
17262 {
17263 if (add_prefix)
17264 {
17265 oa->write_character(to_char_type('U')); // uint8
17266 }
17267 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17268 }
17269 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
17270 {
17271 if (add_prefix)
17272 {
17273 oa->write_character(to_char_type('I')); // int16
17274 }
17275 write_number(static_cast<std::int16_t>(n), use_bjdata);
17276 }
17277 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)())))
17278 {
17279 if (add_prefix)
17280 {
17281 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17282 }
17283 write_number(static_cast<uint16_t>(n), use_bjdata);
17284 }
17285 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
17286 {
17287 if (add_prefix)
17288 {
17289 oa->write_character(to_char_type('l')); // int32
17290 }
17291 write_number(static_cast<std::int32_t>(n), use_bjdata);
17292 }
17293 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)())))
17294 {
17295 if (add_prefix)
17296 {
17297 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17298 }
17299 write_number(static_cast<uint32_t>(n), use_bjdata);
17300 }
17301 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
17302 {
17303 if (add_prefix)
17304 {
17305 oa->write_character(to_char_type('L')); // int64
17306 }
17307 write_number(static_cast<std::int64_t>(n), use_bjdata);
17308 }
17309 // LCOV_EXCL_START
17310 else
17311 {
17312 if (add_prefix)
17313 {
17314 oa->write_character(to_char_type('H')); // high-precision number
17315 }
17316
17317 const auto number = BasicJsonType(n).dump();
17318 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17319 for (std::size_t i = 0; i < number.size(); ++i)
17320 {
17321 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17322 }
17323 }
17324 // LCOV_EXCL_STOP
17325 }
17326
17330 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
17331 {
17332 switch (j.type())
17333 {
17334 case value_t::null:
17335 return 'Z';
17336
17337 case value_t::boolean:
17338 return j.m_data.m_value.boolean ? 'T' : 'F';
17339
17340 case value_t::number_integer:
17341 {
17342 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)())
17343 {
17344 return 'i';
17345 }
17346 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)())
17347 {
17348 return 'U';
17349 }
17350 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)())
17351 {
17352 return 'I';
17353 }
17354 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)()))
17355 {
17356 return 'u';
17357 }
17358 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)())
17359 {
17360 return 'l';
17361 }
17362 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)()))
17363 {
17364 return 'm';
17365 }
17366 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)())
17367 {
17368 return 'L';
17369 }
17370 // anything else is treated as a high-precision number
17371 return 'H'; // LCOV_EXCL_LINE
17372 }
17373
17374 case value_t::number_unsigned:
17375 {
17376 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17377 {
17378 return 'i';
17379 }
17380 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
17381 {
17382 return 'U';
17383 }
17384 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17385 {
17386 return 'I';
17387 }
17388 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
17389 {
17390 return 'u';
17391 }
17392 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17393 {
17394 return 'l';
17395 }
17396 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
17397 {
17398 return 'm';
17399 }
17400 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17401 {
17402 return 'L';
17403 }
17404 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
17405 {
17406 return 'M';
17407 }
17408 // anything else is treated as a high-precision number
17409 return 'H'; // LCOV_EXCL_LINE
17410 }
17411
17412 case value_t::number_float:
17413 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
17414
17415 case value_t::string:
17416 return 'S';
17417
17418 case value_t::array: // fallthrough
17419 case value_t::binary:
17420 return '[';
17421
17422 case value_t::object:
17423 return '{';
17424
17425 case value_t::discarded:
17426 default: // discarded values
17427 return 'N';
17428 }
17429 }
17430
17431 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
17432 {
17433 return 'd'; // float 32
17434 }
17435
17436 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
17437 {
17438 return 'D'; // float 64
17439 }
17440
17444 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
17445 {
17446 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
17447 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'},
17448 {"char", 'C'}, {"byte", 'B'}
17449 };
17450
17451 string_t key = "_ArrayType_";
17452 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
17453 if (it == bjdtype.end())
17454 {
17455 return true;
17456 }
17457 CharType dtype = it->second;
17458
17459 key = "_ArraySize_";
17460 std::size_t len = (value.at(key).empty() ? 0 : 1);
17461 for (const auto& el : value.at(key))
17462 {
17463 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
17464 }
17465
17466 key = "_ArrayData_";
17467 if (value.at(key).size() != len)
17468 {
17469 return true;
17470 }
17471
17472 oa->write_character('[');
17473 oa->write_character('$');
17474 oa->write_character(dtype);
17475 oa->write_character('#');
17476
17477 key = "_ArraySize_";
17478 write_ubjson(value.at(key), use_count, use_type, true, true, bjdata_version);
17479
17480 key = "_ArrayData_";
17481 if (dtype == 'U' || dtype == 'C' || dtype == 'B')
17482 {
17483 for (const auto& el : value.at(key))
17484 {
17485 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
17486 }
17487 }
17488 else if (dtype == 'i')
17489 {
17490 for (const auto& el : value.at(key))
17491 {
17492 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
17493 }
17494 }
17495 else if (dtype == 'u')
17496 {
17497 for (const auto& el : value.at(key))
17498 {
17499 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
17500 }
17501 }
17502 else if (dtype == 'I')
17503 {
17504 for (const auto& el : value.at(key))
17505 {
17506 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
17507 }
17508 }
17509 else if (dtype == 'm')
17510 {
17511 for (const auto& el : value.at(key))
17512 {
17513 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
17514 }
17515 }
17516 else if (dtype == 'l')
17517 {
17518 for (const auto& el : value.at(key))
17519 {
17520 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
17521 }
17522 }
17523 else if (dtype == 'M')
17524 {
17525 for (const auto& el : value.at(key))
17526 {
17527 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
17528 }
17529 }
17530 else if (dtype == 'L')
17531 {
17532 for (const auto& el : value.at(key))
17533 {
17534 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
17535 }
17536 }
17537 else if (dtype == 'd')
17538 {
17539 for (const auto& el : value.at(key))
17540 {
17541 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
17542 }
17543 }
17544 else if (dtype == 'D')
17545 {
17546 for (const auto& el : value.at(key))
17547 {
17548 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
17549 }
17550 }
17551 return false;
17552 }
17553
17555 // Utility functions //
17557
17558 /*
17559 @brief write a number to output input
17560 @param[in] n number of type @a NumberType
17561 @param[in] OutputIsLittleEndian Set to true if output data is
17562 required to be little endian
17563 @tparam NumberType the type of the number
17564
17565 @note This function needs to respect the system's endianness, because bytes
17566 in CBOR, MessagePack, and UBJSON are stored in network order (big
17567 endian) and therefore need reordering on little endian systems.
17568 On the other hand, BSON and BJData use little endian and should reorder
17569 on big endian systems.
17570 */
17571 template<typename NumberType>
17572 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
17573 {
17574 // step 1: write the number to an array of length NumberType
17575 std::array<CharType, sizeof(NumberType)> vec{};
17576 std::memcpy(vec.data(), &n, sizeof(NumberType));
17577
17578 // step 2: write the array to output (with possible reordering)
17579 if (is_little_endian != OutputIsLittleEndian)
17580 {
17581 // reverse byte order prior to conversion if necessary
17582 std::reverse(vec.begin(), vec.end());
17583 }
17584
17585 oa->write_characters(vec.data(), sizeof(NumberType));
17586 }
17587
17588 void write_compact_float(const number_float_t n, detail::input_format_t format)
17589 {
17590#ifdef __GNUC__
17591#pragma GCC diagnostic push
17592#pragma GCC diagnostic ignored "-Wfloat-equal"
17593#endif
17594 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
17595 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
17596 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
17597 {
17598 oa->write_character(format == detail::input_format_t::cbor
17599 ? get_cbor_float_prefix(static_cast<float>(n))
17600 : get_msgpack_float_prefix(static_cast<float>(n)));
17601 write_number(static_cast<float>(n));
17602 }
17603 else
17604 {
17605 oa->write_character(format == detail::input_format_t::cbor
17606 ? get_cbor_float_prefix(n)
17607 : get_msgpack_float_prefix(n));
17608 write_number(n);
17609 }
17610#ifdef __GNUC__
17611#pragma GCC diagnostic pop
17612#endif
17613 }
17614
17615 public:
17616 // The following to_char_type functions are implement the conversion
17617 // between uint8_t and CharType. In case CharType is not unsigned,
17618 // such a conversion is required to allow values greater than 128.
17619 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
17620 template < typename C = CharType,
17621 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
17622 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17623 {
17624 return *reinterpret_cast<char*>(&x);
17625 }
17626
17627 template < typename C = CharType,
17628 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
17629 static CharType to_char_type(std::uint8_t x) noexcept
17630 {
17631 // The std::is_trivial trait is deprecated in C++26. The replacement is to use
17632 // std::is_trivially_copyable and std::is_trivially_default_constructible.
17633 // However, some older library implementations support std::is_trivial
17634 // but not all the std::is_trivially_* traits.
17635 // Since detecting full support across all libraries is difficult,
17636 // we use std::is_trivial unless we are using a standard where it has been deprecated.
17637 // For more details, see: https://github.com/nlohmann/json/pull/4775#issuecomment-2884361627
17638#ifdef JSON_HAS_CPP_26
17639 static_assert(std::is_trivially_copyable<CharType>::value, "CharType must be trivially copyable");
17640 static_assert(std::is_trivially_default_constructible<CharType>::value, "CharType must be trivially default constructible");
17641#else
17642 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
17643#endif
17644
17645 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
17646 CharType result;
17647 std::memcpy(&result, &x, sizeof(x));
17648 return result;
17649 }
17650
17651 template<typename C = CharType,
17653 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17654 {
17655 return x;
17656 }
17657
17658 template < typename InputCharType, typename C = CharType,
17659 enable_if_t <
17660 std::is_signed<C>::value &&
17661 std::is_signed<char>::value &&
17662 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
17663 > * = nullptr >
17664 static constexpr CharType to_char_type(InputCharType x) noexcept
17665 {
17666 return x;
17667 }
17668
17669 private:
17671 const bool is_little_endian = little_endianness();
17672
17674 output_adapter_t<CharType> oa = nullptr;
17675};
17676
17677} // namespace detail
17679
17680// #include <nlohmann/detail/output/output_adapters.hpp>
17681
17682// #include <nlohmann/detail/output/serializer.hpp>
17683// __ _____ _____ _____
17684// __| | __| | | | JSON for Modern C++
17685// | | |__ | | | | | | version 3.12.0
17686// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17687//
17688// SPDX-FileCopyrightText: 2008 - 2009 Björn Hoehrmann <bjoern@hoehrmann.de>
17689// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17690// SPDX-License-Identifier: MIT
17691
17692
17693
17694#include <algorithm> // reverse, remove, fill, find, none_of
17695#include <array> // array
17696#include <clocale> // localeconv, lconv
17697#include <cmath> // labs, isfinite, isnan, signbit
17698#include <cstddef> // size_t, ptrdiff_t
17699#include <cstdint> // uint8_t
17700#include <cstdio> // snprintf
17701#include <limits> // numeric_limits
17702#include <string> // string, char_traits
17703#include <iomanip> // setfill, setw
17704#include <type_traits> // is_same
17705#include <utility> // move
17706
17707// #include <nlohmann/detail/conversions/to_chars.hpp>
17708// __ _____ _____ _____
17709// __| | __| | | | JSON for Modern C++
17710// | | |__ | | | | | | version 3.12.0
17711// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17712//
17713// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
17714// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17715// SPDX-License-Identifier: MIT
17716
17717
17718
17719#include <array> // array
17720#include <cmath> // signbit, isfinite
17721#include <cstdint> // intN_t, uintN_t
17722#include <cstring> // memcpy, memmove
17723#include <limits> // numeric_limits
17724#include <type_traits> // conditional
17725
17726// #include <nlohmann/detail/macro_scope.hpp>
17727
17728
17730namespace detail
17731{
17732
17752namespace dtoa_impl
17753{
17754
17755template<typename Target, typename Source>
17756Target reinterpret_bits(const Source source)
17757{
17758 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
17759
17760 Target target;
17761 std::memcpy(&target, &source, sizeof(Source));
17762 return target;
17763}
17764
17765struct diyfp // f * 2^e
17766{
17767 static constexpr int kPrecision = 64; // = q
17768
17769 std::uint64_t f = 0;
17770 int e = 0;
17771
17772 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
17773
17778 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
17779 {
17780 JSON_ASSERT(x.e == y.e);
17781 JSON_ASSERT(x.f >= y.f);
17782
17783 return {x.f - y.f, x.e};
17784 }
17785
17790 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17791 {
17792 static_assert(kPrecision == 64, "internal error");
17793
17794 // Computes:
17795 // f = round((x.f * y.f) / 2^q)
17796 // e = x.e + y.e + q
17797
17798 // Emulate the 64-bit * 64-bit multiplication:
17799 //
17800 // p = u * v
17801 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17802 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17803 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17804 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17805 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17806 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17807 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17808 //
17809 // (Since Q might be larger than 2^32 - 1)
17810 //
17811 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17812 //
17813 // (Q_hi + H does not overflow a 64-bit int)
17814 //
17815 // = p_lo + 2^64 p_hi
17816
17817 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17818 const std::uint64_t u_hi = x.f >> 32u;
17819 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17820 const std::uint64_t v_hi = y.f >> 32u;
17821
17822 const std::uint64_t p0 = u_lo * v_lo;
17823 const std::uint64_t p1 = u_lo * v_hi;
17824 const std::uint64_t p2 = u_hi * v_lo;
17825 const std::uint64_t p3 = u_hi * v_hi;
17826
17827 const std::uint64_t p0_hi = p0 >> 32u;
17828 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17829 const std::uint64_t p1_hi = p1 >> 32u;
17830 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17831 const std::uint64_t p2_hi = p2 >> 32u;
17832
17833 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17834
17835 // The full product might now be computed as
17836 //
17837 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17838 // p_lo = p0_lo + (Q << 32)
17839 //
17840 // But in this particular case here, the full p_lo is not required.
17841 // Effectively, we only need to add the highest bit in p_lo to p_hi (and
17842 // Q_hi + 1 does not overflow).
17843
17844 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17845
17846 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17847
17848 return {h, x.e + y.e + 64};
17849 }
17850
17855 static diyfp normalize(diyfp x) noexcept
17856 {
17857 JSON_ASSERT(x.f != 0);
17858
17859 while ((x.f >> 63u) == 0)
17860 {
17861 x.f <<= 1u;
17862 x.e--;
17863 }
17864
17865 return x;
17866 }
17867
17872 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17873 {
17874 const int delta = x.e - target_exponent;
17875
17876 JSON_ASSERT(delta >= 0);
17877 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17878
17879 return {x.f << delta, target_exponent};
17880 }
17881};
17882
17889
17896template<typename FloatType>
17898{
17899 JSON_ASSERT(std::isfinite(value));
17900 JSON_ASSERT(value > 0);
17901
17902 // Convert the IEEE representation into a diyfp.
17903 //
17904 // If v is denormal:
17905 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17906 // If v is normalized:
17907 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17908
17909 static_assert(std::numeric_limits<FloatType>::is_iec559,
17910 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17911
17912 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17913 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17914 constexpr int kMinExp = 1 - kBias;
17915 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17916
17917 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17918
17919 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17920 const std::uint64_t E = bits >> (kPrecision - 1);
17921 const std::uint64_t F = bits & (kHiddenBit - 1);
17922
17923 const bool is_denormal = E == 0;
17924 const diyfp v = is_denormal
17925 ? diyfp(F, kMinExp)
17926 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17927
17928 // Compute the boundaries m- and m+ of the floating-point value
17929 // v = f * 2^e.
17930 //
17931 // Determine v- and v+, the floating-point predecessor and successor of v,
17932 // respectively.
17933 //
17934 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17935 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17936 //
17937 // v+ = v + 2^e
17938 //
17939 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17940 // between m- and m+ round to v, regardless of how the input rounding
17941 // algorithm breaks ties.
17942 //
17943 // ---+-------------+-------------+-------------+-------------+--- (A)
17944 // v- m- v m+ v+
17945 //
17946 // -----------------+------+------+-------------+-------------+--- (B)
17947 // v- m- v m+ v+
17948
17949 const bool lower_boundary_is_closer = F == 0 && E > 1;
17950 const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
17951 const diyfp m_minus = lower_boundary_is_closer
17952 ? diyfp((4 * v.f) - 1, v.e - 2) // (B)
17953 : diyfp((2 * v.f) - 1, v.e - 1); // (A)
17954
17955 // Determine the normalized w+ = m+.
17956 const diyfp w_plus = diyfp::normalize(m_plus);
17957
17958 // Determine w- = m- such that e_(w-) = e_(w+).
17959 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17960
17961 return {diyfp::normalize(v), w_minus, w_plus};
17962}
17963
17964// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17965// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17966// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17967//
17968// alpha <= e = e_c + e_w + q <= gamma
17969//
17970// or
17971//
17972// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17973// <= f_c * f_w * 2^gamma
17974//
17975// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17976//
17977// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17978//
17979// or
17980//
17981// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17982//
17983// The choice of (alpha,gamma) determines the size of the table and the form of
17984// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17985// in practice:
17986//
17987// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17988// processed independently: An integral part p1, and a fractional part p2:
17989//
17990// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17991// = (f div 2^-e) + (f mod 2^-e) * 2^e
17992// = p1 + p2 * 2^e
17993//
17994// The conversion of p1 into decimal form requires a series of divisions and
17995// modulos by (a power of) 10. These operations are faster for 32-bit than for
17996// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17997// achieved by choosing
17998//
17999// -e >= 32 or e <= -32 := gamma
18000//
18001// In order to convert the fractional part
18002//
18003// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
18004//
18005// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
18006// d[-i] are extracted in order:
18007//
18008// (10 * p2) div 2^-e = d[-1]
18009// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
18010//
18011// The multiplication by 10 must not overflow. It is sufficient to choose
18012//
18013// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
18014//
18015// Since p2 = f mod 2^-e < 2^-e,
18016//
18017// -e <= 60 or e >= -60 := alpha
18018
18019constexpr int kAlpha = -60;
18020constexpr int kGamma = -32;
18021
18022struct cached_power // c = f * 2^e ~= 10^k
18023{
18024 std::uint64_t f;
18025 int e;
18026 int k;
18027};
18028
18037{
18038 // Now
18039 //
18040 // alpha <= e_c + e + q <= gamma (1)
18041 // ==> f_c * 2^alpha <= c * 2^e * 2^q
18042 //
18043 // and since the c's are normalized, 2^(q-1) <= f_c,
18044 //
18045 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
18046 // ==> 2^(alpha - e - 1) <= c
18047 //
18048 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
18049 //
18050 // k = ceil( log_10( 2^(alpha - e - 1) ) )
18051 // = ceil( (alpha - e - 1) * log_10(2) )
18052 //
18053 // From the paper:
18054 // "In theory the result of the procedure could be wrong since c is rounded,
18055 // and the computation itself is approximated [...]. In practice, however,
18056 // this simple function is sufficient."
18057 //
18058 // For IEEE double precision floating-point numbers converted into
18059 // normalized diyfp's w = f * 2^e, with q = 64,
18060 //
18061 // e >= -1022 (min IEEE exponent)
18062 // -52 (p - 1)
18063 // -52 (p - 1, possibly normalize denormal IEEE numbers)
18064 // -11 (normalize the diyfp)
18065 // = -1137
18066 //
18067 // and
18068 //
18069 // e <= +1023 (max IEEE exponent)
18070 // -52 (p - 1)
18071 // -11 (normalize the diyfp)
18072 // = 960
18073 //
18074 // This binary exponent range [-1137,960] results in a decimal exponent
18075 // range [-307,324]. One does not need to store a cached power for each
18076 // k in this range. For each such k it suffices to find a cached power
18077 // such that the exponent of the product lies in [alpha,gamma].
18078 // This implies that the difference of the decimal exponents of adjacent
18079 // table entries must be less than or equal to
18080 //
18081 // floor( (gamma - alpha) * log_10(2) ) = 8.
18082 //
18083 // (A smaller distance gamma-alpha would require a larger table.)
18084
18085 // NB:
18086 // Actually, this function returns c, such that -60 <= e_c + e + 64 <= -34.
18087
18088 constexpr int kCachedPowersMinDecExp = -300;
18089 constexpr int kCachedPowersDecStep = 8;
18090
18091 static constexpr std::array<cached_power, 79> kCachedPowers =
18092 {
18093 {
18094 { 0xAB70FE17C79AC6CA, -1060, -300 },
18095 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
18096 { 0xBE5691EF416BD60C, -1007, -284 },
18097 { 0x8DD01FAD907FFC3C, -980, -276 },
18098 { 0xD3515C2831559A83, -954, -268 },
18099 { 0x9D71AC8FADA6C9B5, -927, -260 },
18100 { 0xEA9C227723EE8BCB, -901, -252 },
18101 { 0xAECC49914078536D, -874, -244 },
18102 { 0x823C12795DB6CE57, -847, -236 },
18103 { 0xC21094364DFB5637, -821, -228 },
18104 { 0x9096EA6F3848984F, -794, -220 },
18105 { 0xD77485CB25823AC7, -768, -212 },
18106 { 0xA086CFCD97BF97F4, -741, -204 },
18107 { 0xEF340A98172AACE5, -715, -196 },
18108 { 0xB23867FB2A35B28E, -688, -188 },
18109 { 0x84C8D4DFD2C63F3B, -661, -180 },
18110 { 0xC5DD44271AD3CDBA, -635, -172 },
18111 { 0x936B9FCEBB25C996, -608, -164 },
18112 { 0xDBAC6C247D62A584, -582, -156 },
18113 { 0xA3AB66580D5FDAF6, -555, -148 },
18114 { 0xF3E2F893DEC3F126, -529, -140 },
18115 { 0xB5B5ADA8AAFF80B8, -502, -132 },
18116 { 0x87625F056C7C4A8B, -475, -124 },
18117 { 0xC9BCFF6034C13053, -449, -116 },
18118 { 0x964E858C91BA2655, -422, -108 },
18119 { 0xDFF9772470297EBD, -396, -100 },
18120 { 0xA6DFBD9FB8E5B88F, -369, -92 },
18121 { 0xF8A95FCF88747D94, -343, -84 },
18122 { 0xB94470938FA89BCF, -316, -76 },
18123 { 0x8A08F0F8BF0F156B, -289, -68 },
18124 { 0xCDB02555653131B6, -263, -60 },
18125 { 0x993FE2C6D07B7FAC, -236, -52 },
18126 { 0xE45C10C42A2B3B06, -210, -44 },
18127 { 0xAA242499697392D3, -183, -36 },
18128 { 0xFD87B5F28300CA0E, -157, -28 },
18129 { 0xBCE5086492111AEB, -130, -20 },
18130 { 0x8CBCCC096F5088CC, -103, -12 },
18131 { 0xD1B71758E219652C, -77, -4 },
18132 { 0x9C40000000000000, -50, 4 },
18133 { 0xE8D4A51000000000, -24, 12 },
18134 { 0xAD78EBC5AC620000, 3, 20 },
18135 { 0x813F3978F8940984, 30, 28 },
18136 { 0xC097CE7BC90715B3, 56, 36 },
18137 { 0x8F7E32CE7BEA5C70, 83, 44 },
18138 { 0xD5D238A4ABE98068, 109, 52 },
18139 { 0x9F4F2726179A2245, 136, 60 },
18140 { 0xED63A231D4C4FB27, 162, 68 },
18141 { 0xB0DE65388CC8ADA8, 189, 76 },
18142 { 0x83C7088E1AAB65DB, 216, 84 },
18143 { 0xC45D1DF942711D9A, 242, 92 },
18144 { 0x924D692CA61BE758, 269, 100 },
18145 { 0xDA01EE641A708DEA, 295, 108 },
18146 { 0xA26DA3999AEF774A, 322, 116 },
18147 { 0xF209787BB47D6B85, 348, 124 },
18148 { 0xB454E4A179DD1877, 375, 132 },
18149 { 0x865B86925B9BC5C2, 402, 140 },
18150 { 0xC83553C5C8965D3D, 428, 148 },
18151 { 0x952AB45CFA97A0B3, 455, 156 },
18152 { 0xDE469FBD99A05FE3, 481, 164 },
18153 { 0xA59BC234DB398C25, 508, 172 },
18154 { 0xF6C69A72A3989F5C, 534, 180 },
18155 { 0xB7DCBF5354E9BECE, 561, 188 },
18156 { 0x88FCF317F22241E2, 588, 196 },
18157 { 0xCC20CE9BD35C78A5, 614, 204 },
18158 { 0x98165AF37B2153DF, 641, 212 },
18159 { 0xE2A0B5DC971F303A, 667, 220 },
18160 { 0xA8D9D1535CE3B396, 694, 228 },
18161 { 0xFB9B7CD9A4A7443C, 720, 236 },
18162 { 0xBB764C4CA7A44410, 747, 244 },
18163 { 0x8BAB8EEFB6409C1A, 774, 252 },
18164 { 0xD01FEF10A657842C, 800, 260 },
18165 { 0x9B10A4E5E9913129, 827, 268 },
18166 { 0xE7109BFBA19C0C9D, 853, 276 },
18167 { 0xAC2820D9623BF429, 880, 284 },
18168 { 0x80444B5E7AA7CF85, 907, 292 },
18169 { 0xBF21E44003ACDD2D, 933, 300 },
18170 { 0x8E679C2F5E44FF8F, 960, 308 },
18171 { 0xD433179D9C8CB841, 986, 316 },
18172 { 0x9E19DB92B4E31BA9, 1013, 324 },
18173 }
18174 };
18175
18176 // This computation gives exactly the same results for k as
18177 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
18178 // for |e| <= 1500, but doesn't require floating-point operations.
18179 // NB: log_10(2) ~= 78913 / 2^18
18180 JSON_ASSERT(e >= -1500);
18181 JSON_ASSERT(e <= 1500);
18182 const int f = kAlpha - e - 1;
18183 const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
18184
18185 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
18186 JSON_ASSERT(index >= 0);
18187 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
18188
18189 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
18190 JSON_ASSERT(kAlpha <= cached.e + e + 64);
18191 JSON_ASSERT(kGamma >= cached.e + e + 64);
18192
18193 return cached;
18194}
18195
18200inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
18201{
18202 // LCOV_EXCL_START
18203 if (n >= 1000000000)
18204 {
18205 pow10 = 1000000000;
18206 return 10;
18207 }
18208 // LCOV_EXCL_STOP
18209 if (n >= 100000000)
18210 {
18211 pow10 = 100000000;
18212 return 9;
18213 }
18214 if (n >= 10000000)
18215 {
18216 pow10 = 10000000;
18217 return 8;
18218 }
18219 if (n >= 1000000)
18220 {
18221 pow10 = 1000000;
18222 return 7;
18223 }
18224 if (n >= 100000)
18225 {
18226 pow10 = 100000;
18227 return 6;
18228 }
18229 if (n >= 10000)
18230 {
18231 pow10 = 10000;
18232 return 5;
18233 }
18234 if (n >= 1000)
18235 {
18236 pow10 = 1000;
18237 return 4;
18238 }
18239 if (n >= 100)
18240 {
18241 pow10 = 100;
18242 return 3;
18243 }
18244 if (n >= 10)
18245 {
18246 pow10 = 10;
18247 return 2;
18248 }
18249
18250 pow10 = 1;
18251 return 1;
18252}
18253
18254inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
18255 std::uint64_t rest, std::uint64_t ten_k)
18256{
18257 JSON_ASSERT(len >= 1);
18258 JSON_ASSERT(dist <= delta);
18259 JSON_ASSERT(rest <= delta);
18260 JSON_ASSERT(ten_k > 0);
18261
18262 // <--------------------------- delta ---->
18263 // <---- dist --------->
18264 // --------------[------------------+-------------------]--------------
18265 // M- w M+
18266 //
18267 // ten_k
18268 // <------>
18269 // <---- rest ---->
18270 // --------------[------------------+----+--------------]--------------
18271 // w V
18272 // = buf * 10^k
18273 //
18274 // ten_k represents a unit-in-the-last-place in the decimal representation
18275 // stored in buf.
18276 // Decrement buf by ten_k while this takes buf closer to w.
18277
18278 // The tests are written in this order to avoid overflow in unsigned
18279 // integer arithmetic.
18280
18281 while (rest < dist
18282 && delta - rest >= ten_k
18283 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
18284 {
18285 JSON_ASSERT(buf[len - 1] != '0');
18286 buf[len - 1]--;
18287 rest += ten_k;
18288 }
18289}
18290
18295inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
18296 diyfp M_minus, diyfp w, diyfp M_plus)
18297{
18298 static_assert(kAlpha >= -60, "internal error");
18299 static_assert(kGamma <= -32, "internal error");
18300
18301 // Generates the digits (and the exponent) of a decimal floating-point
18302 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
18303 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
18304 //
18305 // <--------------------------- delta ---->
18306 // <---- dist --------->
18307 // --------------[------------------+-------------------]--------------
18308 // M- w M+
18309 //
18310 // Grisu2 generates the digits of M+ from left to right and stops as soon as
18311 // V is in [M-,M+].
18312
18313 JSON_ASSERT(M_plus.e >= kAlpha);
18314 JSON_ASSERT(M_plus.e <= kGamma);
18315
18316 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
18317 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
18318
18319 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
18320 //
18321 // M+ = f * 2^e
18322 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
18323 // = ((p1 ) * 2^-e + (p2 )) * 2^e
18324 // = p1 + p2 * 2^e
18325
18326 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
18327
18328 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.)
18329 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
18330
18331 // 1)
18332 //
18333 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
18334
18335 JSON_ASSERT(p1 > 0);
18336
18337 std::uint32_t pow10{};
18338 const int k = find_largest_pow10(p1, pow10);
18339
18340 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
18341 //
18342 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
18343 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
18344 //
18345 // M+ = p1 + p2 * 2^e
18346 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
18347 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
18348 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
18349 //
18350 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
18351 //
18352 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
18353 //
18354 // but stop as soon as
18355 //
18356 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
18357
18358 int n = k;
18359 while (n > 0)
18360 {
18361 // Invariants:
18362 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
18363 // pow10 = 10^(n-1) <= p1 < 10^n
18364 //
18365 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
18366 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
18367 //
18368 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
18369 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
18370 //
18371 JSON_ASSERT(d <= 9);
18372 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18373 //
18374 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
18375 //
18376 p1 = r;
18377 n--;
18378 //
18379 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
18380 // pow10 = 10^n
18381 //
18382
18383 // Now check if enough digits have been generated.
18384 // Compute
18385 //
18386 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
18387 //
18388 // Note:
18389 // Since rest and delta share the same exponent e, it suffices to
18390 // compare the significands.
18391 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
18392 if (rest <= delta)
18393 {
18394 // V = buffer * 10^n, with M- <= V <= M+.
18395
18396 decimal_exponent += n;
18397
18398 // We may now just stop. But instead, it looks as if the buffer
18399 // could be decremented to bring V closer to w.
18400 //
18401 // pow10 = 10^n is now 1 ulp in the decimal representation V.
18402 // The rounding procedure works with diyfp's with an implicit
18403 // exponent of e.
18404 //
18405 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
18406 //
18407 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
18408 grisu2_round(buffer, length, dist, delta, rest, ten_n);
18409
18410 return;
18411 }
18412
18413 pow10 /= 10;
18414 //
18415 // pow10 = 10^(n-1) <= p1 < 10^n
18416 // Invariants restored.
18417 }
18418
18419 // 2)
18420 //
18421 // The digits of the integral part have been generated:
18422 //
18423 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
18424 // = buffer + p2 * 2^e
18425 //
18426 // Now generate the digits of the fractional part p2 * 2^e.
18427 //
18428 // Note:
18429 // No decimal point is generated: the exponent is adjusted instead.
18430 //
18431 // p2 actually represents the fraction
18432 //
18433 // p2 * 2^e
18434 // = p2 / 2^-e
18435 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
18436 //
18437 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
18438 //
18439 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
18440 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
18441 //
18442 // using
18443 //
18444 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
18445 // = ( d) * 2^-e + ( r)
18446 //
18447 // or
18448 // 10^m * p2 * 2^e = d + r * 2^e
18449 //
18450 // i.e.
18451 //
18452 // M+ = buffer + p2 * 2^e
18453 // = buffer + 10^-m * (d + r * 2^e)
18454 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
18455 //
18456 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
18457
18458 JSON_ASSERT(p2 > delta);
18459
18460 int m = 0;
18461 for (;;)
18462 {
18463 // Invariant:
18464 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
18465 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
18466 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
18467 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
18468 //
18469 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
18470 p2 *= 10;
18471 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
18472 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
18473 //
18474 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
18475 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
18476 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
18477 //
18478 JSON_ASSERT(d <= 9);
18479 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18480 //
18481 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
18482 //
18483 p2 = r;
18484 m++;
18485 //
18486 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
18487 // Invariant restored.
18488
18489 // Check if enough digits have been generated.
18490 //
18491 // 10^-m * p2 * 2^e <= delta * 2^e
18492 // p2 * 2^e <= 10^m * delta * 2^e
18493 // p2 <= 10^m * delta
18494 delta *= 10;
18495 dist *= 10;
18496 if (p2 <= delta)
18497 {
18498 break;
18499 }
18500 }
18501
18502 // V = buffer * 10^-m, with M- <= V <= M+.
18503
18504 decimal_exponent -= m;
18505
18506 // 1 ulp in the decimal representation is now 10^-m.
18507 // Since delta and dist are now scaled by 10^m, we need to do the
18508 // same with ulp in order to keep the units in sync.
18509 //
18510 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
18511 //
18512 const std::uint64_t ten_m = one.f;
18513 grisu2_round(buffer, length, dist, delta, p2, ten_m);
18514
18515 // By construction this algorithm generates the shortest possible decimal
18516 // number (Loitsch, Theorem 6.2) which rounds back to w.
18517 // For an input number of precision p, at least
18518 //
18519 // N = 1 + ceil(p * log_10(2))
18520 //
18521 // decimal digits are sufficient to identify all binary floating-point
18522 // numbers (Matula, "In-and-Out conversions").
18523 // This implies that the algorithm does not produce more than N decimal
18524 // digits.
18525 //
18526 // N = 17 for p = 53 (IEEE double precision)
18527 // N = 9 for p = 24 (IEEE single precision)
18528}
18529
18536inline void grisu2(char* buf, int& len, int& decimal_exponent,
18537 diyfp m_minus, diyfp v, diyfp m_plus)
18538{
18539 JSON_ASSERT(m_plus.e == m_minus.e);
18540 JSON_ASSERT(m_plus.e == v.e);
18541
18542 // --------(-----------------------+-----------------------)-------- (A)
18543 // m- v m+
18544 //
18545 // --------------------(-----------+-----------------------)-------- (B)
18546 // m- v m+
18547 //
18548 // First scale v (and m- and m+) such that the exponent is in the range
18549 // [alpha, gamma].
18550
18551 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
18552
18553 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
18554
18555 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
18556 const diyfp w = diyfp::mul(v, c_minus_k);
18557 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
18558 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
18559
18560 // ----(---+---)---------------(---+---)---------------(---+---)----
18561 // w- w w+
18562 // = c*m- = c*v = c*m+
18563 //
18564 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
18565 // w+ are now off by a small amount.
18566 // In fact:
18567 //
18568 // w - v * 10^k < 1 ulp
18569 //
18570 // To account for this inaccuracy, add resp. subtract 1 ulp.
18571 //
18572 // --------+---[---------------(---+---)---------------]---+--------
18573 // w- M- w M+ w+
18574 //
18575 // Now any number in [M-, M+] (bounds included) will round to w when input,
18576 // regardless of how the input rounding algorithm breaks ties.
18577 //
18578 // And digit_gen generates the shortest possible such number in [M-, M+].
18579 // Note that this does not mean that Grisu2 always generates the shortest
18580 // possible number in the interval (m-, m+).
18581 const diyfp M_minus(w_minus.f + 1, w_minus.e);
18582 const diyfp M_plus (w_plus.f - 1, w_plus.e );
18583
18584 decimal_exponent = -cached.k; // = -(-k) = k
18585
18586 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
18587}
18588
18594template<typename FloatType>
18596void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
18597{
18598 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
18599 "internal error: not enough precision");
18600
18601 JSON_ASSERT(std::isfinite(value));
18602 JSON_ASSERT(value > 0);
18603
18604 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
18605 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
18606 // decimal representations are not exactly "short".
18607 //
18608 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
18609 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
18610 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
18611 // does.
18612 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
18613 // representation using the corresponding std::from_chars function recovers value exactly". That
18614 // indicates that single precision floating-point numbers should be recovered using
18615 // 'std::strtof'.
18616 //
18617 // NB: If the neighbors are computed for single-precision numbers, there is a single float
18618 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
18619 // value is off by 1 ulp.
18620#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
18621 const boundaries w = compute_boundaries(static_cast<double>(value));
18622#else
18624#endif
18625
18626 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
18627}
18628
18636inline char* append_exponent(char* buf, int e)
18637{
18638 JSON_ASSERT(e > -1000);
18639 JSON_ASSERT(e < 1000);
18640
18641 if (e < 0)
18642 {
18643 e = -e;
18644 *buf++ = '-';
18645 }
18646 else
18647 {
18648 *buf++ = '+';
18649 }
18650
18651 auto k = static_cast<std::uint32_t>(e);
18652 if (k < 10)
18653 {
18654 // Always print at least two digits in the exponent.
18655 // This is for compatibility with printf("%g").
18656 *buf++ = '0';
18657 *buf++ = static_cast<char>('0' + k);
18658 }
18659 else if (k < 100)
18660 {
18661 *buf++ = static_cast<char>('0' + (k / 10));
18662 k %= 10;
18663 *buf++ = static_cast<char>('0' + k);
18664 }
18665 else
18666 {
18667 *buf++ = static_cast<char>('0' + (k / 100));
18668 k %= 100;
18669 *buf++ = static_cast<char>('0' + (k / 10));
18670 k %= 10;
18671 *buf++ = static_cast<char>('0' + k);
18672 }
18673
18674 return buf;
18675}
18676
18688inline char* format_buffer(char* buf, int len, int decimal_exponent,
18689 int min_exp, int max_exp)
18690{
18691 JSON_ASSERT(min_exp < 0);
18692 JSON_ASSERT(max_exp > 0);
18693
18694 const int k = len;
18695 const int n = len + decimal_exponent;
18696
18697 // v = buf * 10^(n-k)
18698 // k is the length of the buffer (number of decimal digits)
18699 // n is the position of the decimal point relative to the start of the buffer.
18700
18701 if (k <= n && n <= max_exp)
18702 {
18703 // digits[000]
18704 // len <= max_exp + 2
18705
18706 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
18707 // Make it look like a floating-point number (#362, #378)
18708 buf[n + 0] = '.';
18709 buf[n + 1] = '0';
18710 return buf + (static_cast<size_t>(n) + 2);
18711 }
18712
18713 if (0 < n && n <= max_exp)
18714 {
18715 // dig.its
18716 // len <= max_digits10 + 1
18717
18718 JSON_ASSERT(k > n);
18719
18720 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
18721 buf[n] = '.';
18722 return buf + (static_cast<size_t>(k) + 1U);
18723 }
18724
18725 if (min_exp < n && n <= 0)
18726 {
18727 // 0.[000]digits
18728 // len <= 2 + (-min_exp - 1) + max_digits10
18729
18730 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
18731 buf[0] = '0';
18732 buf[1] = '.';
18733 std::memset(buf + 2, '0', static_cast<size_t>(-n));
18734 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
18735 }
18736
18737 if (k == 1)
18738 {
18739 // dE+123
18740 // len <= 1 + 5
18741
18742 buf += 1;
18743 }
18744 else
18745 {
18746 // d.igitsE+123
18747 // len <= max_digits10 + 1 + 5
18748
18749 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
18750 buf[1] = '.';
18751 buf += 1 + static_cast<size_t>(k);
18752 }
18753
18754 *buf++ = 'e';
18755 return append_exponent(buf, n - 1);
18756}
18757
18758} // namespace dtoa_impl
18759
18770template<typename FloatType>
18773char* to_chars(char* first, const char* last, FloatType value)
18774{
18775 static_cast<void>(last); // maybe unused - fix warning
18776 JSON_ASSERT(std::isfinite(value));
18777
18778 // Use signbit(value) instead of (value < 0) since signbit works for -0.
18779 if (std::signbit(value))
18780 {
18781 value = -value;
18782 *first++ = '-';
18783 }
18784
18785#ifdef __GNUC__
18786#pragma GCC diagnostic push
18787#pragma GCC diagnostic ignored "-Wfloat-equal"
18788#endif
18789 if (value == 0) // +-0
18790 {
18791 *first++ = '0';
18792 // Make it look like a floating-point number (#362, #378)
18793 *first++ = '.';
18794 *first++ = '0';
18795 return first;
18796 }
18797#ifdef __GNUC__
18798#pragma GCC diagnostic pop
18799#endif
18800
18801 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18802
18803 // Compute v = buffer * 10^decimal_exponent.
18804 // The decimal digits are stored in the buffer, which needs to be interpreted
18805 // as an unsigned decimal integer.
18806 // len is the length of the buffer, i.e., the number of decimal digits.
18807 int len = 0;
18808 int decimal_exponent = 0;
18809 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18810
18811 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18812
18813 // Format the buffer like printf("%.*g", prec, value)
18814 constexpr int kMinExp = -4;
18815 // Use digits10 here to increase compatibility with version 2.
18816 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18817
18818 JSON_ASSERT(last - first >= kMaxExp + 2);
18819 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18820 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18821
18822 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18823}
18824
18825} // namespace detail
18827
18828// #include <nlohmann/detail/exceptions.hpp>
18829
18830// #include <nlohmann/detail/macro_scope.hpp>
18831
18832// #include <nlohmann/detail/meta/cpp_future.hpp>
18833
18834// #include <nlohmann/detail/output/binary_writer.hpp>
18835
18836// #include <nlohmann/detail/output/output_adapters.hpp>
18837
18838// #include <nlohmann/detail/string_concat.hpp>
18839
18840// #include <nlohmann/detail/value_t.hpp>
18841
18842
18844namespace detail
18845{
18846
18848// serialization //
18850
18853{
18854 strict,
18855 replace,
18856 ignore
18857};
18858
18859template<typename BasicJsonType>
18861{
18862 using string_t = typename BasicJsonType::string_t;
18863 using number_float_t = typename BasicJsonType::number_float_t;
18864 using number_integer_t = typename BasicJsonType::number_integer_t;
18865 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18866 using binary_char_t = typename BasicJsonType::binary_t::value_type;
18867 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18868 static constexpr std::uint8_t UTF8_REJECT = 1;
18869
18870 public:
18877 error_handler_t error_handler_ = error_handler_t::strict)
18878 : o(std::move(s))
18879 , loc(std::localeconv())
18880 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18881 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18882 , indent_char(ichar)
18883 , indent_string(512, indent_char)
18884 , error_handler(error_handler_)
18885 {}
18886
18887 // deleted because of pointer members
18888 serializer(const serializer&) = delete;
18892 ~serializer() = default;
18893
18916 void dump(const BasicJsonType& val,
18917 const bool pretty_print,
18918 const bool ensure_ascii,
18919 const unsigned int indent_step,
18920 const unsigned int current_indent = 0)
18921 {
18922 switch (val.m_data.m_type)
18923 {
18924 case value_t::object:
18925 {
18926 if (val.m_data.m_value.object->empty())
18927 {
18928 o->write_characters("{}", 2);
18929 return;
18930 }
18931
18932 if (pretty_print)
18933 {
18934 o->write_characters("{\n", 2);
18935
18936 // variable to hold indentation for recursive calls
18937 const auto new_indent = current_indent + indent_step;
18938 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18939 {
18940 indent_string.resize(indent_string.size() * 2, ' ');
18941 }
18942
18943 // first n-1 elements
18944 auto i = val.m_data.m_value.object->cbegin();
18945 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18946 {
18947 o->write_characters(indent_string.c_str(), new_indent);
18948 o->write_character('\"');
18949 dump_escaped(i->first, ensure_ascii);
18950 o->write_characters("\": ", 3);
18951 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18952 o->write_characters(",\n", 2);
18953 }
18954
18955 // last element
18956 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18957 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18958 o->write_characters(indent_string.c_str(), new_indent);
18959 o->write_character('\"');
18960 dump_escaped(i->first, ensure_ascii);
18961 o->write_characters("\": ", 3);
18962 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18963
18964 o->write_character('\n');
18965 o->write_characters(indent_string.c_str(), current_indent);
18966 o->write_character('}');
18967 }
18968 else
18969 {
18970 o->write_character('{');
18971
18972 // first n-1 elements
18973 auto i = val.m_data.m_value.object->cbegin();
18974 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18975 {
18976 o->write_character('\"');
18977 dump_escaped(i->first, ensure_ascii);
18978 o->write_characters("\":", 2);
18979 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18980 o->write_character(',');
18981 }
18982
18983 // last element
18984 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18985 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18986 o->write_character('\"');
18987 dump_escaped(i->first, ensure_ascii);
18988 o->write_characters("\":", 2);
18989 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18990
18991 o->write_character('}');
18992 }
18993
18994 return;
18995 }
18996
18997 case value_t::array:
18998 {
18999 if (val.m_data.m_value.array->empty())
19000 {
19001 o->write_characters("[]", 2);
19002 return;
19003 }
19004
19005 if (pretty_print)
19006 {
19007 o->write_characters("[\n", 2);
19008
19009 // variable to hold indentation for recursive calls
19010 const auto new_indent = current_indent + indent_step;
19011 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
19012 {
19013 indent_string.resize(indent_string.size() * 2, ' ');
19014 }
19015
19016 // first n-1 elements
19017 for (auto i = val.m_data.m_value.array->cbegin();
19018 i != val.m_data.m_value.array->cend() - 1; ++i)
19019 {
19020 o->write_characters(indent_string.c_str(), new_indent);
19021 dump(*i, true, ensure_ascii, indent_step, new_indent);
19022 o->write_characters(",\n", 2);
19023 }
19024
19025 // last element
19026 JSON_ASSERT(!val.m_data.m_value.array->empty());
19027 o->write_characters(indent_string.c_str(), new_indent);
19028 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
19029
19030 o->write_character('\n');
19031 o->write_characters(indent_string.c_str(), current_indent);
19032 o->write_character(']');
19033 }
19034 else
19035 {
19036 o->write_character('[');
19037
19038 // first n-1 elements
19039 for (auto i = val.m_data.m_value.array->cbegin();
19040 i != val.m_data.m_value.array->cend() - 1; ++i)
19041 {
19042 dump(*i, false, ensure_ascii, indent_step, current_indent);
19043 o->write_character(',');
19044 }
19045
19046 // last element
19047 JSON_ASSERT(!val.m_data.m_value.array->empty());
19048 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
19049
19050 o->write_character(']');
19051 }
19052
19053 return;
19054 }
19055
19056 case value_t::string:
19057 {
19058 o->write_character('\"');
19059 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
19060 o->write_character('\"');
19061 return;
19062 }
19063
19064 case value_t::binary:
19065 {
19066 if (pretty_print)
19067 {
19068 o->write_characters("{\n", 2);
19069
19070 // variable to hold indentation for recursive calls
19071 const auto new_indent = current_indent + indent_step;
19072 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
19073 {
19074 indent_string.resize(indent_string.size() * 2, ' ');
19075 }
19076
19077 o->write_characters(indent_string.c_str(), new_indent);
19078
19079 o->write_characters("\"bytes\": [", 10);
19080
19081 if (!val.m_data.m_value.binary->empty())
19082 {
19083 for (auto i = val.m_data.m_value.binary->cbegin();
19084 i != val.m_data.m_value.binary->cend() - 1; ++i)
19085 {
19086 dump_integer(*i);
19087 o->write_characters(", ", 2);
19088 }
19089 dump_integer(val.m_data.m_value.binary->back());
19090 }
19091
19092 o->write_characters("],\n", 3);
19093 o->write_characters(indent_string.c_str(), new_indent);
19094
19095 o->write_characters("\"subtype\": ", 11);
19096 if (val.m_data.m_value.binary->has_subtype())
19097 {
19098 dump_integer(val.m_data.m_value.binary->subtype());
19099 }
19100 else
19101 {
19102 o->write_characters("null", 4);
19103 }
19104 o->write_character('\n');
19105 o->write_characters(indent_string.c_str(), current_indent);
19106 o->write_character('}');
19107 }
19108 else
19109 {
19110 o->write_characters("{\"bytes\":[", 10);
19111
19112 if (!val.m_data.m_value.binary->empty())
19113 {
19114 for (auto i = val.m_data.m_value.binary->cbegin();
19115 i != val.m_data.m_value.binary->cend() - 1; ++i)
19116 {
19117 dump_integer(*i);
19118 o->write_character(',');
19119 }
19120 dump_integer(val.m_data.m_value.binary->back());
19121 }
19122
19123 o->write_characters("],\"subtype\":", 12);
19124 if (val.m_data.m_value.binary->has_subtype())
19125 {
19126 dump_integer(val.m_data.m_value.binary->subtype());
19127 o->write_character('}');
19128 }
19129 else
19130 {
19131 o->write_characters("null}", 5);
19132 }
19133 }
19134 return;
19135 }
19136
19137 case value_t::boolean:
19138 {
19139 if (val.m_data.m_value.boolean)
19140 {
19141 o->write_characters("true", 4);
19142 }
19143 else
19144 {
19145 o->write_characters("false", 5);
19146 }
19147 return;
19148 }
19149
19150 case value_t::number_integer:
19151 {
19152 dump_integer(val.m_data.m_value.number_integer);
19153 return;
19154 }
19155
19156 case value_t::number_unsigned:
19157 {
19158 dump_integer(val.m_data.m_value.number_unsigned);
19159 return;
19160 }
19161
19162 case value_t::number_float:
19163 {
19164 dump_float(val.m_data.m_value.number_float);
19165 return;
19166 }
19167
19168 case value_t::discarded:
19169 {
19170 o->write_characters("<discarded>", 11);
19171 return;
19172 }
19173
19174 case value_t::null:
19175 {
19176 o->write_characters("null", 4);
19177 return;
19178 }
19179
19180 default: // LCOV_EXCL_LINE
19181 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19182 }
19183 }
19184
19200 void dump_escaped(const string_t& s, const bool ensure_ascii)
19201 {
19202 std::uint32_t codepoint{};
19203 std::uint8_t state = UTF8_ACCEPT;
19204 std::size_t bytes = 0; // number of bytes written to string_buffer
19205
19206 // number of bytes written at the point of the last valid byte
19207 std::size_t bytes_after_last_accept = 0;
19208 std::size_t undumped_chars = 0;
19209
19210 for (std::size_t i = 0; i < s.size(); ++i)
19211 {
19212 const auto byte = static_cast<std::uint8_t>(s[i]);
19213
19214 switch (decode(state, codepoint, byte))
19215 {
19216 case UTF8_ACCEPT: // decode found a new code point
19217 {
19218 switch (codepoint)
19219 {
19220 case 0x08: // backspace
19221 {
19222 string_buffer[bytes++] = '\\';
19223 string_buffer[bytes++] = 'b';
19224 break;
19225 }
19226
19227 case 0x09: // horizontal tab
19228 {
19229 string_buffer[bytes++] = '\\';
19230 string_buffer[bytes++] = 't';
19231 break;
19232 }
19233
19234 case 0x0A: // newline
19235 {
19236 string_buffer[bytes++] = '\\';
19237 string_buffer[bytes++] = 'n';
19238 break;
19239 }
19240
19241 case 0x0C: // formfeed
19242 {
19243 string_buffer[bytes++] = '\\';
19244 string_buffer[bytes++] = 'f';
19245 break;
19246 }
19247
19248 case 0x0D: // carriage return
19249 {
19250 string_buffer[bytes++] = '\\';
19251 string_buffer[bytes++] = 'r';
19252 break;
19253 }
19254
19255 case 0x22: // quotation mark
19256 {
19257 string_buffer[bytes++] = '\\';
19258 string_buffer[bytes++] = '\"';
19259 break;
19260 }
19261
19262 case 0x5C: // reverse solidus
19263 {
19264 string_buffer[bytes++] = '\\';
19265 string_buffer[bytes++] = '\\';
19266 break;
19267 }
19268
19269 default:
19270 {
19271 // escape control characters (0x00..0x1F) or, if
19272 // ensure_ascii parameter is used, non-ASCII characters
19273 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
19274 {
19275 if (codepoint <= 0xFFFF)
19276 {
19277 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19278 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
19279 static_cast<std::uint16_t>(codepoint)));
19280 bytes += 6;
19281 }
19282 else
19283 {
19284 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19285 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
19286 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
19287 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
19288 bytes += 12;
19289 }
19290 }
19291 else
19292 {
19293 // copy byte to buffer (all previous bytes
19294 // been copied have in default case above)
19295 string_buffer[bytes++] = s[i];
19296 }
19297 break;
19298 }
19299 }
19300
19301 // write buffer and reset index; there must be 13 bytes
19302 // left, as this is the maximal number of bytes to be
19303 // written ("\uxxxx\uxxxx\0") for one code point
19304 if (string_buffer.size() - bytes < 13)
19305 {
19306 o->write_characters(string_buffer.data(), bytes);
19307 bytes = 0;
19308 }
19309
19310 // remember the byte position of this accept
19311 bytes_after_last_accept = bytes;
19312 undumped_chars = 0;
19313 break;
19314 }
19315
19316 case UTF8_REJECT: // decode found invalid UTF-8 byte
19317 {
19318 switch (error_handler)
19319 {
19320 case error_handler_t::strict:
19321 {
19322 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
19323 }
19324
19325 case error_handler_t::ignore:
19326 case error_handler_t::replace:
19327 {
19328 // in case we saw this character the first time, we
19329 // would like to read it again, because the byte
19330 // may be OK for itself, but just not OK for the
19331 // previous sequence
19332 if (undumped_chars > 0)
19333 {
19334 --i;
19335 }
19336
19337 // reset length buffer to the last accepted index;
19338 // thus removing/ignoring the invalid characters
19339 bytes = bytes_after_last_accept;
19340
19341 if (error_handler == error_handler_t::replace)
19342 {
19343 // add a replacement character
19344 if (ensure_ascii)
19345 {
19346 string_buffer[bytes++] = '\\';
19347 string_buffer[bytes++] = 'u';
19348 string_buffer[bytes++] = 'f';
19349 string_buffer[bytes++] = 'f';
19350 string_buffer[bytes++] = 'f';
19351 string_buffer[bytes++] = 'd';
19352 }
19353 else
19354 {
19355 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
19356 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
19357 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
19358 }
19359
19360 // write buffer and reset index; there must be 13 bytes
19361 // left, as this is the maximal number of bytes to be
19362 // written ("\uxxxx\uxxxx\0") for one code point
19363 if (string_buffer.size() - bytes < 13)
19364 {
19365 o->write_characters(string_buffer.data(), bytes);
19366 bytes = 0;
19367 }
19368
19369 bytes_after_last_accept = bytes;
19370 }
19371
19372 undumped_chars = 0;
19373
19374 // continue processing the string
19375 state = UTF8_ACCEPT;
19376 break;
19377 }
19378
19379 default: // LCOV_EXCL_LINE
19380 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19381 }
19382 break;
19383 }
19384
19385 default: // decode found yet incomplete multibyte code point
19386 {
19387 if (!ensure_ascii)
19388 {
19389 // code point will not be escaped - copy byte to buffer
19390 string_buffer[bytes++] = s[i];
19391 }
19392 ++undumped_chars;
19393 break;
19394 }
19395 }
19396 }
19397
19398 // we finished processing the string
19399 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
19400 {
19401 // write buffer
19402 if (bytes > 0)
19403 {
19404 o->write_characters(string_buffer.data(), bytes);
19405 }
19406 }
19407 else
19408 {
19409 // we finish reading, but do not accept: string was incomplete
19410 switch (error_handler)
19411 {
19412 case error_handler_t::strict:
19413 {
19414 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));
19415 }
19416
19417 case error_handler_t::ignore:
19418 {
19419 // write all accepted bytes
19420 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19421 break;
19422 }
19423
19424 case error_handler_t::replace:
19425 {
19426 // write all accepted bytes
19427 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19428 // add a replacement character
19429 if (ensure_ascii)
19430 {
19431 o->write_characters("\\ufffd", 6);
19432 }
19433 else
19434 {
19435 o->write_characters("\xEF\xBF\xBD", 3);
19436 }
19437 break;
19438 }
19439
19440 default: // LCOV_EXCL_LINE
19441 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19442 }
19443 }
19444 }
19445
19446 private:
19455 unsigned int count_digits(number_unsigned_t x) noexcept
19456 {
19457 unsigned int n_digits = 1;
19458 for (;;)
19459 {
19460 if (x < 10)
19461 {
19462 return n_digits;
19463 }
19464 if (x < 100)
19465 {
19466 return n_digits + 1;
19467 }
19468 if (x < 1000)
19469 {
19470 return n_digits + 2;
19471 }
19472 if (x < 10000)
19473 {
19474 return n_digits + 3;
19475 }
19476 x = x / 10000u;
19477 n_digits += 4;
19478 }
19479 }
19480
19486 static std::string hex_bytes(std::uint8_t byte)
19487 {
19488 std::string result = "FF";
19489 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
19490 result[0] = nibble_to_hex[byte / 16];
19491 result[1] = nibble_to_hex[byte % 16];
19492 return result;
19493 }
19494
19495 // templates to avoid warnings about useless casts
19496 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
19497 bool is_negative_number(NumberType x)
19498 {
19499 return x < 0;
19500 }
19501
19502 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
19503 bool is_negative_number(NumberType /*unused*/)
19504 {
19505 return false;
19506 }
19507
19517 template < typename NumberType, detail::enable_if_t <
19518 std::is_integral<NumberType>::value ||
19519 std::is_same<NumberType, number_unsigned_t>::value ||
19520 std::is_same<NumberType, number_integer_t>::value ||
19521 std::is_same<NumberType, binary_char_t>::value,
19522 int > = 0 >
19523 void dump_integer(NumberType x)
19524 {
19525 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
19526 {
19527 {
19528 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
19529 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
19530 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
19531 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
19532 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
19533 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
19534 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
19535 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
19536 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
19537 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
19538 }
19539 };
19540
19541 // special case for "0"
19542 if (x == 0)
19543 {
19544 o->write_character('0');
19545 return;
19546 }
19547
19548 // use a pointer to fill the buffer
19549 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19550
19551 number_unsigned_t abs_value;
19552
19553 unsigned int n_chars{};
19554
19555 if (is_negative_number(x))
19556 {
19557 *buffer_ptr = '-';
19558 abs_value = remove_sign(static_cast<number_integer_t>(x));
19559
19560 // account one more byte for the minus sign
19561 n_chars = 1 + count_digits(abs_value);
19562 }
19563 else
19564 {
19565 abs_value = static_cast<number_unsigned_t>(x);
19566 n_chars = count_digits(abs_value);
19567 }
19568
19569 // spare 1 byte for '\0'
19570 JSON_ASSERT(n_chars < number_buffer.size() - 1);
19571
19572 // jump to the end to generate the string from backward,
19573 // so we later avoid reversing the result
19574 buffer_ptr += static_cast<typename decltype(number_buffer)::difference_type>(n_chars);
19575
19576 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
19577 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
19578 while (abs_value >= 100)
19579 {
19580 const auto digits_index = static_cast<unsigned>((abs_value % 100));
19581 abs_value /= 100;
19582 *(--buffer_ptr) = digits_to_99[digits_index][1];
19583 *(--buffer_ptr) = digits_to_99[digits_index][0];
19584 }
19585
19586 if (abs_value >= 10)
19587 {
19588 const auto digits_index = static_cast<unsigned>(abs_value);
19589 *(--buffer_ptr) = digits_to_99[digits_index][1];
19590 *(--buffer_ptr) = digits_to_99[digits_index][0];
19591 }
19592 else
19593 {
19594 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
19595 }
19596
19597 o->write_characters(number_buffer.data(), n_chars);
19598 }
19599
19608 void dump_float(number_float_t x)
19609 {
19610 // NaN / inf
19611 if (!std::isfinite(x))
19612 {
19613 o->write_characters("null", 4);
19614 return;
19615 }
19616
19617 // If number_float_t is an IEEE-754 single or double precision number,
19618 // use the Grisu2 algorithm to produce short numbers which are
19619 // guaranteed to round-trip, using strtof and strtod, resp.
19620 //
19621 // NB: The test below works if <long double> == <double>.
19622 static constexpr bool is_ieee_single_or_double
19623 = (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) ||
19624 (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);
19625
19626 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
19627 }
19628
19629 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
19630 {
19631 auto* begin = number_buffer.data();
19632 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
19633
19634 o->write_characters(begin, static_cast<size_t>(end - begin));
19635 }
19636
19637 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
19638 {
19639 // get the number of digits for a float -> text -> float round-trip
19640 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
19641
19642 // the actual conversion
19643 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19644 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
19645
19646 // negative value indicates an error
19647 JSON_ASSERT(len > 0);
19648 // check if the buffer was large enough
19649 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
19650
19651 // erase thousands separators
19652 if (thousands_sep != '\0')
19653 {
19654 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
19655 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
19656 std::fill(end, number_buffer.end(), '\0');
19657 JSON_ASSERT((end - number_buffer.begin()) <= len);
19658 len = (end - number_buffer.begin());
19659 }
19660
19661 // convert decimal point to '.'
19662 if (decimal_point != '\0' && decimal_point != '.')
19663 {
19664 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
19665 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
19666 if (dec_pos != number_buffer.end())
19667 {
19668 *dec_pos = '.';
19669 }
19670 }
19671
19672 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
19673
19674 // determine if we need to append ".0"
19675 const bool value_is_int_like =
19676 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
19677 [](char c)
19678 {
19679 return c == '.' || c == 'e';
19680 });
19681
19682 if (value_is_int_like)
19683 {
19684 o->write_characters(".0", 2);
19685 }
19686 }
19687
19709 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
19710 {
19711 static const std::array<std::uint8_t, 400> utf8d =
19712 {
19713 {
19714 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
19715 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
19716 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
19717 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
19718 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
19719 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
19720 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
19721 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
19722 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
19723 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
19724 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
19725 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
19726 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
19727 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
19728 }
19729 };
19730
19731 JSON_ASSERT(byte < utf8d.size());
19732 const std::uint8_t type = utf8d[byte];
19733
19734 codep = (state != UTF8_ACCEPT)
19735 ? (byte & 0x3fu) | (codep << 6u)
19736 : (0xFFu >> type) & (byte);
19737
19738 const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
19739 JSON_ASSERT(index < utf8d.size());
19740 state = utf8d[index];
19741 return state;
19742 }
19743
19744 /*
19745 * Overload to make the compiler happy while it is instantiating
19746 * dump_integer for number_unsigned_t.
19747 * Must never be called.
19748 */
19749 number_unsigned_t remove_sign(number_unsigned_t x)
19750 {
19751 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19752 return x; // LCOV_EXCL_LINE
19753 }
19754
19755 /*
19756 * Helper function for dump_integer
19757 *
19758 * This function takes a negative signed integer and returns its absolute
19759 * value as an unsigned integer. The plus/minus shuffling is necessary as we
19760 * cannot directly remove the sign of an arbitrary signed integer as the
19761 * absolute values of INT_MIN and INT_MAX are usually not the same. See
19762 * #1708 for details.
19763 */
19764 number_unsigned_t remove_sign(number_integer_t x) noexcept
19765 {
19766 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
19767 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
19768 }
19769
19770 private:
19772 output_adapter_t<char> o = nullptr;
19773
19775 std::array<char, 64> number_buffer{{}};
19776
19778 const std::lconv* loc = nullptr;
19780 const char thousands_sep = '\0';
19782 const char decimal_point = '\0';
19783
19785 std::array<char, 512> string_buffer{{}};
19786
19788 const char indent_char;
19791
19794};
19795
19796} // namespace detail
19798
19799// #include <nlohmann/detail/value_t.hpp>
19800
19801// #include <nlohmann/json_fwd.hpp>
19802
19803// #include <nlohmann/ordered_map.hpp>
19804// __ _____ _____ _____
19805// __| | __| | | | JSON for Modern C++
19806// | | |__ | | | | | | version 3.12.0
19807// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19808//
19809// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
19810// SPDX-License-Identifier: MIT
19811
19812
19813
19814#include <functional> // equal_to, less
19815#include <initializer_list> // initializer_list
19816#include <iterator> // input_iterator_tag, iterator_traits
19817#include <memory> // allocator
19818#include <stdexcept> // for out_of_range
19819#include <type_traits> // enable_if, is_convertible
19820#include <utility> // pair
19821#include <vector> // vector
19822
19823// #include <nlohmann/detail/macro_scope.hpp>
19824
19825// #include <nlohmann/detail/meta/type_traits.hpp>
19826
19827
19829
19832template <class Key, class T, class IgnoredLess = std::less<Key>,
19833 class Allocator = std::allocator<std::pair<const Key, T>>>
19834 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19835{
19836 using key_type = Key;
19837 using mapped_type = T;
19838 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19839 using iterator = typename Container::iterator;
19840 using const_iterator = typename Container::const_iterator;
19841 using size_type = typename Container::size_type;
19842 using value_type = typename Container::value_type;
19843#ifdef JSON_HAS_CPP_14
19844 using key_compare = std::equal_to<>;
19845#else
19846 using key_compare = std::equal_to<Key>;
19847#endif
19848
19849 // Explicit constructors instead of `using Container::Container`
19850 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19851 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19852 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19853 template <class It>
19854 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19855 : Container{first, last, alloc} {}
19856 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19857 : Container{init, alloc} {}
19858
19859 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19860 {
19861 for (auto it = this->begin(); it != this->end(); ++it)
19862 {
19863 if (m_compare(it->first, key))
19864 {
19865 return {it, false};
19866 }
19867 }
19868 Container::emplace_back(key, std::forward<T>(t));
19869 return {std::prev(this->end()), true};
19870 }
19871
19872 template<class KeyType, detail::enable_if_t<
19874 std::pair<iterator, bool> emplace(KeyType && key, T && t)
19875 {
19876 for (auto it = this->begin(); it != this->end(); ++it)
19877 {
19878 if (m_compare(it->first, key))
19879 {
19880 return {it, false};
19881 }
19882 }
19883 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19884 return {std::prev(this->end()), true};
19885 }
19886
19887 T& operator[](const key_type& key)
19888 {
19889 return emplace(key, T{}).first->second;
19890 }
19891
19892 template<class KeyType, detail::enable_if_t<
19894 T & operator[](KeyType && key)
19895 {
19896 return emplace(std::forward<KeyType>(key), T{}).first->second;
19897 }
19898
19899 const T& operator[](const key_type& key) const
19900 {
19901 return at(key);
19902 }
19903
19904 template<class KeyType, detail::enable_if_t<
19906 const T & operator[](KeyType && key) const
19907 {
19908 return at(std::forward<KeyType>(key));
19909 }
19910
19911 T& at(const key_type& key)
19912 {
19913 for (auto it = this->begin(); it != this->end(); ++it)
19914 {
19915 if (m_compare(it->first, key))
19916 {
19917 return it->second;
19918 }
19919 }
19920
19921 JSON_THROW(std::out_of_range("key not found"));
19922 }
19923
19924 template<class KeyType, detail::enable_if_t<
19926 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19927 {
19928 for (auto it = this->begin(); it != this->end(); ++it)
19929 {
19930 if (m_compare(it->first, key))
19931 {
19932 return it->second;
19933 }
19934 }
19935
19936 JSON_THROW(std::out_of_range("key not found"));
19937 }
19938
19939 const T& at(const key_type& key) const
19940 {
19941 for (auto it = this->begin(); it != this->end(); ++it)
19942 {
19943 if (m_compare(it->first, key))
19944 {
19945 return it->second;
19946 }
19947 }
19948
19949 JSON_THROW(std::out_of_range("key not found"));
19950 }
19951
19952 template<class KeyType, detail::enable_if_t<
19954 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19955 {
19956 for (auto it = this->begin(); it != this->end(); ++it)
19957 {
19958 if (m_compare(it->first, key))
19959 {
19960 return it->second;
19961 }
19962 }
19963
19964 JSON_THROW(std::out_of_range("key not found"));
19965 }
19966
19968 {
19969 for (auto it = this->begin(); it != this->end(); ++it)
19970 {
19971 if (m_compare(it->first, key))
19972 {
19973 // Since we cannot move const Keys, re-construct them in place
19974 for (auto next = it; ++next != this->end(); ++it)
19975 {
19976 it->~value_type(); // Destroy but keep allocation
19977 new (&*it) value_type{std::move(*next)};
19978 }
19979 Container::pop_back();
19980 return 1;
19981 }
19982 }
19983 return 0;
19984 }
19985
19986 template<class KeyType, detail::enable_if_t<
19988 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19989 {
19990 for (auto it = this->begin(); it != this->end(); ++it)
19991 {
19992 if (m_compare(it->first, key))
19993 {
19994 // Since we cannot move const Keys, re-construct them in place
19995 for (auto next = it; ++next != this->end(); ++it)
19996 {
19997 it->~value_type(); // Destroy but keep allocation
19998 new (&*it) value_type{std::move(*next)};
19999 }
20000 Container::pop_back();
20001 return 1;
20002 }
20003 }
20004 return 0;
20005 }
20006
20008 {
20009 return erase(pos, std::next(pos));
20010 }
20011
20013 {
20014 if (first == last)
20015 {
20016 return first;
20017 }
20018
20019 const auto elements_affected = std::distance(first, last);
20020 const auto offset = std::distance(Container::begin(), first);
20021
20022 // This is the start situation. We need to delete elements_affected
20023 // elements (3 in this example: e, f, g), and need to return an
20024 // iterator past the last deleted element (h in this example).
20025 // Note that offset is the distance from the start of the vector
20026 // to first. We will need this later.
20027
20028 // [ a, b, c, d, e, f, g, h, i, j ]
20029 // ^ ^
20030 // first last
20031
20032 // Since we cannot move const Keys, we re-construct them in place.
20033 // We start at first and re-construct (viz. copy) the elements from
20034 // the back of the vector. Example for the first iteration:
20035
20036 // ,--------.
20037 // v | destroy e and re-construct with h
20038 // [ a, b, c, d, e, f, g, h, i, j ]
20039 // ^ ^
20040 // it it + elements_affected
20041
20042 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
20043 {
20044 it->~value_type(); // destroy but keep allocation
20045 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
20046 }
20047
20048 // [ a, b, c, d, h, i, j, h, i, j ]
20049 // ^ ^
20050 // first last
20051
20052 // remove the unneeded elements at the end of the vector
20053 Container::resize(this->size() - static_cast<size_type>(elements_affected));
20054
20055 // [ a, b, c, d, h, i, j ]
20056 // ^ ^
20057 // first last
20058
20059 // first is now pointing past the last deleted element, but we cannot
20060 // use this iterator, because it may have been invalidated by the
20061 // resize call. Instead, we can return begin() + offset.
20062 return Container::begin() + offset;
20063 }
20064
20065 size_type count(const key_type& key) const
20066 {
20067 for (auto it = this->begin(); it != this->end(); ++it)
20068 {
20069 if (m_compare(it->first, key))
20070 {
20071 return 1;
20072 }
20073 }
20074 return 0;
20075 }
20076
20077 template<class KeyType, detail::enable_if_t<
20079 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
20080 {
20081 for (auto it = this->begin(); it != this->end(); ++it)
20082 {
20083 if (m_compare(it->first, key))
20084 {
20085 return 1;
20086 }
20087 }
20088 return 0;
20089 }
20090
20092 {
20093 for (auto it = this->begin(); it != this->end(); ++it)
20094 {
20095 if (m_compare(it->first, key))
20096 {
20097 return it;
20098 }
20099 }
20100 return Container::end();
20101 }
20102
20103 template<class KeyType, detail::enable_if_t<
20105 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
20106 {
20107 for (auto it = this->begin(); it != this->end(); ++it)
20108 {
20109 if (m_compare(it->first, key))
20110 {
20111 return it;
20112 }
20113 }
20114 return Container::end();
20115 }
20116
20117 const_iterator find(const key_type& key) const
20118 {
20119 for (auto it = this->begin(); it != this->end(); ++it)
20120 {
20121 if (m_compare(it->first, key))
20122 {
20123 return it;
20124 }
20125 }
20126 return Container::end();
20127 }
20128
20129 std::pair<iterator, bool> insert( value_type&& value )
20130 {
20131 return emplace(value.first, std::move(value.second));
20132 }
20133
20134 std::pair<iterator, bool> insert( const value_type& value )
20135 {
20136 for (auto it = this->begin(); it != this->end(); ++it)
20137 {
20138 if (m_compare(it->first, value.first))
20139 {
20140 return {it, false};
20141 }
20142 }
20143 Container::push_back(value);
20144 return {--this->end(), true};
20145 }
20146
20147 template<typename InputIt>
20148 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
20149 std::input_iterator_tag>::value>::type;
20150
20151 template<typename InputIt, typename = require_input_iter<InputIt>>
20152 void insert(InputIt first, InputIt last)
20153 {
20154 for (auto it = first; it != last; ++it)
20155 {
20156 insert(*it);
20157 }
20158 }
20159
20160private:
20161 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
20162};
20163
20165
20166
20167#if defined(JSON_HAS_CPP_17)
20168 #if JSON_HAS_STATIC_RTTI
20169 #include <any>
20170 #endif
20171 #include <string_view>
20172#endif
20173
20180
20200class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
20201 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
20202{
20203 private:
20204 template<detail::value_t> friend struct detail::external_constructor;
20205
20206 template<typename>
20207 friend class ::nlohmann::json_pointer;
20208 // can be restored when json_pointer backwards compatibility is removed
20209 // friend ::nlohmann::json_pointer<StringType>;
20210
20211 template<typename BasicJsonType, typename InputType>
20212 friend class ::nlohmann::detail::parser;
20213 friend ::nlohmann::detail::serializer<basic_json>;
20214 template<typename BasicJsonType>
20215 friend class ::nlohmann::detail::iter_impl;
20216 template<typename BasicJsonType, typename CharType>
20217 friend class ::nlohmann::detail::binary_writer;
20218 template<typename BasicJsonType, typename InputType, typename SAX>
20219 friend class ::nlohmann::detail::binary_reader;
20220 template<typename BasicJsonType, typename InputAdapterType>
20221 friend class ::nlohmann::detail::json_sax_dom_parser;
20222 template<typename BasicJsonType, typename InputAdapterType>
20223 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
20224 friend class ::nlohmann::detail::exception;
20225
20227 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
20228 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
20229
20231 // convenience aliases for types residing in namespace detail;
20232 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
20233
20234 template<typename InputAdapterType>
20235 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
20236 InputAdapterType adapter,
20238 const bool allow_exceptions = true,
20239 const bool ignore_comments = false,
20240 const bool ignore_trailing_commas = false
20241 )
20242 {
20243 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
20244 std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
20245 }
20246
20247 private:
20248 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
20249 template<typename BasicJsonType>
20250 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
20251 template<typename BasicJsonType>
20252 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
20253 template<typename Iterator>
20254 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
20255 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
20256
20257 template<typename CharType>
20258 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
20259
20260 template<typename InputType>
20261 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
20262 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
20263
20265 using serializer = ::nlohmann::detail::serializer<basic_json>;
20266
20267 public:
20270 using json_pointer = ::nlohmann::json_pointer<StringType>;
20271 template<typename T, typename SFINAE>
20272 using json_serializer = JSONSerializer<T, SFINAE>;
20280 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
20281
20285
20287 // exceptions //
20289
20293
20300
20302
20304 // container types //
20306
20311
20314
20319
20321 using difference_type = std::ptrdiff_t;
20323 using size_type = std::size_t;
20324
20326 using allocator_type = AllocatorType<basic_json>;
20327
20329 using pointer = typename std::allocator_traits<allocator_type>::pointer;
20331 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
20332
20334 using iterator = iter_impl<basic_json>;
20336 using const_iterator = iter_impl<const basic_json>;
20338 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
20340 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
20341
20343
20347 {
20348 return allocator_type();
20349 }
20350
20355 {
20356 basic_json result;
20357
20358 result["copyright"] = "(C) 2013-2025 Niels Lohmann";
20359 result["name"] = "JSON for Modern C++";
20360 result["url"] = "https://github.com/nlohmann/json";
20361 result["version"]["string"] =
20362 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
20363 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
20364 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
20365 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
20366 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
20367 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
20368
20369#ifdef _WIN32
20370 result["platform"] = "win32";
20371#elif defined __linux__
20372 result["platform"] = "linux";
20373#elif defined __APPLE__
20374 result["platform"] = "apple";
20375#elif defined __unix__
20376 result["platform"] = "unix";
20377#else
20378 result["platform"] = "unknown";
20379#endif
20380
20381#if defined(__ICC) || defined(__INTEL_COMPILER)
20382 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
20383#elif defined(__clang__)
20384 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
20385#elif defined(__GNUC__) || defined(__GNUG__)
20386 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
20387 std::to_string(__GNUC__), '.',
20388 std::to_string(__GNUC_MINOR__), '.',
20389 std::to_string(__GNUC_PATCHLEVEL__))
20390 }
20391 };
20392#elif defined(__HP_cc) || defined(__HP_aCC)
20393 result["compiler"] = "hp"
20394#elif defined(__IBMCPP__)
20395 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
20396#elif defined(_MSC_VER)
20397 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
20398#elif defined(__PGI)
20399 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
20400#elif defined(__SUNPRO_CC)
20401 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
20402#else
20403 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
20404#endif
20405
20406#if defined(_MSVC_LANG)
20407 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
20408#elif defined(__cplusplus)
20409 result["compiler"]["c++"] = std::to_string(__cplusplus);
20410#else
20411 result["compiler"]["c++"] = "unknown";
20412#endif
20413 return result;
20414 }
20415
20417 // JSON value data types //
20419
20424
20429#if defined(JSON_HAS_CPP_14)
20430 // use of transparent comparator avoids unnecessary repeated construction of temporaries
20431 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
20432 using default_object_comparator_t = std::less<>;
20433#else
20434 using default_object_comparator_t = std::less<StringType>;
20435#endif
20436
20439 using object_t = ObjectType<StringType,
20440 basic_json,
20442 AllocatorType<std::pair<const StringType,
20443 basic_json>>>;
20444
20447 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
20448
20451 using string_t = StringType;
20452
20455 using boolean_t = BooleanType;
20456
20459 using number_integer_t = NumberIntegerType;
20460
20463 using number_unsigned_t = NumberUnsignedType;
20464
20467 using number_float_t = NumberFloatType;
20468
20471 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
20472
20476
20478
20479 private:
20480
20482 template<typename T, typename... Args>
20484 static T* create(Args&& ... args)
20485 {
20486 AllocatorType<T> alloc;
20487 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
20488
20489 auto deleter = [&](T * obj)
20490 {
20491 AllocatorTraits::deallocate(alloc, obj, 1);
20492 };
20493 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
20494 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
20495 JSON_ASSERT(obj != nullptr);
20496 return obj.release();
20497 }
20498
20500 // JSON value storage //
20502
20529 union json_value
20530 {
20532 object_t* object;
20534 array_t* array;
20536 string_t* string;
20538 binary_t* binary;
20540 boolean_t boolean;
20542 number_integer_t number_integer;
20544 number_unsigned_t number_unsigned;
20546 number_float_t number_float;
20547
20549 json_value() = default;
20551 json_value(boolean_t v) noexcept : boolean(v) {}
20553 json_value(number_integer_t v) noexcept : number_integer(v) {}
20555 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
20557 json_value(number_float_t v) noexcept : number_float(v) {}
20559 json_value(value_t t)
20560 {
20561 switch (t)
20562 {
20563 case value_t::object:
20564 {
20565 object = create<object_t>();
20566 break;
20567 }
20568
20569 case value_t::array:
20570 {
20571 array = create<array_t>();
20572 break;
20573 }
20574
20575 case value_t::string:
20576 {
20577 string = create<string_t>("");
20578 break;
20579 }
20580
20581 case value_t::binary:
20582 {
20583 binary = create<binary_t>();
20584 break;
20585 }
20586
20587 case value_t::boolean:
20588 {
20589 boolean = static_cast<boolean_t>(false);
20590 break;
20591 }
20592
20593 case value_t::number_integer:
20594 {
20595 number_integer = static_cast<number_integer_t>(0);
20596 break;
20597 }
20598
20599 case value_t::number_unsigned:
20600 {
20601 number_unsigned = static_cast<number_unsigned_t>(0);
20602 break;
20603 }
20604
20605 case value_t::number_float:
20606 {
20607 number_float = static_cast<number_float_t>(0.0);
20608 break;
20609 }
20610
20611 case value_t::null:
20612 {
20613 object = nullptr; // silence warning, see #821
20614 break;
20615 }
20616
20617 case value_t::discarded:
20618 default:
20619 {
20620 object = nullptr; // silence warning, see #821
20621 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
20622 {
20623 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.12.0", nullptr)); // LCOV_EXCL_LINE
20624 }
20625 break;
20626 }
20627 }
20628 }
20629
20631 json_value(const string_t& value) : string(create<string_t>(value)) {}
20632
20634 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
20635
20637 json_value(const object_t& value) : object(create<object_t>(value)) {}
20638
20640 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
20641
20643 json_value(const array_t& value) : array(create<array_t>(value)) {}
20644
20646 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
20647
20649 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
20650
20652 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
20653
20655 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
20656
20658 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
20659
20660 void destroy(value_t t)
20661 {
20662 if (
20663 (t == value_t::object && object == nullptr) ||
20664 (t == value_t::array && array == nullptr) ||
20665 (t == value_t::string && string == nullptr) ||
20666 (t == value_t::binary && binary == nullptr)
20667 )
20668 {
20669 // not initialized (e.g., due to exception in the ctor)
20670 return;
20671 }
20672 if (t == value_t::array || t == value_t::object)
20673 {
20674 // flatten the current json_value to a heap-allocated stack
20675 std::vector<basic_json> stack;
20676
20677 // move the top-level items to stack
20678 if (t == value_t::array)
20679 {
20680 stack.reserve(array->size());
20681 std::move(array->begin(), array->end(), std::back_inserter(stack));
20682 }
20683 else
20684 {
20685 stack.reserve(object->size());
20686 for (auto&& it : *object)
20687 {
20688 stack.push_back(std::move(it.second));
20689 }
20690 }
20691
20692 while (!stack.empty())
20693 {
20694 // move the last item to a local variable to be processed
20695 basic_json current_item(std::move(stack.back()));
20696 stack.pop_back();
20697
20698 // if current_item is array/object, move
20699 // its children to the stack to be processed later
20700 if (current_item.is_array())
20701 {
20702 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
20703
20704 current_item.m_data.m_value.array->clear();
20705 }
20706 else if (current_item.is_object())
20707 {
20708 for (auto&& it : *current_item.m_data.m_value.object)
20709 {
20710 stack.push_back(std::move(it.second));
20711 }
20712
20713 current_item.m_data.m_value.object->clear();
20714 }
20715
20716 // it's now safe that current_item gets destructed
20717 // since it doesn't have any children
20718 }
20719 }
20720
20721 switch (t)
20722 {
20723 case value_t::object:
20724 {
20725 AllocatorType<object_t> alloc;
20726 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
20727 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
20728 break;
20729 }
20730
20731 case value_t::array:
20732 {
20733 AllocatorType<array_t> alloc;
20734 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
20735 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
20736 break;
20737 }
20738
20739 case value_t::string:
20740 {
20741 AllocatorType<string_t> alloc;
20742 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
20743 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
20744 break;
20745 }
20746
20747 case value_t::binary:
20748 {
20749 AllocatorType<binary_t> alloc;
20750 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
20751 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
20752 break;
20753 }
20754
20755 case value_t::null:
20756 case value_t::boolean:
20757 case value_t::number_integer:
20758 case value_t::number_unsigned:
20759 case value_t::number_float:
20760 case value_t::discarded:
20761 default:
20762 {
20763 break;
20764 }
20765 }
20766 }
20767 };
20768
20769 private:
20788 void assert_invariant(bool check_parents = true) const noexcept
20789 {
20790 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20791 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20792 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20793 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20794
20795#if JSON_DIAGNOSTICS
20796 JSON_TRY
20797 {
20798 // cppcheck-suppress assertWithSideEffect
20799 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20800 {
20801 return j.m_parent == this;
20802 }));
20803 }
20804 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20805#endif
20806 static_cast<void>(check_parents);
20807 }
20808
20809 void set_parents()
20810 {
20811#if JSON_DIAGNOSTICS
20812 switch (m_data.m_type)
20813 {
20814 case value_t::array:
20815 {
20816 for (auto& element : *m_data.m_value.array)
20817 {
20818 element.m_parent = this;
20819 }
20820 break;
20821 }
20822
20823 case value_t::object:
20824 {
20825 for (auto& element : *m_data.m_value.object)
20826 {
20827 element.second.m_parent = this;
20828 }
20829 break;
20830 }
20831
20832 case value_t::null:
20833 case value_t::string:
20834 case value_t::boolean:
20835 case value_t::number_integer:
20836 case value_t::number_unsigned:
20837 case value_t::number_float:
20838 case value_t::binary:
20839 case value_t::discarded:
20840 default:
20841 break;
20842 }
20843#endif
20844 }
20845
20846 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20847 {
20848#if JSON_DIAGNOSTICS
20849 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20850 {
20851 (it + i)->m_parent = this;
20852 }
20853#else
20854 static_cast<void>(count_set_parents);
20855#endif
20856 return it;
20857 }
20858
20859 reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size())
20860 {
20861#if JSON_DIAGNOSTICS
20862 if (old_capacity != detail::unknown_size())
20863 {
20864 // see https://github.com/nlohmann/json/issues/2838
20865 JSON_ASSERT(type() == value_t::array);
20866 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20867 {
20868 // capacity has changed: update all parents
20869 set_parents();
20870 return j;
20871 }
20872 }
20873
20874 // ordered_json uses a vector internally, so pointers could have
20875 // been invalidated; see https://github.com/nlohmann/json/issues/2962
20876#ifdef JSON_HEDLEY_MSVC_VERSION
20877#pragma warning(push )
20878#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20879#endif
20881 {
20882 set_parents();
20883 return j;
20884 }
20885#ifdef JSON_HEDLEY_MSVC_VERSION
20886#pragma warning( pop )
20887#endif
20888
20889 j.m_parent = this;
20890#else
20891 static_cast<void>(j);
20892 static_cast<void>(old_capacity);
20893#endif
20894 return j;
20895 }
20896
20897 public:
20899 // JSON parser callback //
20901
20905
20909
20911 // constructors //
20913
20918
20922 : m_data(v)
20923 {
20924 assert_invariant();
20925 }
20926
20929 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20930 : basic_json(value_t::null)
20931 {
20932 assert_invariant();
20933 }
20934
20937 template < typename CompatibleType,
20941 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20942 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20943 std::forward<CompatibleType>(val))))
20944 {
20945 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20946 set_parents();
20947 assert_invariant();
20948 }
20949
20952 template < typename BasicJsonType,
20954 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20955 basic_json(const BasicJsonType& val)
20956#if JSON_DIAGNOSTIC_POSITIONS
20957 : start_position(val.start_pos()),
20958 end_position(val.end_pos())
20959#endif
20960 {
20961 using other_boolean_t = typename BasicJsonType::boolean_t;
20962 using other_number_float_t = typename BasicJsonType::number_float_t;
20963 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20964 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20965 using other_string_t = typename BasicJsonType::string_t;
20966 using other_object_t = typename BasicJsonType::object_t;
20967 using other_array_t = typename BasicJsonType::array_t;
20968 using other_binary_t = typename BasicJsonType::binary_t;
20969
20970 switch (val.type())
20971 {
20972 case value_t::boolean:
20973 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20974 break;
20975 case value_t::number_float:
20976 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20977 break;
20978 case value_t::number_integer:
20979 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20980 break;
20981 case value_t::number_unsigned:
20982 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20983 break;
20984 case value_t::string:
20985 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20986 break;
20987 case value_t::object:
20988 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20989 break;
20990 case value_t::array:
20991 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20992 break;
20993 case value_t::binary:
20994 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20995 break;
20996 case value_t::null:
20997 *this = nullptr;
20998 break;
20999 case value_t::discarded:
21000 m_data.m_type = value_t::discarded;
21001 break;
21002 default: // LCOV_EXCL_LINE
21003 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
21004 }
21005 JSON_ASSERT(m_data.m_type == val.type());
21006
21007 set_parents();
21008 assert_invariant();
21009 }
21010
21014 bool type_deduction = true,
21015 value_t manual_type = value_t::array)
21016 {
21017 // check if each element is an array with two elements whose first
21018 // element is a string
21019 bool is_an_object = std::all_of(init.begin(), init.end(),
21020 [](const detail::json_ref<basic_json>& element_ref)
21021 {
21022 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
21023 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
21024 // broken call to op[key_type], the wrong semantics, and a 4804 warning on Windows)
21025 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
21026 });
21027
21028 // adjust type if type deduction is not wanted
21029 if (!type_deduction)
21030 {
21031 // if an array is wanted, do not create an object though possible
21032 if (manual_type == value_t::array)
21033 {
21034 is_an_object = false;
21035 }
21036
21037 // if an object is wanted but impossible, throw an exception
21038 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
21039 {
21040 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
21041 }
21042 }
21043
21044 if (is_an_object)
21045 {
21046 // the initializer list is a list of pairs -> create an object
21047 m_data.m_type = value_t::object;
21048 m_data.m_value = value_t::object;
21049
21050 for (auto& element_ref : init)
21051 {
21052 auto element = element_ref.moved_or_copied();
21053 m_data.m_value.object->emplace(
21054 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
21055 std::move((*element.m_data.m_value.array)[1]));
21056 }
21057 }
21058 else
21059 {
21060 // the initializer list describes an array -> create an array
21061 m_data.m_type = value_t::array;
21062 m_data.m_value.array = create<array_t>(init.begin(), init.end());
21063 }
21064
21065 set_parents();
21066 assert_invariant();
21067 }
21068
21072 static basic_json binary(const typename binary_t::container_type& init)
21073 {
21074 auto res = basic_json();
21075 res.m_data.m_type = value_t::binary;
21076 res.m_data.m_value = init;
21077 return res;
21078 }
21079
21083 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
21084 {
21085 auto res = basic_json();
21086 res.m_data.m_type = value_t::binary;
21087 res.m_data.m_value = binary_t(init, subtype);
21088 return res;
21089 }
21090
21094 static basic_json binary(typename binary_t::container_type&& init)
21095 {
21096 auto res = basic_json();
21097 res.m_data.m_type = value_t::binary;
21098 res.m_data.m_value = std::move(init);
21099 return res;
21100 }
21101
21105 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
21106 {
21107 auto res = basic_json();
21108 res.m_data.m_type = value_t::binary;
21109 res.m_data.m_value = binary_t(std::move(init), subtype);
21110 return res;
21111 }
21112
21117 {
21118 return basic_json(init, false, value_t::array);
21119 }
21120
21125 {
21126 return basic_json(init, false, value_t::object);
21127 }
21128
21132 m_data{cnt, val}
21133 {
21134 set_parents();
21135 assert_invariant();
21136 }
21137
21140 template < class InputIT, typename std::enable_if <
21141 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
21142 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
21143 basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
21144 {
21145 JSON_ASSERT(first.m_object != nullptr);
21146 JSON_ASSERT(last.m_object != nullptr);
21147
21148 // make sure the iterator fits the current value
21149 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
21150 {
21151 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
21152 }
21153
21154 // copy type from the first iterator
21155 m_data.m_type = first.m_object->m_data.m_type;
21156
21157 // check if the iterator range is complete for primitive values
21158 switch (m_data.m_type)
21159 {
21160 case value_t::boolean:
21161 case value_t::number_float:
21162 case value_t::number_integer:
21163 case value_t::number_unsigned:
21164 case value_t::string:
21165 {
21166 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
21167 || !last.m_it.primitive_iterator.is_end()))
21168 {
21169 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
21170 }
21171 break;
21172 }
21173
21174 case value_t::null:
21175 case value_t::object:
21176 case value_t::array:
21177 case value_t::binary:
21178 case value_t::discarded:
21179 default:
21180 break;
21181 }
21182
21183 switch (m_data.m_type)
21184 {
21185 case value_t::number_integer:
21186 {
21187 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
21188 break;
21189 }
21190
21191 case value_t::number_unsigned:
21192 {
21193 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
21194 break;
21195 }
21196
21197 case value_t::number_float:
21198 {
21199 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
21200 break;
21201 }
21202
21203 case value_t::boolean:
21204 {
21205 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
21206 break;
21207 }
21208
21209 case value_t::string:
21210 {
21211 m_data.m_value = *first.m_object->m_data.m_value.string;
21212 break;
21213 }
21214
21215 case value_t::object:
21216 {
21217 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
21218 last.m_it.object_iterator);
21219 break;
21220 }
21221
21222 case value_t::array:
21223 {
21224 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
21225 last.m_it.array_iterator);
21226 break;
21227 }
21228
21229 case value_t::binary:
21230 {
21231 m_data.m_value = *first.m_object->m_data.m_value.binary;
21232 break;
21233 }
21234
21235 case value_t::null:
21236 case value_t::discarded:
21237 default:
21238 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
21239 }
21240
21241 set_parents();
21242 assert_invariant();
21243 }
21244
21246 // other constructors and destructor //
21248
21249 template<typename JsonRef,
21251 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
21252 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
21253
21257 : json_base_class_t(other)
21259 , start_position(other.start_position)
21260 , end_position(other.end_position)
21261#endif
21262 {
21263 m_data.m_type = other.m_data.m_type;
21264 // check of passed value is valid
21265 other.assert_invariant();
21266
21267 switch (m_data.m_type)
21268 {
21269 case value_t::object:
21270 {
21271 m_data.m_value = *other.m_data.m_value.object;
21272 break;
21273 }
21274
21275 case value_t::array:
21276 {
21277 m_data.m_value = *other.m_data.m_value.array;
21278 break;
21279 }
21280
21281 case value_t::string:
21282 {
21283 m_data.m_value = *other.m_data.m_value.string;
21284 break;
21285 }
21286
21287 case value_t::boolean:
21288 {
21289 m_data.m_value = other.m_data.m_value.boolean;
21290 break;
21291 }
21292
21293 case value_t::number_integer:
21294 {
21295 m_data.m_value = other.m_data.m_value.number_integer;
21296 break;
21297 }
21298
21299 case value_t::number_unsigned:
21300 {
21301 m_data.m_value = other.m_data.m_value.number_unsigned;
21302 break;
21303 }
21304
21305 case value_t::number_float:
21306 {
21307 m_data.m_value = other.m_data.m_value.number_float;
21308 break;
21309 }
21310
21311 case value_t::binary:
21312 {
21313 m_data.m_value = *other.m_data.m_value.binary;
21314 break;
21315 }
21316
21317 case value_t::null:
21318 case value_t::discarded:
21319 default:
21320 break;
21321 }
21322
21323 set_parents();
21324 assert_invariant();
21325 }
21326
21329 basic_json(basic_json&& other) noexcept
21330 : json_base_class_t(std::forward<json_base_class_t>(other)),
21331 m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
21332#if JSON_DIAGNOSTIC_POSITIONS
21333 , start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
21334 , end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
21335#endif
21336 {
21337 // check that the passed value is valid
21338 other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
21339
21340 // invalidate payload
21341 other.m_data.m_type = value_t::null;
21342 other.m_data.m_value = {};
21343
21344#if JSON_DIAGNOSTIC_POSITIONS
21345 other.start_position = std::string::npos;
21346 other.end_position = std::string::npos;
21347#endif
21348
21349 set_parents();
21350 assert_invariant();
21351 }
21352
21356 std::is_nothrow_move_constructible<value_t>::value&&
21357 std::is_nothrow_move_assignable<value_t>::value&&
21358 std::is_nothrow_move_constructible<json_value>::value&&
21359 std::is_nothrow_move_assignable<json_value>::value&&
21360 std::is_nothrow_move_assignable<json_base_class_t>::value
21361 )
21362 {
21363 // check that the passed value is valid
21364 other.assert_invariant();
21365
21366 using std::swap;
21367 swap(m_data.m_type, other.m_data.m_type);
21368 swap(m_data.m_value, other.m_data.m_value);
21369
21370#if JSON_DIAGNOSTIC_POSITIONS
21371 swap(start_position, other.start_position);
21372 swap(end_position, other.end_position);
21373#endif
21374
21375 json_base_class_t::operator=(std::move(other));
21376
21377 set_parents();
21378 assert_invariant();
21379 return *this;
21380 }
21381
21384 ~basic_json() noexcept
21385 {
21386 assert_invariant(false);
21387 }
21388
21390
21391 public:
21393 // object inspection //
21395
21399
21402 string_t dump(const int indent = -1,
21403 const char indent_char = ' ',
21404 const bool ensure_ascii = false,
21405 const error_handler_t error_handler = error_handler_t::strict) const
21406 {
21407 string_t result;
21408 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
21409
21410 if (indent >= 0)
21411 {
21412 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
21413 }
21414 else
21415 {
21416 s.dump(*this, false, ensure_ascii, 0);
21417 }
21418
21419 return result;
21420 }
21421
21424 constexpr value_t type() const noexcept
21425 {
21426 return m_data.m_type;
21427 }
21428
21431 constexpr bool is_primitive() const noexcept
21432 {
21433 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
21434 }
21435
21438 constexpr bool is_structured() const noexcept
21439 {
21440 return is_array() || is_object();
21441 }
21442
21445 constexpr bool is_null() const noexcept
21446 {
21447 return m_data.m_type == value_t::null;
21448 }
21449
21452 constexpr bool is_boolean() const noexcept
21453 {
21454 return m_data.m_type == value_t::boolean;
21455 }
21456
21459 constexpr bool is_number() const noexcept
21460 {
21461 return is_number_integer() || is_number_float();
21462 }
21463
21466 constexpr bool is_number_integer() const noexcept
21467 {
21468 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
21469 }
21470
21473 constexpr bool is_number_unsigned() const noexcept
21474 {
21475 return m_data.m_type == value_t::number_unsigned;
21476 }
21477
21480 constexpr bool is_number_float() const noexcept
21481 {
21482 return m_data.m_type == value_t::number_float;
21483 }
21484
21487 constexpr bool is_object() const noexcept
21488 {
21489 return m_data.m_type == value_t::object;
21490 }
21491
21494 constexpr bool is_array() const noexcept
21495 {
21496 return m_data.m_type == value_t::array;
21497 }
21498
21501 constexpr bool is_string() const noexcept
21502 {
21503 return m_data.m_type == value_t::string;
21504 }
21505
21508 constexpr bool is_binary() const noexcept
21509 {
21510 return m_data.m_type == value_t::binary;
21511 }
21512
21515 constexpr bool is_discarded() const noexcept
21516 {
21517 return m_data.m_type == value_t::discarded;
21518 }
21519
21522 constexpr operator value_t() const noexcept
21523 {
21524 return m_data.m_type;
21525 }
21526
21528
21529 private:
21531 // value access //
21533
21535 boolean_t get_impl(boolean_t* /*unused*/) const
21536 {
21537 if (JSON_HEDLEY_LIKELY(is_boolean()))
21538 {
21539 return m_data.m_value.boolean;
21540 }
21541
21542 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
21543 }
21544
21546 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
21547 {
21548 return is_object() ? m_data.m_value.object : nullptr;
21549 }
21550
21552 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
21553 {
21554 return is_object() ? m_data.m_value.object : nullptr;
21555 }
21556
21558 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
21559 {
21560 return is_array() ? m_data.m_value.array : nullptr;
21561 }
21562
21564 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
21565 {
21566 return is_array() ? m_data.m_value.array : nullptr;
21567 }
21568
21570 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
21571 {
21572 return is_string() ? m_data.m_value.string : nullptr;
21573 }
21574
21576 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
21577 {
21578 return is_string() ? m_data.m_value.string : nullptr;
21579 }
21580
21582 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
21583 {
21584 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21585 }
21586
21588 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
21589 {
21590 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21591 }
21592
21594 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
21595 {
21596 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21597 }
21598
21600 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
21601 {
21602 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21603 }
21604
21606 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
21607 {
21608 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21609 }
21610
21612 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
21613 {
21614 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21615 }
21616
21618 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
21619 {
21620 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21621 }
21622
21624 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
21625 {
21626 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21627 }
21628
21630 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
21631 {
21632 return is_binary() ? m_data.m_value.binary : nullptr;
21633 }
21634
21636 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
21637 {
21638 return is_binary() ? m_data.m_value.binary : nullptr;
21639 }
21640
21652 template<typename ReferenceType, typename ThisType>
21653 static ReferenceType get_ref_impl(ThisType& obj)
21654 {
21655 // delegate the call to get_ptr<>()
21656 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
21657
21658 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
21659 {
21660 return *ptr;
21661 }
21662
21663 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
21664 }
21665
21666 public:
21670
21673 template<typename PointerType, typename std::enable_if<
21674 std::is_pointer<PointerType>::value, int>::type = 0>
21675 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21676 {
21677 // delegate the call to get_impl_ptr<>()
21678 return get_impl_ptr(static_cast<PointerType>(nullptr));
21679 }
21680
21683 template < typename PointerType, typename std::enable_if <
21684 std::is_pointer<PointerType>::value&&
21685 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
21686 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21687 {
21688 // delegate the call to get_impl_ptr<>() const
21689 return get_impl_ptr(static_cast<PointerType>(nullptr));
21690 }
21691
21692 private:
21731 template < typename ValueType,
21735 int > = 0 >
21736 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
21737 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
21738 {
21739 auto ret = ValueType();
21740 JSONSerializer<ValueType>::from_json(*this, ret);
21741 return ret;
21742 }
21743
21774 template < typename ValueType,
21777 int > = 0 >
21778 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
21779 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
21780 {
21781 return JSONSerializer<ValueType>::from_json(*this);
21782 }
21783
21799 template < typename BasicJsonType,
21802 int > = 0 >
21803 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
21804 {
21805 return *this;
21806 }
21807
21822 template<typename BasicJsonType,
21824 std::is_same<BasicJsonType, basic_json_t>::value,
21825 int> = 0>
21826 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
21827 {
21828 return *this;
21829 }
21830
21835 template<typename PointerType,
21837 std::is_pointer<PointerType>::value,
21838 int> = 0>
21839 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21840 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21841 {
21842 // delegate the call to get_ptr
21843 return get_ptr<PointerType>();
21844 }
21845
21846 public:
21870 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21871#if defined(JSON_HAS_CPP_14)
21872 constexpr
21873#endif
21874 auto get() const noexcept(
21875 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21876 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21877 {
21878 // we cannot static_assert on ValueTypeCV being non-const, because
21879 // there is support for get<const basic_json_t>(), which is why we
21880 // still need the uncvref
21881 static_assert(!std::is_reference<ValueTypeCV>::value,
21882 "get() cannot be used with reference types, you might want to use get_ref()");
21883 return get_impl<ValueType>(detail::priority_tag<4> {});
21884 }
21885
21913 template<typename PointerType, typename std::enable_if<
21914 std::is_pointer<PointerType>::value, int>::type = 0>
21915 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21916 {
21917 // delegate the call to get_ptr
21918 return get_ptr<PointerType>();
21919 }
21920
21923 template < typename ValueType,
21927 int > = 0 >
21928 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21929 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21930 {
21931 JSONSerializer<ValueType>::from_json(*this, v);
21932 return v;
21933 }
21934
21935 // specialization to allow calling get_to with a basic_json value
21936 // see https://github.com/nlohmann/json/issues/2175
21937 template<typename ValueType,
21940 int> = 0>
21941 ValueType & get_to(ValueType& v) const
21942 {
21943 v = *this;
21944 return v;
21945 }
21946
21947 template <
21948 typename T, std::size_t N,
21949 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21952 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21953 noexcept(noexcept(JSONSerializer<Array>::from_json(
21954 std::declval<const basic_json_t&>(), v)))
21955 {
21956 JSONSerializer<Array>::from_json(*this, v);
21957 return v;
21958 }
21959
21962 template<typename ReferenceType, typename std::enable_if<
21963 std::is_reference<ReferenceType>::value, int>::type = 0>
21964 ReferenceType get_ref()
21965 {
21966 // delegate call to get_ref_impl
21967 return get_ref_impl<ReferenceType>(*this);
21968 }
21969
21972 template < typename ReferenceType, typename std::enable_if <
21973 std::is_reference<ReferenceType>::value&&
21974 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21975 ReferenceType get_ref() const
21976 {
21977 // delegate call to get_ref_impl
21978 return get_ref_impl<ReferenceType>(*this);
21979 }
21980
22010 template < typename ValueType, typename std::enable_if <
22018#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
22020#endif
22021#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
22023#endif
22025 >::value, int >::type = 0 >
22026 JSON_EXPLICIT operator ValueType() const
22027 {
22028 // delegate the call to get<>() const
22029 return get<ValueType>();
22030 }
22031
22035 {
22036 if (!is_binary())
22037 {
22038 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
22039 }
22040
22041 return *get_ptr<binary_t*>();
22042 }
22043
22046 const binary_t& get_binary() const
22047 {
22048 if (!is_binary())
22049 {
22050 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
22051 }
22052
22053 return *get_ptr<const binary_t*>();
22054 }
22055
22057
22059 // element access //
22061
22065
22069 {
22070 // at only works for arrays
22071 if (JSON_HEDLEY_LIKELY(is_array()))
22072 {
22073 JSON_TRY
22074 {
22075 return set_parent(m_data.m_value.array->at(idx));
22076 }
22077 JSON_CATCH (std::out_of_range&)
22078 {
22079 // create a better exception explanation
22080 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22081 } // cppcheck-suppress[missingReturn]
22082 }
22083 else
22084 {
22085 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22086 }
22087 }
22088
22092 {
22093 // at only works for arrays
22094 if (JSON_HEDLEY_LIKELY(is_array()))
22095 {
22096 JSON_TRY
22097 {
22098 return m_data.m_value.array->at(idx);
22099 }
22100 JSON_CATCH (std::out_of_range&)
22101 {
22102 // create a better exception explanation
22103 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22104 } // cppcheck-suppress[missingReturn]
22105 }
22106 else
22107 {
22108 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22109 }
22110 }
22111
22114 reference at(const typename object_t::key_type& key)
22115 {
22116 // at only works for objects
22117 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22118 {
22119 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22120 }
22121
22122 auto it = m_data.m_value.object->find(key);
22123 if (it == m_data.m_value.object->end())
22124 {
22125 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22126 }
22127 return set_parent(it->second);
22128 }
22129
22132 template<class KeyType, detail::enable_if_t<
22134 reference at(KeyType && key)
22135 {
22136 // at only works for objects
22137 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22138 {
22139 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22140 }
22141
22142 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22143 if (it == m_data.m_value.object->end())
22144 {
22145 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22146 }
22147 return set_parent(it->second);
22148 }
22149
22152 const_reference at(const typename object_t::key_type& key) const
22153 {
22154 // at only works for objects
22155 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22156 {
22157 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22158 }
22159
22160 auto it = m_data.m_value.object->find(key);
22161 if (it == m_data.m_value.object->end())
22162 {
22163 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22164 }
22165 return it->second;
22166 }
22167
22170 template<class KeyType, detail::enable_if_t<
22172 const_reference at(KeyType && key) const
22173 {
22174 // at only works for objects
22175 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22176 {
22177 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22178 }
22179
22180 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22181 if (it == m_data.m_value.object->end())
22182 {
22183 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22184 }
22185 return it->second;
22186 }
22187
22191 {
22192 // implicitly convert a null value to an empty array
22193 if (is_null())
22194 {
22195 m_data.m_type = value_t::array;
22196 m_data.m_value.array = create<array_t>();
22197 assert_invariant();
22198 }
22199
22200 // operator[] only works for arrays
22201 if (JSON_HEDLEY_LIKELY(is_array()))
22202 {
22203 // fill up the array with null values if given idx is outside the range
22204 if (idx >= m_data.m_value.array->size())
22205 {
22206#if JSON_DIAGNOSTICS
22207 // remember array size & capacity before resizing
22208 const auto old_size = m_data.m_value.array->size();
22209 const auto old_capacity = m_data.m_value.array->capacity();
22210#endif
22211 m_data.m_value.array->resize(idx + 1);
22212
22213#if JSON_DIAGNOSTICS
22214 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
22215 {
22216 // capacity has changed: update all parents
22217 set_parents();
22218 }
22219 else
22220 {
22221 // set parent for values added above
22222 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
22223 }
22224#endif
22225 assert_invariant();
22226 }
22227
22228 return m_data.m_value.array->operator[](idx);
22229 }
22230
22231 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22232 }
22233
22237 {
22238 // const operator[] only works for arrays
22239 if (JSON_HEDLEY_LIKELY(is_array()))
22240 {
22241 return m_data.m_value.array->operator[](idx);
22242 }
22243
22244 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22245 }
22246
22249 reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
22250 {
22251 // implicitly convert a null value to an empty object
22252 if (is_null())
22253 {
22254 m_data.m_type = value_t::object;
22255 m_data.m_value.object = create<object_t>();
22256 assert_invariant();
22257 }
22258
22259 // operator[] only works for objects
22260 if (JSON_HEDLEY_LIKELY(is_object()))
22261 {
22262 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
22263 return set_parent(result.first->second);
22264 }
22265
22266 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22267 }
22268
22271 const_reference operator[](const typename object_t::key_type& key) const
22272 {
22273 // const operator[] only works for objects
22274 if (JSON_HEDLEY_LIKELY(is_object()))
22275 {
22276 auto it = m_data.m_value.object->find(key);
22277 JSON_ASSERT(it != m_data.m_value.object->end());
22278 return it->second;
22279 }
22280
22281 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22282 }
22283
22284 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
22285 // (they seemingly cannot be constrained to resolve the ambiguity)
22286 template<typename T>
22288 {
22289 return operator[](typename object_t::key_type(key));
22290 }
22291
22292 template<typename T>
22294 {
22295 return operator[](typename object_t::key_type(key));
22296 }
22297
22300 template<class KeyType, detail::enable_if_t<
22303 {
22304 // implicitly convert a null value to an empty object
22305 if (is_null())
22306 {
22307 m_data.m_type = value_t::object;
22308 m_data.m_value.object = create<object_t>();
22309 assert_invariant();
22310 }
22311
22312 // operator[] only works for objects
22313 if (JSON_HEDLEY_LIKELY(is_object()))
22314 {
22315 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
22316 return set_parent(result.first->second);
22317 }
22318
22319 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22320 }
22321
22324 template<class KeyType, detail::enable_if_t<
22327 {
22328 // const operator[] only works for objects
22329 if (JSON_HEDLEY_LIKELY(is_object()))
22330 {
22331 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22332 JSON_ASSERT(it != m_data.m_value.object->end());
22333 return it->second;
22334 }
22335
22336 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22337 }
22338
22339 private:
22340 template<typename KeyType>
22341 using is_comparable_with_object_key = detail::is_comparable <
22342 object_comparator_t, const typename object_t::key_type&, KeyType >;
22343
22344 template<typename ValueType>
22345 using value_return_type = std::conditional <
22347 string_t, typename std::decay<ValueType>::type >;
22348
22349 public:
22352 template < class ValueType, detail::enable_if_t <
22355 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22356 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
22357 {
22358 // value only works for objects
22359 if (JSON_HEDLEY_LIKELY(is_object()))
22360 {
22361 // If 'key' is found, return its value. Otherwise, return `default_value'.
22362 const auto it = find(key);
22363 if (it != end())
22364 {
22365 return it->template get<ValueType>();
22366 }
22367
22368 return default_value;
22369 }
22370
22371 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22372 }
22373
22376 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22380 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22381 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
22382 {
22383 // value only works for objects
22384 if (JSON_HEDLEY_LIKELY(is_object()))
22385 {
22386 // If 'key' is found, return its value. Otherwise, return `default_value'.
22387 const auto it = find(key);
22388 if (it != end())
22389 {
22390 return it->template get<ReturnType>();
22391 }
22392
22393 return std::forward<ValueType>(default_value);
22394 }
22395
22396 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22397 }
22398
22401 template < class ValueType, class KeyType, detail::enable_if_t <
22404 && is_comparable_with_object_key<KeyType>::value
22406 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22407 ValueType value(KeyType && key, const ValueType& default_value) const
22408 {
22409 // value only works for objects
22410 if (JSON_HEDLEY_LIKELY(is_object()))
22411 {
22412 // If 'key' is found, return its value. Otherwise, return `default_value'.
22413 const auto it = find(std::forward<KeyType>(key));
22414 if (it != end())
22415 {
22416 return it->template get<ValueType>();
22417 }
22418
22419 return default_value;
22420 }
22421
22422 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22423 }
22424
22427 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
22431 && is_comparable_with_object_key<KeyType>::value
22433 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22434 ReturnType value(KeyType && key, ValueType && default_value) const
22435 {
22436 // value only works for objects
22437 if (JSON_HEDLEY_LIKELY(is_object()))
22438 {
22439 // If 'key' is found, return its value. Otherwise, return `default_value'.
22440 const auto it = find(std::forward<KeyType>(key));
22441 if (it != end())
22442 {
22443 return it->template get<ReturnType>();
22444 }
22445
22446 return std::forward<ValueType>(default_value);
22447 }
22448
22449 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22450 }
22451
22454 template < class ValueType, detail::enable_if_t <
22456 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22457 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
22458 {
22459 // value only works for objects
22460 if (JSON_HEDLEY_LIKELY(is_object()))
22461 {
22462 // If the pointer resolves to a value, return it. Otherwise, return
22463 // 'default_value'.
22464 JSON_TRY
22465 {
22466 return ptr.get_checked(this).template get<ValueType>();
22467 }
22469 {
22470 return default_value;
22471 }
22472 }
22473
22474 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22475 }
22476
22479 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22482 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22483 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
22484 {
22485 // value only works for objects
22486 if (JSON_HEDLEY_LIKELY(is_object()))
22487 {
22488 // If the pointer resolves to a value, return it. Otherwise, return
22489 // 'default_value'.
22490 JSON_TRY
22491 {
22492 return ptr.get_checked(this).template get<ReturnType>();
22493 }
22495 {
22496 return std::forward<ValueType>(default_value);
22497 }
22498 }
22499
22500 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22501 }
22502
22503 template < class ValueType, class BasicJsonType, detail::enable_if_t <
22506 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22507 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22508 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
22509 {
22510 return value(ptr.convert(), default_value);
22511 }
22512
22513 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
22517 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22518 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22519 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
22520 {
22521 return value(ptr.convert(), std::forward<ValueType>(default_value));
22522 }
22523
22527 {
22528 return *begin();
22529 }
22530
22534 {
22535 return *cbegin();
22536 }
22537
22541 {
22542 auto tmp = end();
22543 --tmp;
22544 return *tmp;
22545 }
22546
22550 {
22551 auto tmp = cend();
22552 --tmp;
22553 return *tmp;
22554 }
22555
22558 template < class IteratorType, detail::enable_if_t <
22559 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22560 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22561 IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
22562 {
22563 // make sure the iterator fits the current value
22564 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
22565 {
22566 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22567 }
22568
22569 IteratorType result = end();
22570
22571 switch (m_data.m_type)
22572 {
22573 case value_t::boolean:
22574 case value_t::number_float:
22575 case value_t::number_integer:
22576 case value_t::number_unsigned:
22577 case value_t::string:
22578 case value_t::binary:
22579 {
22580 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
22581 {
22582 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
22583 }
22584
22585 if (is_string())
22586 {
22587 AllocatorType<string_t> alloc;
22588 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22589 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22590 m_data.m_value.string = nullptr;
22591 }
22592 else if (is_binary())
22593 {
22594 AllocatorType<binary_t> alloc;
22595 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22596 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22597 m_data.m_value.binary = nullptr;
22598 }
22599
22600 m_data.m_type = value_t::null;
22601 assert_invariant();
22602 break;
22603 }
22604
22605 case value_t::object:
22606 {
22607 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
22608 break;
22609 }
22610
22611 case value_t::array:
22612 {
22613 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
22614 break;
22615 }
22616
22617 case value_t::null:
22618 case value_t::discarded:
22619 default:
22620 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22621 }
22622
22623 return result;
22624 }
22625
22628 template < class IteratorType, detail::enable_if_t <
22629 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22630 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22631 IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
22632 {
22633 // make sure the iterator fits the current value
22634 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
22635 {
22636 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
22637 }
22638
22639 IteratorType result = end();
22640
22641 switch (m_data.m_type)
22642 {
22643 case value_t::boolean:
22644 case value_t::number_float:
22645 case value_t::number_integer:
22646 case value_t::number_unsigned:
22647 case value_t::string:
22648 case value_t::binary:
22649 {
22650 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
22651 || !last.m_it.primitive_iterator.is_end()))
22652 {
22653 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
22654 }
22655
22656 if (is_string())
22657 {
22658 AllocatorType<string_t> alloc;
22659 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22660 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22661 m_data.m_value.string = nullptr;
22662 }
22663 else if (is_binary())
22664 {
22665 AllocatorType<binary_t> alloc;
22666 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22667 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22668 m_data.m_value.binary = nullptr;
22669 }
22670
22671 m_data.m_type = value_t::null;
22672 assert_invariant();
22673 break;
22674 }
22675
22676 case value_t::object:
22677 {
22678 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
22679 last.m_it.object_iterator);
22680 break;
22681 }
22682
22683 case value_t::array:
22684 {
22685 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
22686 last.m_it.array_iterator);
22687 break;
22688 }
22689
22690 case value_t::null:
22691 case value_t::discarded:
22692 default:
22693 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22694 }
22695
22696 return result;
22697 }
22698
22699 private:
22700 template < typename KeyType, detail::enable_if_t <
22702 size_type erase_internal(KeyType && key)
22703 {
22704 // this erase only works for objects
22705 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22706 {
22707 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22708 }
22709
22710 return m_data.m_value.object->erase(std::forward<KeyType>(key));
22711 }
22712
22713 template < typename KeyType, detail::enable_if_t <
22715 size_type erase_internal(KeyType && key)
22716 {
22717 // this erase only works for objects
22718 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22719 {
22720 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22721 }
22722
22723 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22724 if (it != m_data.m_value.object->end())
22725 {
22726 m_data.m_value.object->erase(it);
22727 return 1;
22728 }
22729 return 0;
22730 }
22731
22732 public:
22733
22736 size_type erase(const typename object_t::key_type& key)
22737 {
22738 // the indirection via erase_internal() is added to avoid making this
22739 // function a template and thus de-rank it during overload resolution
22740 return erase_internal(key);
22741 }
22742
22745 template<class KeyType, detail::enable_if_t<
22747 size_type erase(KeyType && key)
22748 {
22749 return erase_internal(std::forward<KeyType>(key));
22750 }
22751
22754 void erase(const size_type idx)
22755 {
22756 // this erase only works for arrays
22757 if (JSON_HEDLEY_LIKELY(is_array()))
22758 {
22759 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
22760 {
22761 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22762 }
22763
22764 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
22765 }
22766 else
22767 {
22768 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22769 }
22770 }
22771
22773
22775 // lookup //
22777
22780
22783 iterator find(const typename object_t::key_type& key)
22784 {
22785 auto result = end();
22786
22787 if (is_object())
22788 {
22789 result.m_it.object_iterator = m_data.m_value.object->find(key);
22790 }
22791
22792 return result;
22793 }
22794
22797 const_iterator find(const typename object_t::key_type& key) const
22798 {
22799 auto result = cend();
22800
22801 if (is_object())
22802 {
22803 result.m_it.object_iterator = m_data.m_value.object->find(key);
22804 }
22805
22806 return result;
22807 }
22808
22811 template<class KeyType, detail::enable_if_t<
22813 iterator find(KeyType && key)
22814 {
22815 auto result = end();
22816
22817 if (is_object())
22818 {
22819 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22820 }
22821
22822 return result;
22823 }
22824
22827 template<class KeyType, detail::enable_if_t<
22829 const_iterator find(KeyType && key) const
22830 {
22831 auto result = cend();
22832
22833 if (is_object())
22834 {
22835 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22836 }
22837
22838 return result;
22839 }
22840
22843 size_type count(const typename object_t::key_type& key) const
22844 {
22845 // return 0 for all nonobject types
22846 return is_object() ? m_data.m_value.object->count(key) : 0;
22847 }
22848
22851 template<class KeyType, detail::enable_if_t<
22853 size_type count(KeyType && key) const
22854 {
22855 // return 0 for all nonobject types
22856 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22857 }
22858
22861 bool contains(const typename object_t::key_type& key) const
22862 {
22863 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22864 }
22865
22868 template<class KeyType, detail::enable_if_t<
22870 bool contains(KeyType && key) const
22871 {
22872 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22873 }
22874
22877 bool contains(const json_pointer& ptr) const
22878 {
22879 return ptr.contains(this);
22880 }
22881
22882 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22883 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22884 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22885 {
22886 return ptr.contains(this);
22887 }
22888
22890
22892 // iterators //
22894
22897
22900 iterator begin() noexcept
22901 {
22902 iterator result(this);
22903 result.set_begin();
22904 return result;
22905 }
22906
22909 const_iterator begin() const noexcept
22910 {
22911 return cbegin();
22912 }
22913
22916 const_iterator cbegin() const noexcept
22917 {
22918 const_iterator result(this);
22919 result.set_begin();
22920 return result;
22921 }
22922
22925 iterator end() noexcept
22926 {
22927 iterator result(this);
22928 result.set_end();
22929 return result;
22930 }
22931
22934 const_iterator end() const noexcept
22935 {
22936 return cend();
22937 }
22938
22941 const_iterator cend() const noexcept
22942 {
22943 const_iterator result(this);
22944 result.set_end();
22945 return result;
22946 }
22947
22951 {
22952 return reverse_iterator(end());
22953 }
22954
22958 {
22959 return crbegin();
22960 }
22961
22965 {
22966 return reverse_iterator(begin());
22967 }
22968
22972 {
22973 return crend();
22974 }
22975
22979 {
22980 return const_reverse_iterator(cend());
22981 }
22982
22986 {
22987 return const_reverse_iterator(cbegin());
22988 }
22989
22990 public:
22996 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22997 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22998 {
22999 return ref.items();
23000 }
23001
23007 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
23008 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
23009 {
23010 return ref.items();
23011 }
23012
23015 iteration_proxy<iterator> items() noexcept
23016 {
23017 return iteration_proxy<iterator>(*this);
23018 }
23019
23022 iteration_proxy<const_iterator> items() const noexcept
23023 {
23024 return iteration_proxy<const_iterator>(*this);
23025 }
23026
23028
23030 // capacity //
23032
23035
23038 bool empty() const noexcept
23039 {
23040 switch (m_data.m_type)
23041 {
23042 case value_t::null:
23043 {
23044 // null values are empty
23045 return true;
23046 }
23047
23048 case value_t::array:
23049 {
23050 // delegate call to array_t::empty()
23051 return m_data.m_value.array->empty();
23052 }
23053
23054 case value_t::object:
23055 {
23056 // delegate call to object_t::empty()
23057 return m_data.m_value.object->empty();
23058 }
23059
23060 case value_t::string:
23061 case value_t::boolean:
23062 case value_t::number_integer:
23063 case value_t::number_unsigned:
23064 case value_t::number_float:
23065 case value_t::binary:
23066 case value_t::discarded:
23067 default:
23068 {
23069 // all other types are nonempty
23070 return false;
23071 }
23072 }
23073 }
23074
23077 size_type size() const noexcept
23078 {
23079 switch (m_data.m_type)
23080 {
23081 case value_t::null:
23082 {
23083 // null values are empty
23084 return 0;
23085 }
23086
23087 case value_t::array:
23088 {
23089 // delegate call to array_t::size()
23090 return m_data.m_value.array->size();
23091 }
23092
23093 case value_t::object:
23094 {
23095 // delegate call to object_t::size()
23096 return m_data.m_value.object->size();
23097 }
23098
23099 case value_t::string:
23100 case value_t::boolean:
23101 case value_t::number_integer:
23102 case value_t::number_unsigned:
23103 case value_t::number_float:
23104 case value_t::binary:
23105 case value_t::discarded:
23106 default:
23107 {
23108 // all other types have size 1
23109 return 1;
23110 }
23111 }
23112 }
23113
23116 size_type max_size() const noexcept
23117 {
23118 switch (m_data.m_type)
23119 {
23120 case value_t::array:
23121 {
23122 // delegate call to array_t::max_size()
23123 return m_data.m_value.array->max_size();
23124 }
23125
23126 case value_t::object:
23127 {
23128 // delegate call to object_t::max_size()
23129 return m_data.m_value.object->max_size();
23130 }
23131
23132 case value_t::null:
23133 case value_t::string:
23134 case value_t::boolean:
23135 case value_t::number_integer:
23136 case value_t::number_unsigned:
23137 case value_t::number_float:
23138 case value_t::binary:
23139 case value_t::discarded:
23140 default:
23141 {
23142 // all other types have max_size() == size()
23143 return size();
23144 }
23145 }
23146 }
23147
23149
23151 // modifiers //
23153
23156
23159 void clear() noexcept
23160 {
23161 switch (m_data.m_type)
23162 {
23163 case value_t::number_integer:
23164 {
23165 m_data.m_value.number_integer = 0;
23166 break;
23167 }
23168
23169 case value_t::number_unsigned:
23170 {
23171 m_data.m_value.number_unsigned = 0;
23172 break;
23173 }
23174
23175 case value_t::number_float:
23176 {
23177 m_data.m_value.number_float = 0.0;
23178 break;
23179 }
23180
23181 case value_t::boolean:
23182 {
23183 m_data.m_value.boolean = false;
23184 break;
23185 }
23186
23187 case value_t::string:
23188 {
23189 m_data.m_value.string->clear();
23190 break;
23191 }
23192
23193 case value_t::binary:
23194 {
23195 m_data.m_value.binary->clear();
23196 break;
23197 }
23198
23199 case value_t::array:
23200 {
23201 m_data.m_value.array->clear();
23202 break;
23203 }
23204
23205 case value_t::object:
23206 {
23207 m_data.m_value.object->clear();
23208 break;
23209 }
23210
23211 case value_t::null:
23212 case value_t::discarded:
23213 default:
23214 break;
23215 }
23216 }
23217
23221 {
23222 // push_back only works for null objects or arrays
23223 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23224 {
23225 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23226 }
23227
23228 // transform a null object into an array
23229 if (is_null())
23230 {
23231 m_data.m_type = value_t::array;
23232 m_data.m_value = value_t::array;
23233 assert_invariant();
23234 }
23235
23236 // add the element to the array (move semantics)
23237 const auto old_capacity = m_data.m_value.array->capacity();
23238 m_data.m_value.array->push_back(std::move(val));
23239 set_parent(m_data.m_value.array->back(), old_capacity);
23240 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
23241 }
23242
23246 {
23247 push_back(std::move(val));
23248 return *this;
23249 }
23250
23253 void push_back(const basic_json& val)
23254 {
23255 // push_back only works for null objects or arrays
23256 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23257 {
23258 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23259 }
23260
23261 // transform a null object into an array
23262 if (is_null())
23263 {
23264 m_data.m_type = value_t::array;
23265 m_data.m_value = value_t::array;
23266 assert_invariant();
23267 }
23268
23269 // add the element to the array
23270 const auto old_capacity = m_data.m_value.array->capacity();
23271 m_data.m_value.array->push_back(val);
23272 set_parent(m_data.m_value.array->back(), old_capacity);
23273 }
23274
23278 {
23279 push_back(val);
23280 return *this;
23281 }
23282
23285 void push_back(const typename object_t::value_type& val)
23286 {
23287 // push_back only works for null objects or objects
23288 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23289 {
23290 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23291 }
23292
23293 // transform a null object into an object
23294 if (is_null())
23295 {
23296 m_data.m_type = value_t::object;
23297 m_data.m_value = value_t::object;
23298 assert_invariant();
23299 }
23300
23301 // add the element to the object
23302 auto res = m_data.m_value.object->insert(val);
23303 set_parent(res.first->second);
23304 }
23305
23308 reference operator+=(const typename object_t::value_type& val)
23309 {
23310 push_back(val);
23311 return *this;
23312 }
23313
23317 {
23318 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
23319 {
23320 basic_json&& key = init.begin()->moved_or_copied();
23321 push_back(typename object_t::value_type(
23322 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
23323 }
23324 else
23325 {
23326 push_back(basic_json(init));
23327 }
23328 }
23329
23333 {
23334 push_back(init);
23335 return *this;
23336 }
23337
23340 template<class... Args>
23341 reference emplace_back(Args&& ... args)
23342 {
23343 // emplace_back only works for null objects or arrays
23344 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23345 {
23346 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
23347 }
23348
23349 // transform a null object into an array
23350 if (is_null())
23351 {
23352 m_data.m_type = value_t::array;
23353 m_data.m_value = value_t::array;
23354 assert_invariant();
23355 }
23356
23357 // add the element to the array (perfect forwarding)
23358 const auto old_capacity = m_data.m_value.array->capacity();
23359 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
23360 return set_parent(m_data.m_value.array->back(), old_capacity);
23361 }
23362
23365 template<class... Args>
23366 std::pair<iterator, bool> emplace(Args&& ... args)
23367 {
23368 // emplace only works for null objects or arrays
23369 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23370 {
23371 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
23372 }
23373
23374 // transform a null object into an object
23375 if (is_null())
23376 {
23377 m_data.m_type = value_t::object;
23378 m_data.m_value = value_t::object;
23379 assert_invariant();
23380 }
23381
23382 // add the element to the array (perfect forwarding)
23383 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
23384 set_parent(res.first->second);
23385
23386 // create a result iterator and set iterator to the result of emplace
23387 auto it = begin();
23388 it.m_it.object_iterator = res.first;
23389
23390 // return pair of iterator and boolean
23391 return {it, res.second};
23392 }
23393
23397 template<typename... Args>
23398 iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
23399 {
23400 iterator result(this);
23401 JSON_ASSERT(m_data.m_value.array != nullptr);
23402
23403 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
23404 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
23405 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
23406
23407 // This could have been written as:
23408 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
23409 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
23410
23411 set_parents();
23412 return result;
23413 }
23414
23417 iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23418 {
23419 // insert only works for arrays
23420 if (JSON_HEDLEY_LIKELY(is_array()))
23421 {
23422 // check if iterator pos fits to this JSON value
23423 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23424 {
23425 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23426 }
23427
23428 // insert to array and return iterator
23429 return insert_iterator(pos, val);
23430 }
23431
23432 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23433 }
23434
23437 iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
23438 {
23439 return insert(pos, val);
23440 }
23441
23444 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23445 {
23446 // insert only works for arrays
23447 if (JSON_HEDLEY_LIKELY(is_array()))
23448 {
23449 // check if iterator pos fits to this JSON value
23450 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23451 {
23452 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23453 }
23454
23455 // insert to array and return iterator
23456 return insert_iterator(pos, cnt, val);
23457 }
23458
23459 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23460 }
23461
23464 iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23465 {
23466 // insert only works for arrays
23467 if (JSON_HEDLEY_UNLIKELY(!is_array()))
23468 {
23469 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23470 }
23471
23472 // check if iterator pos fits to this JSON value
23473 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23474 {
23475 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23476 }
23477
23478 // check if range iterators belong to the same JSON object
23479 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23480 {
23481 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23482 }
23483
23484 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
23485 {
23486 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
23487 }
23488
23489 // insert to array and return iterator
23490 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
23491 }
23492
23495 iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
23496 {
23497 // insert only works for arrays
23498 if (JSON_HEDLEY_UNLIKELY(!is_array()))
23499 {
23500 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23501 }
23502
23503 // check if iterator pos fits to this JSON value
23504 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23505 {
23506 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23507 }
23508
23509 // insert to array and return iterator
23510 return insert_iterator(pos, ilist.begin(), ilist.end());
23511 }
23512
23515 void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23516 {
23517 // insert only works for objects
23518 if (JSON_HEDLEY_UNLIKELY(!is_object()))
23519 {
23520 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23521 }
23522
23523 // check if range iterators belong to the same JSON object
23524 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23525 {
23526 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23527 }
23528
23529 // passed iterators must belong to objects
23530 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23531 {
23532 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
23533 }
23534
23535 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
23536 set_parents();
23537 }
23538
23541 void update(const_reference j, bool merge_objects = false)
23542 {
23543 update(j.begin(), j.end(), merge_objects);
23544 }
23545
23548 void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
23549 {
23550 // implicitly convert a null value to an empty object
23551 if (is_null())
23552 {
23553 m_data.m_type = value_t::object;
23554 m_data.m_value.object = create<object_t>();
23555 assert_invariant();
23556 }
23557
23558 if (JSON_HEDLEY_UNLIKELY(!is_object()))
23559 {
23560 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
23561 }
23562
23563 // check if range iterators belong to the same JSON object
23564 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23565 {
23566 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23567 }
23568
23569 // passed iterators must belong to objects
23570 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23571 {
23572 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
23573 }
23574
23575 for (auto it = first; it != last; ++it)
23576 {
23577 if (merge_objects && it.value().is_object())
23578 {
23579 auto it2 = m_data.m_value.object->find(it.key());
23580 if (it2 != m_data.m_value.object->end())
23581 {
23582 it2->second.update(it.value(), true);
23583 continue;
23584 }
23585 }
23586 m_data.m_value.object->operator[](it.key()) = it.value();
23587#if JSON_DIAGNOSTICS
23588 m_data.m_value.object->operator[](it.key()).m_parent = this;
23589#endif
23590 }
23591 }
23592
23595 void swap(reference other) noexcept (
23596 std::is_nothrow_move_constructible<value_t>::value&&
23597 std::is_nothrow_move_assignable<value_t>::value&&
23598 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23599 std::is_nothrow_move_assignable<json_value>::value
23600 )
23601 {
23602 std::swap(m_data.m_type, other.m_data.m_type);
23603 std::swap(m_data.m_value, other.m_data.m_value);
23604
23605 set_parents();
23606 other.set_parents();
23607 assert_invariant();
23608 }
23609
23612 friend void swap(reference left, reference right) noexcept (
23613 std::is_nothrow_move_constructible<value_t>::value&&
23614 std::is_nothrow_move_assignable<value_t>::value&&
23615 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23616 std::is_nothrow_move_assignable<json_value>::value
23617 )
23618 {
23619 left.swap(right);
23620 }
23621
23624 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23625 {
23626 // swap only works for arrays
23627 if (JSON_HEDLEY_LIKELY(is_array()))
23628 {
23629 using std::swap;
23630 swap(*(m_data.m_value.array), other);
23631 }
23632 else
23633 {
23634 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
23635 }
23636 }
23637
23640 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23641 {
23642 // swap only works for objects
23643 if (JSON_HEDLEY_LIKELY(is_object()))
23644 {
23645 using std::swap;
23646 swap(*(m_data.m_value.object), other);
23647 }
23648 else
23649 {
23650 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
23651 }
23652 }
23653
23656 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23657 {
23658 // swap only works for strings
23659 if (JSON_HEDLEY_LIKELY(is_string()))
23660 {
23661 using std::swap;
23662 swap(*(m_data.m_value.string), other);
23663 }
23664 else
23665 {
23666 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
23667 }
23668 }
23669
23672 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23673 {
23674 // swap only works for strings
23675 if (JSON_HEDLEY_LIKELY(is_binary()))
23676 {
23677 using std::swap;
23678 swap(*(m_data.m_value.binary), other);
23679 }
23680 else
23681 {
23682 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
23683 }
23684 }
23685
23688 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
23689 {
23690 // swap only works for strings
23691 if (JSON_HEDLEY_LIKELY(is_binary()))
23692 {
23693 using std::swap;
23694 swap(*(m_data.m_value.binary), other);
23695 }
23696 else
23697 {
23698 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
23699 }
23700 }
23701
23703
23705 // lexicographical comparison operators //
23707
23710
23711 // note parentheses around operands are necessary; see
23712 // https://github.com/nlohmann/json/issues/1530
23713#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
23714 const auto lhs_type = lhs.type(); \
23715 const auto rhs_type = rhs.type(); \
23716 \
23717 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
23718 { \
23719 switch (lhs_type) \
23720 { \
23721 case value_t::array: \
23722 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
23723 \
23724 case value_t::object: \
23725 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
23726 \
23727 case value_t::null: \
23728 return (null_result); \
23729 \
23730 case value_t::string: \
23731 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
23732 \
23733 case value_t::boolean: \
23734 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
23735 \
23736 case value_t::number_integer: \
23737 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
23738 \
23739 case value_t::number_unsigned: \
23740 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
23741 \
23742 case value_t::number_float: \
23743 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
23744 \
23745 case value_t::binary: \
23746 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
23747 \
23748 case value_t::discarded: \
23749 default: \
23750 return (unordered_result); \
23751 } \
23752 } \
23753 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
23754 { \
23755 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
23756 } \
23757 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
23758 { \
23759 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
23760 } \
23761 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
23762 { \
23763 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
23764 } \
23765 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
23766 { \
23767 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
23768 } \
23769 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
23770 { \
23771 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
23772 } \
23773 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
23774 { \
23775 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
23776 } \
23777 else if(compares_unordered(lhs, rhs))\
23778 {\
23779 return (unordered_result);\
23780 }\
23781 \
23782 return (default_result);
23783
23785 // returns true if:
23786 // - any operand is NaN and the other operand is of number type
23787 // - any operand is discarded
23788 // in legacy mode, discarded values are considered ordered if
23789 // an operation is computed as an odd number of inverses of others
23790 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
23791 {
23792 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
23793 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
23794 {
23795 return true;
23796 }
23797#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23798 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
23799#else
23800 static_cast<void>(inverse);
23801 return lhs.is_discarded() || rhs.is_discarded();
23802#endif
23803 }
23804
23805 private:
23806 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
23807 {
23808 return compares_unordered(*this, rhs, inverse);
23809 }
23810
23811 public:
23812#if JSON_HAS_THREE_WAY_COMPARISON
23815 bool operator==(const_reference rhs) const noexcept
23816 {
23817#ifdef __GNUC__
23818#pragma GCC diagnostic push
23819#pragma GCC diagnostic ignored "-Wfloat-equal"
23820#endif
23821 const_reference lhs = *this;
23822 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23823#ifdef __GNUC__
23824#pragma GCC diagnostic pop
23825#endif
23826 }
23827
23830 template<typename ScalarType>
23831 requires std::is_scalar_v<ScalarType>
23832 bool operator==(ScalarType rhs) const noexcept
23833 {
23834 return *this == basic_json(rhs);
23835 }
23836
23839 bool operator!=(const_reference rhs) const noexcept
23840 {
23841 if (compares_unordered(rhs, true))
23842 {
23843 return false;
23844 }
23845 return !operator==(rhs);
23846 }
23847
23850 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23851 {
23852 const_reference lhs = *this;
23853 // default_result is used if we cannot compare values. In that case,
23854 // we compare types.
23855 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23856 std::partial_ordering::equivalent,
23857 std::partial_ordering::unordered,
23858 lhs_type <=> rhs_type) // *NOPAD*
23859 }
23860
23863 template<typename ScalarType>
23864 requires std::is_scalar_v<ScalarType>
23865 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23866 {
23867 return *this <=> basic_json(rhs); // *NOPAD*
23868 }
23869
23870#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23871 // all operators that are computed as an odd number of inverses of others
23872 // need to be overloaded to emulate the legacy comparison behavior
23873
23877 bool operator<=(const_reference rhs) const noexcept
23878 {
23879 if (compares_unordered(rhs, true))
23880 {
23881 return false;
23882 }
23883 return !(rhs < *this);
23884 }
23885
23888 template<typename ScalarType>
23889 requires std::is_scalar_v<ScalarType>
23890 bool operator<=(ScalarType rhs) const noexcept
23891 {
23892 return *this <= basic_json(rhs);
23893 }
23894
23898 bool operator>=(const_reference rhs) const noexcept
23899 {
23900 if (compares_unordered(rhs, true))
23901 {
23902 return false;
23903 }
23904 return !(*this < rhs);
23905 }
23906
23909 template<typename ScalarType>
23910 requires std::is_scalar_v<ScalarType>
23911 bool operator>=(ScalarType rhs) const noexcept
23912 {
23913 return *this >= basic_json(rhs);
23914 }
23915#endif
23916#else
23919 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23920 {
23921#ifdef __GNUC__
23922#pragma GCC diagnostic push
23923#pragma GCC diagnostic ignored "-Wfloat-equal"
23924#endif
23925 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23926#ifdef __GNUC__
23927#pragma GCC diagnostic pop
23928#endif
23929 }
23930
23933 template<typename ScalarType, typename std::enable_if<
23934 std::is_scalar<ScalarType>::value, int>::type = 0>
23935 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23936 {
23937 return lhs == basic_json(rhs);
23938 }
23939
23942 template<typename ScalarType, typename std::enable_if<
23943 std::is_scalar<ScalarType>::value, int>::type = 0>
23944 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23945 {
23946 return basic_json(lhs) == rhs;
23947 }
23948
23951 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23952 {
23953 if (compares_unordered(lhs, rhs, true))
23954 {
23955 return false;
23956 }
23957 return !(lhs == rhs);
23958 }
23959
23962 template<typename ScalarType, typename std::enable_if<
23963 std::is_scalar<ScalarType>::value, int>::type = 0>
23964 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23965 {
23966 return lhs != basic_json(rhs);
23967 }
23968
23971 template<typename ScalarType, typename std::enable_if<
23972 std::is_scalar<ScalarType>::value, int>::type = 0>
23973 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23974 {
23975 return basic_json(lhs) != rhs;
23976 }
23977
23980 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23981 {
23982 // default_result is used if we cannot compare values. In that case,
23983 // we compare types. Note we have to call the operator explicitly,
23984 // because MSVC has problems otherwise.
23985 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23986 }
23987
23990 template<typename ScalarType, typename std::enable_if<
23991 std::is_scalar<ScalarType>::value, int>::type = 0>
23992 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23993 {
23994 return lhs < basic_json(rhs);
23995 }
23996
23999 template<typename ScalarType, typename std::enable_if<
24000 std::is_scalar<ScalarType>::value, int>::type = 0>
24001 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
24002 {
24003 return basic_json(lhs) < rhs;
24004 }
24005
24008 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
24009 {
24010 if (compares_unordered(lhs, rhs, true))
24011 {
24012 return false;
24013 }
24014 return !(rhs < lhs);
24015 }
24016
24019 template<typename ScalarType, typename std::enable_if<
24020 std::is_scalar<ScalarType>::value, int>::type = 0>
24021 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
24022 {
24023 return lhs <= basic_json(rhs);
24024 }
24025
24028 template<typename ScalarType, typename std::enable_if<
24029 std::is_scalar<ScalarType>::value, int>::type = 0>
24030 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
24031 {
24032 return basic_json(lhs) <= rhs;
24033 }
24034
24037 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
24038 {
24039 // double inverse
24040 if (compares_unordered(lhs, rhs))
24041 {
24042 return false;
24043 }
24044 return !(lhs <= rhs);
24045 }
24046
24049 template<typename ScalarType, typename std::enable_if<
24050 std::is_scalar<ScalarType>::value, int>::type = 0>
24051 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
24052 {
24053 return lhs > basic_json(rhs);
24054 }
24055
24058 template<typename ScalarType, typename std::enable_if<
24059 std::is_scalar<ScalarType>::value, int>::type = 0>
24060 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
24061 {
24062 return basic_json(lhs) > rhs;
24063 }
24064
24067 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
24068 {
24069 if (compares_unordered(lhs, rhs, true))
24070 {
24071 return false;
24072 }
24073 return !(lhs < rhs);
24074 }
24075
24078 template<typename ScalarType, typename std::enable_if<
24079 std::is_scalar<ScalarType>::value, int>::type = 0>
24080 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
24081 {
24082 return lhs >= basic_json(rhs);
24083 }
24084
24087 template<typename ScalarType, typename std::enable_if<
24088 std::is_scalar<ScalarType>::value, int>::type = 0>
24089 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
24090 {
24091 return basic_json(lhs) >= rhs;
24092 }
24093#endif
24094
24095#undef JSON_IMPLEMENT_OPERATOR
24096
24098
24100 // serialization //
24102
24105#ifndef JSON_NO_IO
24108 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
24109 {
24110 // read width member and use it as the indentation parameter if nonzero
24111 const bool pretty_print = o.width() > 0;
24112 const auto indentation = pretty_print ? o.width() : 0;
24113
24114 // reset width to 0 for subsequent calls to this stream
24115 o.width(0);
24116
24117 // do the actual serialization
24118 serializer s(detail::output_adapter<char>(o), o.fill());
24119 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
24120 return o;
24121 }
24122
24129 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
24130 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
24131 {
24132 return o << j;
24133 }
24134#endif // JSON_NO_IO
24136
24138 // deserialization //
24140
24143
24146 template<typename InputType>
24148 static basic_json parse(InputType&& i,
24149 parser_callback_t cb = nullptr,
24150 const bool allow_exceptions = true,
24151 const bool ignore_comments = false,
24152 const bool ignore_trailing_commas = false)
24153 {
24154 basic_json result;
24155 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]
24156 return result;
24157 }
24158
24161 template<typename IteratorType>
24163 static basic_json parse(IteratorType first,
24164 IteratorType last,
24165 parser_callback_t cb = nullptr,
24166 const bool allow_exceptions = true,
24167 const bool ignore_comments = false,
24168 const bool ignore_trailing_commas = false)
24169 {
24170 basic_json result;
24171 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]
24172 return result;
24173 }
24174
24176 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
24177 static basic_json parse(detail::span_input_adapter&& i,
24178 parser_callback_t cb = nullptr,
24179 const bool allow_exceptions = true,
24180 const bool ignore_comments = false,
24181 const bool ignore_trailing_commas = false)
24182 {
24183 basic_json result;
24184 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
24185 return result;
24186 }
24187
24190 template<typename InputType>
24191 static bool accept(InputType&& i,
24192 const bool ignore_comments = false,
24193 const bool ignore_trailing_commas = false)
24194 {
24195 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24196 }
24197
24200 template<typename IteratorType>
24201 static bool accept(IteratorType first, IteratorType last,
24202 const bool ignore_comments = false,
24203 const bool ignore_trailing_commas = false)
24204 {
24205 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24206 }
24207
24209 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
24210 static bool accept(detail::span_input_adapter&& i,
24211 const bool ignore_comments = false,
24212 const bool ignore_trailing_commas = false)
24213 {
24214 return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24215 }
24216
24219 template <typename InputType, typename SAX>
24221 static bool sax_parse(InputType&& i, SAX* sax,
24223 const bool strict = true,
24224 const bool ignore_comments = false,
24225 const bool ignore_trailing_commas = false)
24226 {
24227 auto ia = detail::input_adapter(std::forward<InputType>(i));
24228 return format == input_format_t::json
24229 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24230 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24231 }
24232
24235 template<class IteratorType, class SAX>
24237 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
24239 const bool strict = true,
24240 const bool ignore_comments = false,
24241 const bool ignore_trailing_commas = false)
24242 {
24243 auto ia = detail::input_adapter(std::move(first), std::move(last));
24244 return format == input_format_t::json
24245 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24246 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24247 }
24248
24254 template <typename SAX>
24255 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
24257 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
24259 const bool strict = true,
24260 const bool ignore_comments = false,
24261 const bool ignore_trailing_commas = false)
24262 {
24263 auto ia = i.get();
24264 return format == input_format_t::json
24265 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24266 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24267 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24268 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24269 }
24270#ifndef JSON_NO_IO
24277 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
24278 friend std::istream& operator<<(basic_json& j, std::istream& i)
24279 {
24280 return operator>>(i, j);
24281 }
24282
24285 friend std::istream& operator>>(std::istream& i, basic_json& j)
24286 {
24287 parser(detail::input_adapter(i)).parse(false, j);
24288 return i;
24289 }
24290#endif // JSON_NO_IO
24292
24294 // convenience functions //
24296
24300 const char* type_name() const noexcept
24301 {
24302 switch (m_data.m_type)
24303 {
24304 case value_t::null:
24305 return "null";
24306 case value_t::object:
24307 return "object";
24308 case value_t::array:
24309 return "array";
24310 case value_t::string:
24311 return "string";
24312 case value_t::boolean:
24313 return "boolean";
24314 case value_t::binary:
24315 return "binary";
24316 case value_t::discarded:
24317 return "discarded";
24318 case value_t::number_integer:
24319 case value_t::number_unsigned:
24320 case value_t::number_float:
24321 return "number";
24322 default:
24323 return "invalid";
24324 }
24325 }
24326
24329 // member variables //
24331
24332 struct data
24333 {
24335 value_t m_type = value_t::null;
24336
24338 json_value m_value = {};
24339
24341 : m_type(v), m_value(v)
24342 {
24343 }
24344
24345 data(size_type cnt, const basic_json& val)
24346 : m_type(value_t::array)
24347 {
24348 m_value.array = create<array_t>(cnt, val);
24349 }
24350
24351 data() noexcept = default;
24352 data(data&&) noexcept = default;
24353 data(const data&) noexcept = delete;
24354 data& operator=(data&&) noexcept = delete;
24355 data& operator=(const data&) noexcept = delete;
24356
24357 ~data() noexcept
24358 {
24359 m_value.destroy(m_type);
24360 }
24361 };
24362
24363 data m_data = {};
24364
24365#if JSON_DIAGNOSTICS
24367 basic_json* m_parent = nullptr;
24368#endif
24369
24370#if JSON_DIAGNOSTIC_POSITIONS
24372 std::size_t start_position = std::string::npos;
24374 std::size_t end_position = std::string::npos;
24375 public:
24376 constexpr std::size_t start_pos() const noexcept
24377 {
24378 return start_position;
24379 }
24380
24381 constexpr std::size_t end_pos() const noexcept
24382 {
24383 return end_position;
24384 }
24385#endif
24386
24388 // binary serialization/deserialization //
24390
24393
24394 public:
24397 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
24398 {
24399 std::vector<std::uint8_t> result;
24400 to_cbor(j, result);
24401 return result;
24402 }
24403
24407 {
24408 binary_writer<std::uint8_t>(o).write_cbor(j);
24409 }
24410
24414 {
24415 binary_writer<char>(o).write_cbor(j);
24416 }
24417
24420 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
24421 {
24422 std::vector<std::uint8_t> result;
24423 to_msgpack(j, result);
24424 return result;
24425 }
24426
24430 {
24431 binary_writer<std::uint8_t>(o).write_msgpack(j);
24432 }
24433
24437 {
24438 binary_writer<char>(o).write_msgpack(j);
24439 }
24440
24443 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
24444 const bool use_size = false,
24445 const bool use_type = false)
24446 {
24447 std::vector<std::uint8_t> result;
24448 to_ubjson(j, result, use_size, use_type);
24449 return result;
24450 }
24451
24455 const bool use_size = false, const bool use_type = false)
24456 {
24457 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
24458 }
24459
24463 const bool use_size = false, const bool use_type = false)
24464 {
24465 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
24466 }
24467
24470 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
24471 const bool use_size = false,
24472 const bool use_type = false,
24473 const bjdata_version_t version = bjdata_version_t::draft2)
24474 {
24475 std::vector<std::uint8_t> result;
24476 to_bjdata(j, result, use_size, use_type, version);
24477 return result;
24478 }
24479
24483 const bool use_size = false, const bool use_type = false,
24484 const bjdata_version_t version = bjdata_version_t::draft2)
24485 {
24486 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true, version);
24487 }
24488
24492 const bool use_size = false, const bool use_type = false,
24493 const bjdata_version_t version = bjdata_version_t::draft2)
24494 {
24495 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true, version);
24496 }
24497
24500 static std::vector<std::uint8_t> to_bson(const basic_json& j)
24501 {
24502 std::vector<std::uint8_t> result;
24503 to_bson(j, result);
24504 return result;
24505 }
24506
24510 {
24511 binary_writer<std::uint8_t>(o).write_bson(j);
24512 }
24513
24517 {
24518 binary_writer<char>(o).write_bson(j);
24519 }
24520
24523 template<typename InputType>
24525 static basic_json from_cbor(InputType&& i,
24526 const bool strict = true,
24527 const bool allow_exceptions = true,
24528 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24529 {
24530 basic_json result;
24531 auto ia = detail::input_adapter(std::forward<InputType>(i));
24532 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24533 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]
24534 return res ? result : basic_json(value_t::discarded);
24535 }
24536
24539 template<typename IteratorType>
24541 static basic_json from_cbor(IteratorType first, IteratorType last,
24542 const bool strict = true,
24543 const bool allow_exceptions = true,
24544 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24545 {
24546 basic_json result;
24547 auto ia = detail::input_adapter(std::move(first), std::move(last));
24548 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24549 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]
24550 return res ? result : basic_json(value_t::discarded);
24551 }
24552
24553 template<typename T>
24555 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24556 static basic_json from_cbor(const T* ptr, std::size_t len,
24557 const bool strict = true,
24558 const bool allow_exceptions = true,
24559 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24560 {
24561 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
24562 }
24563
24565 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24566 static basic_json from_cbor(detail::span_input_adapter&& i,
24567 const bool strict = true,
24568 const bool allow_exceptions = true,
24569 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24570 {
24571 basic_json result;
24572 auto ia = i.get();
24573 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24574 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24575 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]
24576 return res ? result : basic_json(value_t::discarded);
24577 }
24578
24581 template<typename InputType>
24583 static basic_json from_msgpack(InputType&& i,
24584 const bool strict = true,
24585 const bool allow_exceptions = true)
24586 {
24587 basic_json result;
24588 auto ia = detail::input_adapter(std::forward<InputType>(i));
24589 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24590 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]
24591 return res ? result : basic_json(value_t::discarded);
24592 }
24593
24596 template<typename IteratorType>
24598 static basic_json from_msgpack(IteratorType first, IteratorType last,
24599 const bool strict = true,
24600 const bool allow_exceptions = true)
24601 {
24602 basic_json result;
24603 auto ia = detail::input_adapter(std::move(first), std::move(last));
24604 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24605 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]
24606 return res ? result : basic_json(value_t::discarded);
24607 }
24608
24609 template<typename T>
24611 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24612 static basic_json from_msgpack(const T* ptr, std::size_t len,
24613 const bool strict = true,
24614 const bool allow_exceptions = true)
24615 {
24616 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
24617 }
24618
24620 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24621 static basic_json from_msgpack(detail::span_input_adapter&& i,
24622 const bool strict = true,
24623 const bool allow_exceptions = true)
24624 {
24625 basic_json result;
24626 auto ia = i.get();
24627 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24628 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24629 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]
24630 return res ? result : basic_json(value_t::discarded);
24631 }
24632
24635 template<typename InputType>
24637 static basic_json from_ubjson(InputType&& i,
24638 const bool strict = true,
24639 const bool allow_exceptions = true)
24640 {
24641 basic_json result;
24642 auto ia = detail::input_adapter(std::forward<InputType>(i));
24643 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24644 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]
24645 return res ? result : basic_json(value_t::discarded);
24646 }
24647
24650 template<typename IteratorType>
24652 static basic_json from_ubjson(IteratorType first, IteratorType last,
24653 const bool strict = true,
24654 const bool allow_exceptions = true)
24655 {
24656 basic_json result;
24657 auto ia = detail::input_adapter(std::move(first), std::move(last));
24658 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24659 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]
24660 return res ? result : basic_json(value_t::discarded);
24661 }
24662
24663 template<typename T>
24665 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24666 static basic_json from_ubjson(const T* ptr, std::size_t len,
24667 const bool strict = true,
24668 const bool allow_exceptions = true)
24669 {
24670 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24671 }
24672
24674 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24675 static basic_json from_ubjson(detail::span_input_adapter&& i,
24676 const bool strict = true,
24677 const bool allow_exceptions = true)
24678 {
24679 basic_json result;
24680 auto ia = i.get();
24681 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24682 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24683 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]
24684 return res ? result : basic_json(value_t::discarded);
24685 }
24686
24689 template<typename InputType>
24691 static basic_json from_bjdata(InputType&& i,
24692 const bool strict = true,
24693 const bool allow_exceptions = true)
24694 {
24695 basic_json result;
24696 auto ia = detail::input_adapter(std::forward<InputType>(i));
24697 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24698 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]
24699 return res ? result : basic_json(value_t::discarded);
24700 }
24701
24704 template<typename IteratorType>
24706 static basic_json from_bjdata(IteratorType first, IteratorType last,
24707 const bool strict = true,
24708 const bool allow_exceptions = true)
24709 {
24710 basic_json result;
24711 auto ia = detail::input_adapter(std::move(first), std::move(last));
24712 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24713 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]
24714 return res ? result : basic_json(value_t::discarded);
24715 }
24716
24719 template<typename InputType>
24721 static basic_json from_bson(InputType&& i,
24722 const bool strict = true,
24723 const bool allow_exceptions = true)
24724 {
24725 basic_json result;
24726 auto ia = detail::input_adapter(std::forward<InputType>(i));
24727 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24728 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]
24729 return res ? result : basic_json(value_t::discarded);
24730 }
24731
24734 template<typename IteratorType>
24736 static basic_json from_bson(IteratorType first, IteratorType last,
24737 const bool strict = true,
24738 const bool allow_exceptions = true)
24739 {
24740 basic_json result;
24741 auto ia = detail::input_adapter(std::move(first), std::move(last));
24742 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24743 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]
24744 return res ? result : basic_json(value_t::discarded);
24745 }
24746
24747 template<typename T>
24749 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24750 static basic_json from_bson(const T* ptr, std::size_t len,
24751 const bool strict = true,
24752 const bool allow_exceptions = true)
24753 {
24754 return from_bson(ptr, ptr + len, strict, allow_exceptions);
24755 }
24756
24758 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24759 static basic_json from_bson(detail::span_input_adapter&& i,
24760 const bool strict = true,
24761 const bool allow_exceptions = true)
24762 {
24763 basic_json result;
24764 auto ia = i.get();
24765 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24766 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24767 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]
24768 return res ? result : basic_json(value_t::discarded);
24769 }
24771
24773 // JSON Pointer support //
24775
24778
24782 {
24783 return ptr.get_unchecked(this);
24784 }
24785
24786 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24787 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24788 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24789 {
24790 return ptr.get_unchecked(this);
24791 }
24792
24796 {
24797 return ptr.get_unchecked(this);
24798 }
24799
24800 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24801 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24802 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24803 {
24804 return ptr.get_unchecked(this);
24805 }
24806
24810 {
24811 return ptr.get_checked(this);
24812 }
24813
24814 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24815 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24816 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24817 {
24818 return ptr.get_checked(this);
24819 }
24820
24824 {
24825 return ptr.get_checked(this);
24826 }
24827
24828 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24829 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24830 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24831 {
24832 return ptr.get_checked(this);
24833 }
24834
24838 {
24839 basic_json result(value_t::object);
24840 json_pointer::flatten("", *this, result);
24841 return result;
24842 }
24843
24847 {
24848 return json_pointer::unflatten(*this);
24849 }
24850
24852
24854 // JSON Patch functions //
24856
24859
24862 void patch_inplace(const basic_json& json_patch)
24863 {
24864 basic_json& result = *this;
24865 // the valid JSON Patch operations
24866 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24867
24868 const auto get_op = [](const string_t& op)
24869 {
24870 if (op == "add")
24871 {
24872 return patch_operations::add;
24873 }
24874 if (op == "remove")
24875 {
24876 return patch_operations::remove;
24877 }
24878 if (op == "replace")
24879 {
24880 return patch_operations::replace;
24881 }
24882 if (op == "move")
24883 {
24884 return patch_operations::move;
24885 }
24886 if (op == "copy")
24887 {
24888 return patch_operations::copy;
24889 }
24890 if (op == "test")
24891 {
24892 return patch_operations::test;
24893 }
24894
24895 return patch_operations::invalid;
24896 };
24897
24898 // wrapper for "add" operation; add value at ptr
24899 const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
24900 {
24901 // adding to the root of the target document means replacing it
24902 if (ptr.empty())
24903 {
24904 result = val;
24905 return;
24906 }
24907
24908 // make sure the top element of the pointer exists
24909 json_pointer const top_pointer = ptr.top();
24910 if (top_pointer != ptr)
24911 {
24912 result.at(top_pointer);
24913 }
24914
24915 // get reference to the parent of the JSON pointer ptr
24916 const auto last_path = ptr.back();
24917 ptr.pop_back();
24918 // parent must exist when performing patch add per RFC6902 specs
24919 basic_json& parent = result.at(ptr);
24920
24921 switch (parent.m_data.m_type)
24922 {
24923 case value_t::null:
24924 case value_t::object:
24925 {
24926 // use operator[] to add value
24927 parent[last_path] = val;
24928 break;
24929 }
24930
24931 case value_t::array:
24932 {
24933 if (last_path == "-")
24934 {
24935 // special case: append to back
24936 parent.push_back(val);
24937 }
24938 else
24939 {
24940 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24941 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24942 {
24943 // avoid undefined behavior
24944 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24945 }
24946
24947 // default case: insert add offset
24948 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24949 }
24950 break;
24951 }
24952
24953 // if there exists a parent, it cannot be primitive
24954 case value_t::string: // LCOV_EXCL_LINE
24955 case value_t::boolean: // LCOV_EXCL_LINE
24956 case value_t::number_integer: // LCOV_EXCL_LINE
24957 case value_t::number_unsigned: // LCOV_EXCL_LINE
24958 case value_t::number_float: // LCOV_EXCL_LINE
24959 case value_t::binary: // LCOV_EXCL_LINE
24960 case value_t::discarded: // LCOV_EXCL_LINE
24961 default: // LCOV_EXCL_LINE
24962 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24963 }
24964 };
24965
24966 // wrapper for "remove" operation; remove value at ptr
24967 const auto operation_remove = [this, & result](json_pointer & ptr)
24968 {
24969 // get reference to the parent of the JSON pointer ptr
24970 const auto last_path = ptr.back();
24971 ptr.pop_back();
24972 basic_json& parent = result.at(ptr);
24973
24974 // remove child
24975 if (parent.is_object())
24976 {
24977 // perform range check
24978 auto it = parent.find(last_path);
24979 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24980 {
24981 parent.erase(it);
24982 }
24983 else
24984 {
24985 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24986 }
24987 }
24988 else if (parent.is_array())
24989 {
24990 // note erase performs range check
24991 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24992 }
24993 };
24994
24995 // type check: top level value must be an array
24996 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24997 {
24998 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24999 }
25000
25001 // iterate and apply the operations
25002 for (const auto& val : json_patch)
25003 {
25004 // wrapper to get a value for an operation
25005 const auto get_value = [&val](const string_t& op,
25006 const string_t& member,
25007 bool string_type) -> basic_json &
25008 {
25009 // find value
25010 auto it = val.m_data.m_value.object->find(member);
25011
25012 // context-sensitive error message
25013 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
25014
25015 // check if the desired value is present
25016 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
25017 {
25018 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
25019 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
25020 }
25021
25022 // check if the result is of type string
25023 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
25024 {
25025 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
25026 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
25027 }
25028
25029 // no error: return value
25030 return it->second;
25031 };
25032
25033 // type check: every element of the array must be an object
25034 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
25035 {
25036 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
25037 }
25038
25039 // collect mandatory members
25040 const auto op = get_value("op", "op", true).template get<string_t>();
25041 const auto path = get_value(op, "path", true).template get<string_t>();
25042 json_pointer ptr(path);
25043
25044 switch (get_op(op))
25045 {
25046 case patch_operations::add:
25047 {
25048 operation_add(ptr, get_value("add", "value", false));
25049 break;
25050 }
25051
25052 case patch_operations::remove:
25053 {
25054 operation_remove(ptr);
25055 break;
25056 }
25057
25058 case patch_operations::replace:
25059 {
25060 // the "path" location must exist - use at()
25061 result.at(ptr) = get_value("replace", "value", false);
25062 break;
25063 }
25064
25065 case patch_operations::move:
25066 {
25067 const auto from_path = get_value("move", "from", true).template get<string_t>();
25068 json_pointer from_ptr(from_path);
25069
25070 // the "from" location must exist - use at()
25071 basic_json const v = result.at(from_ptr);
25072
25073 // The move operation is functionally identical to a
25074 // "remove" operation on the "from" location, followed
25075 // immediately by an "add" operation at the target
25076 // location with the value that was just removed.
25077 operation_remove(from_ptr);
25078 operation_add(ptr, v);
25079 break;
25080 }
25081
25082 case patch_operations::copy:
25083 {
25084 const auto from_path = get_value("copy", "from", true).template get<string_t>();
25085 const json_pointer from_ptr(from_path);
25086
25087 // the "from" location must exist - use at()
25088 basic_json const v = result.at(from_ptr);
25089
25090 // The copy is functionally identical to an "add"
25091 // operation at the target location using the value
25092 // specified in the "from" member.
25093 operation_add(ptr, v);
25094 break;
25095 }
25096
25097 case patch_operations::test:
25098 {
25099 bool success = false;
25100 JSON_TRY
25101 {
25102 // check if "value" matches the one at "path"
25103 // the "path" location must exist - use at()
25104 success = (result.at(ptr) == get_value("test", "value", false));
25105 }
25107 {
25108 // ignore out of range errors: success remains false
25109 }
25110
25111 // throw an exception if the test fails
25112 if (JSON_HEDLEY_UNLIKELY(!success))
25113 {
25114 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
25115 }
25116
25117 break;
25118 }
25119
25120 case patch_operations::invalid:
25121 default:
25122 {
25123 // op must be "add", "remove", "replace", "move", "copy", or
25124 // "test"
25125 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
25126 }
25127 }
25128 }
25129 }
25130
25133 basic_json patch(const basic_json& json_patch) const
25134 {
25135 basic_json result = *this;
25136 result.patch_inplace(json_patch);
25137 return result;
25138 }
25139
25143 static basic_json diff(const basic_json& source, const basic_json& target,
25144 const string_t& path = "")
25145 {
25146 // the patch
25147 basic_json result(value_t::array);
25148
25149 // if the values are the same, return an empty patch
25150 if (source == target)
25151 {
25152 return result;
25153 }
25154
25155 if (source.type() != target.type())
25156 {
25157 // different types: replace value
25158 result.push_back(
25159 {
25160 {"op", "replace"}, {"path", path}, {"value", target}
25161 });
25162 return result;
25163 }
25164
25165 switch (source.type())
25166 {
25167 case value_t::array:
25168 {
25169 // first pass: traverse common elements
25170 std::size_t i = 0;
25171 while (i < source.size() && i < target.size())
25172 {
25173 // recursive call to compare array values at index i
25174 auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
25175 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25176 ++i;
25177 }
25178
25179 // We now reached the end of at least one array
25180 // in a second pass, traverse the remaining elements
25181
25182 // remove my remaining elements
25183 const auto end_index = static_cast<difference_type>(result.size());
25184 while (i < source.size())
25185 {
25186 // add operations in reverse order to avoid invalid
25187 // indices
25188 result.insert(result.begin() + end_index, object(
25189 {
25190 {"op", "remove"},
25191 {"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
25192 }));
25193 ++i;
25194 }
25195
25196 // add other remaining elements
25197 while (i < target.size())
25198 {
25199 result.push_back(
25200 {
25201 {"op", "add"},
25202 {"path", detail::concat<string_t>(path, "/-")},
25203 {"value", target[i]}
25204 });
25205 ++i;
25206 }
25207
25208 break;
25209 }
25210
25211 case value_t::object:
25212 {
25213 // first pass: traverse this object's elements
25214 for (auto it = source.cbegin(); it != source.cend(); ++it)
25215 {
25216 // escape the key name to be used in a JSON patch
25217 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25218
25219 if (target.find(it.key()) != target.end())
25220 {
25221 // recursive call to compare object values at key it
25222 auto temp_diff = diff(it.value(), target[it.key()], path_key);
25223 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25224 }
25225 else
25226 {
25227 // found a key that is not in o -> remove it
25228 result.push_back(object(
25229 {
25230 {"op", "remove"}, {"path", path_key}
25231 }));
25232 }
25233 }
25234
25235 // second pass: traverse other object's elements
25236 for (auto it = target.cbegin(); it != target.cend(); ++it)
25237 {
25238 if (source.find(it.key()) == source.end())
25239 {
25240 // found a key that is not in this -> add it
25241 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25242 result.push_back(
25243 {
25244 {"op", "add"}, {"path", path_key},
25245 {"value", it.value()}
25246 });
25247 }
25248 }
25249
25250 break;
25251 }
25252
25253 case value_t::null:
25254 case value_t::string:
25255 case value_t::boolean:
25256 case value_t::number_integer:
25257 case value_t::number_unsigned:
25258 case value_t::number_float:
25259 case value_t::binary:
25260 case value_t::discarded:
25261 default:
25262 {
25263 // both primitive types: replace value
25264 result.push_back(
25265 {
25266 {"op", "replace"}, {"path", path}, {"value", target}
25267 });
25268 break;
25269 }
25270 }
25271
25272 return result;
25273 }
25275
25277 // JSON Merge Patch functions //
25279
25282
25285 void merge_patch(const basic_json& apply_patch)
25286 {
25287 if (apply_patch.is_object())
25288 {
25289 if (!is_object())
25290 {
25291 *this = object();
25292 }
25293 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
25294 {
25295 if (it.value().is_null())
25296 {
25297 erase(it.key());
25298 }
25299 else
25300 {
25301 operator[](it.key()).merge_patch(it.value());
25302 }
25303 }
25304 }
25305 else
25306 {
25307 *this = apply_patch;
25308 }
25309 }
25310
25312};
25313
25318{
25319 return j.dump();
25320}
25321
25322inline namespace literals
25323{
25324inline namespace json_literals
25325{
25326
25330#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25331 inline nlohmann::json operator ""_json(const char* s, std::size_t n)
25332#else
25333 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
25334#endif
25335{
25336 return nlohmann::json::parse(s, s + n);
25337}
25338
25342#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25343 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
25344#else
25345 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
25346#endif
25347{
25348 return nlohmann::json::json_pointer(std::string(s, n));
25349}
25350
25351} // namespace json_literals
25352} // namespace literals
25354
25356// nonmember support //
25358
25359namespace std // NOLINT(cert-dcl58-cpp)
25360{
25361
25365struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
25366{
25367 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
25368 {
25369 return nlohmann::detail::hash(j);
25370 }
25371};
25372
25373// specialization for std::less<value_t>
25374template<>
25375struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
25376{
25381 bool operator()(::nlohmann::detail::value_t lhs,
25382 ::nlohmann::detail::value_t rhs) const noexcept
25383 {
25384#if JSON_HAS_THREE_WAY_COMPARISON
25385 return std::is_lt(lhs <=> rhs); // *NOPAD*
25386#else
25387 return ::nlohmann::detail::operator<(lhs, rhs);
25388#endif
25389 }
25390};
25391
25392// C++20 prohibit function specialization in the std namespace.
25393#ifndef JSON_HAS_CPP_20
25394
25398inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
25399 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
25400 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
25401{
25402 j1.swap(j2);
25403}
25404
25405#endif
25406
25407} // namespace std
25408
25409#if JSON_USE_GLOBAL_UDLS
25410 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25411 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25412 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25413 #else
25414 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25415 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25416 #endif
25417#endif
25418
25419// #include <nlohmann/detail/macro_unscope.hpp>
25420// __ _____ _____ _____
25421// __| | __| | | | JSON for Modern C++
25422// | | |__ | | | | | | version 3.12.0
25423// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25424//
25425// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25426// SPDX-License-Identifier: MIT
25427
25428
25429
25430// restore clang diagnostic settings
25431#if defined(__clang__)
25432 #pragma clang diagnostic pop
25433#endif
25434
25435// clean up
25436#undef JSON_ASSERT
25437#undef JSON_INTERNAL_CATCH
25438#undef JSON_THROW
25439#undef JSON_PRIVATE_UNLESS_TESTED
25440#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
25441#undef NLOHMANN_BASIC_JSON_TPL
25442#undef JSON_EXPLICIT
25443#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
25444#undef JSON_INLINE_VARIABLE
25445#undef JSON_NO_UNIQUE_ADDRESS
25446#undef JSON_DISABLE_ENUM_SERIALIZATION
25447#undef JSON_USE_GLOBAL_UDLS
25448
25449#ifndef JSON_TEST_KEEP_MACROS
25450 #undef JSON_CATCH
25451 #undef JSON_TRY
25452 #undef JSON_HAS_CPP_11
25453 #undef JSON_HAS_CPP_14
25454 #undef JSON_HAS_CPP_17
25455 #undef JSON_HAS_CPP_20
25456 #undef JSON_HAS_CPP_23
25457 #undef JSON_HAS_CPP_26
25458 #undef JSON_HAS_FILESYSTEM
25459 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
25460 #undef JSON_HAS_THREE_WAY_COMPARISON
25461 #undef JSON_HAS_RANGES
25462 #undef JSON_HAS_STATIC_RTTI
25463 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
25464#endif
25465
25466// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
25467// __ _____ _____ _____
25468// __| | __| | | | JSON for Modern C++
25469// | | |__ | | | | | | version 3.12.0
25470// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25471//
25472// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25473// SPDX-License-Identifier: MIT
25474
25475
25476
25477#undef JSON_HEDLEY_ALWAYS_INLINE
25478#undef JSON_HEDLEY_ARM_VERSION
25479#undef JSON_HEDLEY_ARM_VERSION_CHECK
25480#undef JSON_HEDLEY_ARRAY_PARAM
25481#undef JSON_HEDLEY_ASSUME
25482#undef JSON_HEDLEY_BEGIN_C_DECLS
25483#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
25484#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
25485#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
25486#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
25487#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
25488#undef JSON_HEDLEY_CLANG_HAS_FEATURE
25489#undef JSON_HEDLEY_CLANG_HAS_WARNING
25490#undef JSON_HEDLEY_COMPCERT_VERSION
25491#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
25492#undef JSON_HEDLEY_CONCAT
25493#undef JSON_HEDLEY_CONCAT3
25494#undef JSON_HEDLEY_CONCAT3_EX
25495#undef JSON_HEDLEY_CONCAT_EX
25496#undef JSON_HEDLEY_CONST
25497#undef JSON_HEDLEY_CONSTEXPR
25498#undef JSON_HEDLEY_CONST_CAST
25499#undef JSON_HEDLEY_CPP_CAST
25500#undef JSON_HEDLEY_CRAY_VERSION
25501#undef JSON_HEDLEY_CRAY_VERSION_CHECK
25502#undef JSON_HEDLEY_C_DECL
25503#undef JSON_HEDLEY_DEPRECATED
25504#undef JSON_HEDLEY_DEPRECATED_FOR
25505#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
25506#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
25507#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
25508#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
25509#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
25510#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
25511#undef JSON_HEDLEY_DIAGNOSTIC_POP
25512#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
25513#undef JSON_HEDLEY_DMC_VERSION
25514#undef JSON_HEDLEY_DMC_VERSION_CHECK
25515#undef JSON_HEDLEY_EMPTY_BASES
25516#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
25517#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
25518#undef JSON_HEDLEY_END_C_DECLS
25519#undef JSON_HEDLEY_FLAGS
25520#undef JSON_HEDLEY_FLAGS_CAST
25521#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
25522#undef JSON_HEDLEY_GCC_HAS_BUILTIN
25523#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
25524#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
25525#undef JSON_HEDLEY_GCC_HAS_EXTENSION
25526#undef JSON_HEDLEY_GCC_HAS_FEATURE
25527#undef JSON_HEDLEY_GCC_HAS_WARNING
25528#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
25529#undef JSON_HEDLEY_GCC_VERSION
25530#undef JSON_HEDLEY_GCC_VERSION_CHECK
25531#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
25532#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
25533#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
25534#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
25535#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
25536#undef JSON_HEDLEY_GNUC_HAS_FEATURE
25537#undef JSON_HEDLEY_GNUC_HAS_WARNING
25538#undef JSON_HEDLEY_GNUC_VERSION
25539#undef JSON_HEDLEY_GNUC_VERSION_CHECK
25540#undef JSON_HEDLEY_HAS_ATTRIBUTE
25541#undef JSON_HEDLEY_HAS_BUILTIN
25542#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
25543#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
25544#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
25545#undef JSON_HEDLEY_HAS_EXTENSION
25546#undef JSON_HEDLEY_HAS_FEATURE
25547#undef JSON_HEDLEY_HAS_WARNING
25548#undef JSON_HEDLEY_IAR_VERSION
25549#undef JSON_HEDLEY_IAR_VERSION_CHECK
25550#undef JSON_HEDLEY_IBM_VERSION
25551#undef JSON_HEDLEY_IBM_VERSION_CHECK
25552#undef JSON_HEDLEY_IMPORT
25553#undef JSON_HEDLEY_INLINE
25554#undef JSON_HEDLEY_INTEL_CL_VERSION
25555#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
25556#undef JSON_HEDLEY_INTEL_VERSION
25557#undef JSON_HEDLEY_INTEL_VERSION_CHECK
25558#undef JSON_HEDLEY_IS_CONSTANT
25559#undef JSON_HEDLEY_IS_CONSTEXPR_
25560#undef JSON_HEDLEY_LIKELY
25561#undef JSON_HEDLEY_MALLOC
25562#undef JSON_HEDLEY_MCST_LCC_VERSION
25563#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
25564#undef JSON_HEDLEY_MESSAGE
25565#undef JSON_HEDLEY_MSVC_VERSION
25566#undef JSON_HEDLEY_MSVC_VERSION_CHECK
25567#undef JSON_HEDLEY_NEVER_INLINE
25568#undef JSON_HEDLEY_NON_NULL
25569#undef JSON_HEDLEY_NO_ESCAPE
25570#undef JSON_HEDLEY_NO_RETURN
25571#undef JSON_HEDLEY_NO_THROW
25572#undef JSON_HEDLEY_NULL
25573#undef JSON_HEDLEY_PELLES_VERSION
25574#undef JSON_HEDLEY_PELLES_VERSION_CHECK
25575#undef JSON_HEDLEY_PGI_VERSION
25576#undef JSON_HEDLEY_PGI_VERSION_CHECK
25577#undef JSON_HEDLEY_PREDICT
25578#undef JSON_HEDLEY_PRINTF_FORMAT
25579#undef JSON_HEDLEY_PRIVATE
25580#undef JSON_HEDLEY_PUBLIC
25581#undef JSON_HEDLEY_PURE
25582#undef JSON_HEDLEY_REINTERPRET_CAST
25583#undef JSON_HEDLEY_REQUIRE
25584#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
25585#undef JSON_HEDLEY_REQUIRE_MSG
25586#undef JSON_HEDLEY_RESTRICT
25587#undef JSON_HEDLEY_RETURNS_NON_NULL
25588#undef JSON_HEDLEY_SENTINEL
25589#undef JSON_HEDLEY_STATIC_ASSERT
25590#undef JSON_HEDLEY_STATIC_CAST
25591#undef JSON_HEDLEY_STRINGIFY
25592#undef JSON_HEDLEY_STRINGIFY_EX
25593#undef JSON_HEDLEY_SUNPRO_VERSION
25594#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
25595#undef JSON_HEDLEY_TINYC_VERSION
25596#undef JSON_HEDLEY_TINYC_VERSION_CHECK
25597#undef JSON_HEDLEY_TI_ARMCL_VERSION
25598#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
25599#undef JSON_HEDLEY_TI_CL2000_VERSION
25600#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
25601#undef JSON_HEDLEY_TI_CL430_VERSION
25602#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
25603#undef JSON_HEDLEY_TI_CL6X_VERSION
25604#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
25605#undef JSON_HEDLEY_TI_CL7X_VERSION
25606#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
25607#undef JSON_HEDLEY_TI_CLPRU_VERSION
25608#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
25609#undef JSON_HEDLEY_TI_VERSION
25610#undef JSON_HEDLEY_TI_VERSION_CHECK
25611#undef JSON_HEDLEY_UNAVAILABLE
25612#undef JSON_HEDLEY_UNLIKELY
25613#undef JSON_HEDLEY_UNPREDICTABLE
25614#undef JSON_HEDLEY_UNREACHABLE
25615#undef JSON_HEDLEY_UNREACHABLE_RETURN
25616#undef JSON_HEDLEY_VERSION
25617#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
25618#undef JSON_HEDLEY_VERSION_DECODE_MINOR
25619#undef JSON_HEDLEY_VERSION_DECODE_REVISION
25620#undef JSON_HEDLEY_VERSION_ENCODE
25621#undef JSON_HEDLEY_WARNING
25622#undef JSON_HEDLEY_WARN_UNUSED_RESULT
25623#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
25624#undef JSON_HEDLEY_FALL_THROUGH
25625
25626
25627
25628#endif // INCLUDE_NLOHMANN_JSON_HPP_
a class to store JSON values
Definition json.hpp:20202
constexpr bool is_string() const noexcept
return whether value is a string
Definition json.hpp:21501
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:22736
reference operator[](KeyType &&key)
access specified object element
Definition json.hpp:22302
size_type size() const noexcept
returns the number of elements
Definition json.hpp:23077
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:24541
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:21874
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22934
reference back()
access the last element
Definition json.hpp:22540
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:20941
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22950
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition json.hpp:25133
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
Definition json.hpp:24300
const_reference front() const
access the first element
Definition json.hpp:22533
constexpr bool is_array() const noexcept
return whether value is an array
Definition json.hpp:21494
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:23595
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22483
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22853
iter_impl< const basic_json > const_iterator
a const iterator for a basic_json container
Definition json.hpp:20336
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition json.hpp:21466
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition json.hpp:20340
data(size_type cnt, const basic_json &val)
Definition json.hpp:24345
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:24736
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24781
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition json.hpp:20331
std::size_t size_type
a type to represent container sizes
Definition json.hpp:20323
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.hpp:21438
const_reference operator[](KeyType &&key) const
access specified object element
Definition json.hpp:22326
void swap(binary_t &other)
exchanges the values
Definition json.hpp:23672
ReferenceType get_ref()
get a reference value (implicit)
Definition json.hpp:21964
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.hpp:23116
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:23541
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:21975
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:21515
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.hpp:23332
void push_back(basic_json &&val)
add an object to an array
Definition json.hpp:23220
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition json.hpp:22271
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:23022
const_reference back() const
access the last element
Definition json.hpp:22549
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:22631
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:23277
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:23612
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:24637
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:21083
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition json.hpp:23444
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:24721
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:20346
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
Definition json.hpp:20471
reference at(KeyType &&key)
access specified object element with bounds checking
Definition json.hpp:22134
iterator end() noexcept
returns an iterator to one past the last element
Definition json.hpp:22925
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:21473
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:23548
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition json.hpp:24500
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22957
data m_data
Definition json.hpp:24363
void push_back(initializer_list_t init)
add an object to an object
Definition json.hpp:23316
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
Definition json.hpp:20908
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.hpp:21124
ValueType & get_to(ValueType &v) const
Definition json.hpp:21941
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:24436
iterator begin() noexcept
returns an iterator to the first element
Definition json.hpp:22900
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition json.hpp:22381
const_iterator cend() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22941
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:24691
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24823
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition json.hpp:21094
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:20929
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:24525
basic_json flatten() const
return flattened JSON value
Definition json.hpp:24837
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:24652
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition json.hpp:22747
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:24221
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition json.hpp:20447
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:20439
const binary_t & get_binary() const
get a binary value
Definition json.hpp:22046
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition json.hpp:23464
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition json.hpp:24862
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22434
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24795
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition json.hpp:20280
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition json.hpp:22870
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:24406
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:24516
iterator find(const typename object_t::key_type &key)
find an element in a JSON object
Definition json.hpp:22783
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:21072
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:24470
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition json.hpp:22172
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.hpp:20354
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:21131
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition json.hpp:22797
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.hpp:24397
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:22561
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition json.hpp:23417
NumberFloatType number_float_t
a type for a number (floating-point)
Definition json.hpp:20467
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:22356
AllocatorType< basic_json > allocator_type
the allocator type
Definition json.hpp:20326
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition json.hpp:20329
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:21402
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.hpp:25285
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:21928
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:24482
reference operator[](T *key)
Definition json.hpp:22287
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:22068
iterator find(KeyType &&key)
find an element in a JSON object
Definition json.hpp:22813
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition json.hpp:21480
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.hpp:22964
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:24443
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24809
BooleanType boolean_t
a type for a boolean
Definition json.hpp:20455
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:25143
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:20434
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:23308
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition json.hpp:22916
reference operator[](typename object_t::key_type key)
access specified object element
Definition json.hpp:22249
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:21686
~basic_json() noexcept
destructor
Definition json.hpp:21384
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition json.hpp:22985
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:21013
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.hpp:23688
binary_t & get_binary()
get a binary value
Definition json.hpp:22034
const_iterator begin() const noexcept
returns an iterator to the first element
Definition json.hpp:22909
constexpr bool is_number() const noexcept
return whether value is a number
Definition json.hpp:21459
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition json.hpp:23515
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:24583
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:21915
const_reference operator[](T *key) const
Definition json.hpp:22293
data(const value_t v)
Definition json.hpp:24340
reference operator[](size_type idx)
access specified array element
Definition json.hpp:22190
basic_json(const JsonRef &ref)
Definition json.hpp:21252
JSONSerializer< T, SFINAE > json_serializer
Definition json.hpp:20272
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value &&std::is_nothrow_move_assignable< json_base_class_t >::value)
copy assignment
Definition json.hpp:21355
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:24462
Array get_to(T(&v)[N]) const noexcept(noexcept(JSONSerializer< Array >::from_json(std::declval< const basic_json_t & >(), v)))
Definition json.hpp:21952
NumberIntegerType number_integer_t
a type for a number (integer)
Definition json.hpp:20459
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:21675
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:22152
constexpr bool is_binary() const noexcept
return whether value is a binary array
Definition json.hpp:21508
void swap(object_t &other)
exchanges the values
Definition json.hpp:23640
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.hpp:24846
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition json.hpp:23495
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:24491
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:21105
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:23015
bool empty() const noexcept
checks whether the container is empty.
Definition json.hpp:23038
void swap(array_t &other)
exchanges the values
Definition json.hpp:23624
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:22754
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:23245
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.hpp:22877
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.hpp:21424
reference emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:23341
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22457
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.hpp:21116
data() noexcept=default
StringType string_t
a type for a string
Definition json.hpp:20451
void push_back(const basic_json &val)
add an object to an array
Definition json.hpp:23253
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:22407
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:22114
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:24706
json_value m_value
the value of the current element
Definition json.hpp:24338
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.hpp:22978
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition json.hpp:21452
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:22843
reference front()
access the first element
Definition json.hpp:22526
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:21431
constexpr bool is_null() const noexcept
return whether value is null
Definition json.hpp:21445
void clear() noexcept
clears the contents
Definition json.hpp:23159
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:24454
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:21329
iter_impl< basic_json > iterator
an iterator for a basic_json container
Definition json.hpp:20334
basic_json(const value_t v)
create an empty value with a given type
Definition json.hpp:20921
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:22236
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition json.hpp:20321
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition json.hpp:23437
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition json.hpp:22971
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition json.hpp:20463
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition json.hpp:24285
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:24420
void swap(string_t &other)
exchanges the values
Definition json.hpp:23656
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.hpp:20955
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition json.hpp:20338
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:22091
detail::actual_object_comparator_t< basic_json > object_comparator_t
object key comparator type
Definition json.hpp:20475
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:21256
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:23285
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:23366
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:24413
constexpr bool is_object() const noexcept
return whether value is an object
Definition json.hpp:21487
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:24429
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:24598
iterator insert_iterator(const_iterator pos, Args &&... args)
Helper for insertion of an iterator.
Definition json.hpp:23398
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:21143
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition json.hpp:22861
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:24509
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition json.hpp:22829
::nlohmann::json_pointer< StringType > json_pointer
JSON Pointer, see nlohmann::json_pointer.
Definition json.hpp:20270
an internal type for a backed binary type
Definition json.hpp:6239
bool operator!=(const byte_container_with_subtype &rhs) const
Definition json.hpp:6279
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.hpp:6245
std::uint64_t subtype_type
Definition json.hpp:6242
bool operator==(const byte_container_with_subtype &rhs) const
Definition json.hpp:6273
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6267
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6255
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.hpp:6294
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.hpp:6260
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.hpp:6301
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.hpp:6250
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.hpp:6286
void clear_subtype() noexcept
clears the binary subtype
Definition json.hpp:6308
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:9891
binary_reader(const binary_reader &)=delete
binary_reader(binary_reader &&)=default
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.hpp:9907
binary_reader & operator=(const binary_reader &)=delete
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:9928
binary_reader & operator=(binary_reader &&)=default
serialization to CBOR and MessagePack values
Definition json.hpp:15862
void write_bson(const BasicJsonType &j)
Definition json.hpp:15882
static constexpr CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:17622
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:16562
static CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:17629
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition json.hpp:15873
static constexpr CharType to_char_type(InputCharType x) noexcept
Definition json.hpp:17664
void write_msgpack(const BasicJsonType &j)
Definition json.hpp:16235
void write_cbor(const BasicJsonType &j)
Definition json.hpp:15911
general exception of the basic_json class
Definition json.hpp:4540
const int id
the id of the exception
Definition json.hpp:4549
static std::string diagnostics(std::nullptr_t)
Definition json.hpp:4560
static std::string name(const std::string &ename, int id_)
Definition json.hpp:4555
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:4543
static std::string diagnostics(const BasicJsonType *leaf_element)
Definition json.hpp:4566
file_input_adapter(const file_input_adapter &)=delete
std::char_traits< char >::int_type get_character() noexcept
Definition json.hpp:6559
file_input_adapter(file_input_adapter &&) noexcept=default
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6566
input_stream_adapter & operator=(input_stream_adapter &&)=delete
input_stream_adapter(input_stream_adapter &&rhs) noexcept
Definition json.hpp:6609
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6631
std::char_traits< char >::int_type get_character()
Definition json.hpp:6619
input_stream_adapter(const input_stream_adapter &)=delete
input_stream_adapter & operator=(input_stream_adapter &)=delete
input_stream_adapter(std::istream &i)
Definition json.hpp:6600
exception indicating errors with iterators
Definition json.hpp:4709
static invalid_iterator create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4712
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition json.hpp:13681
~iter_impl()=default
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:14264
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:13818
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:14209
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:13808
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:14151
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:14191
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:14255
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:14061
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:14364
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.hpp:14102
iter_impl operator++(int) &
post-increment (it++)
Definition json.hpp:13999
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:14218
reference operator[](difference_type n) const
access to successor
Definition json.hpp:14326
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:13713
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition json.hpp:13711
pointer operator->() const
dereference the iterator
Definition json.hpp:13957
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
Definition json.hpp:14389
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:14297
iter_impl(iter_impl &&) noexcept=default
std::bidirectional_iterator_tag iterator_category
The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
Definition json.hpp:13706
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:14275
reference value() const
return the value of an iterator
Definition json.hpp:14380
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:14200
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:14010
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition json.hpp:13709
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:13913
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:14286
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:13717
iter_impl()=default
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.hpp:13793
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition json.hpp:14142
iter_impl operator--(int) &
post-decrement (it–)
Definition json.hpp:14050
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.hpp:13783
void set_end() noexcept
set the iterator past the last value
Definition json.hpp:13874
iteration_proxy_value operator++(int) &
Definition json.hpp:5557
iteration_proxy_value(iteration_proxy_value const &)=default
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.hpp:5566
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.hpp:5572
std::ptrdiff_t difference_type
Definition json.hpp:5503
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:5524
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:5549
std::forward_iterator_tag iterator_category
Definition json.hpp:5507
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:5614
const string_type & key() const
return key of the iterator
Definition json.hpp:5578
iteration_proxy_value & operator=(iteration_proxy_value const &)=default
typename std::remove_cv< typename std::remove_reference< decltype(std::declval< IteratorType >().key()) >::type >::type string_type
Definition json.hpp:5508
proxy class for the items() function
Definition json.hpp:13660
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.hpp:5647
iteration_proxy(iteration_proxy const &)=default
iteration_proxy(iteration_proxy &&) noexcept=default
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:5631
iteration_proxy & operator=(iteration_proxy const &)=default
char_traits< char_type >::int_type get_character()
Definition json.hpp:6660
iterator_input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:6656
typename std::iterator_traits< IteratorType >::value_type char_type
Definition json.hpp:6654
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6674
json_ref(json_ref &&) noexcept=default
json_ref(const value_type &value)
Definition json.hpp:15602
json_ref(value_type &&value)
Definition json.hpp:15598
value_type const & operator*() const
Definition json.hpp:15633
value_type const * operator->() const
Definition json.hpp:15638
json_ref(std::initializer_list< json_ref > init)
Definition json.hpp:15606
json_ref(Args &&... args)
Definition json.hpp:15613
value_type moved_or_copied() const
Definition json.hpp:15624
BasicJsonType value_type
Definition json.hpp:15596
a template for a reverse iterator class
Definition json.hpp:14443
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition json.hpp:14459
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition json.hpp:14471
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.hpp:14465
std::ptrdiff_t difference_type
Definition json.hpp:14445
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.hpp:14483
reference operator[](difference_type n) const
access to successor
Definition json.hpp:14507
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.hpp:14513
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.hpp:14501
typename Base::reference reference
the reference type for the pointed-to element
Definition json.hpp:14449
reference value() const
return the value of an iterator
Definition json.hpp:14520
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.hpp:14456
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.hpp:14477
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.hpp:14447
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.hpp:14495
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.hpp:14452
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.hpp:14489
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9609
bool binary(binary_t &)
Definition json.hpp:9644
bool number_integer(number_integer_t)
Definition json.hpp:9624
bool start_array(std::size_t=detail::unknown_size())
Definition json.hpp:9664
bool number_unsigned(number_unsigned_t)
Definition json.hpp:9629
bool start_object(std::size_t=detail::unknown_size())
Definition json.hpp:9649
bool string(string_t &)
Definition json.hpp:9639
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9612
bool number_float(number_float_t, const string_t &)
Definition json.hpp:9634
bool parse_error(std::size_t, const std::string &, const detail::exception &)
Definition json.hpp:9674
bool key(string_t &)
Definition json.hpp:9654
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9608
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9610
typename BasicJsonType::string_t string_t
Definition json.hpp:9611
bool start_array(std::size_t len)
Definition json.hpp:9337
typename BasicJsonType::parser_callback_t parser_callback_t
Definition json.hpp:9176
typename BasicJsonType::parse_event_t parse_event_t
Definition json.hpp:9177
json_sax_dom_callback_parser & operator=(json_sax_dom_callback_parser &&)=default
bool number_integer(number_integer_t val)
Definition json.hpp:9208
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:9416
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9173
json_sax_dom_callback_parser & operator=(const json_sax_dom_callback_parser &)=delete
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:9214
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:9220
constexpr bool is_errored() const
Definition json.hpp:9428
json_sax_dom_callback_parser(BasicJsonType &r, parser_callback_t cb, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.hpp:9180
typename BasicJsonType::string_t string_t
Definition json.hpp:9174
json_sax_dom_callback_parser(json_sax_dom_callback_parser &&)=default
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9172
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9171
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9175
bool start_object(std::size_t len)
Definition json.hpp:9238
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:8863
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:8912
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:8906
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:8924
typename BasicJsonType::binary_t binary_t
Definition json.hpp:8869
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.hpp:8877
bool start_object(std::size_t len)
Definition json.hpp:8930
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:8865
bool key(string_t &val)
Definition json.hpp:8953
typename BasicJsonType::string_t string_t
Definition json.hpp:8868
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:8866
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:9021
bool boolean(bool val)
Definition json.hpp:8894
bool start_array(std::size_t len)
Definition json.hpp:8981
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:8867
json_sax_dom_parser(json_sax_dom_parser &&)=default
constexpr bool is_errored() const
Definition json.hpp:9033
bool string(string_t &val)
Definition json.hpp:8918
json_sax_dom_parser & operator=(json_sax_dom_parser &&)=default
bool number_integer(number_integer_t val)
Definition json.hpp:8900
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:7130
token_type
token types for the parser
Definition json.hpp:7107
@ 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:7180
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.hpp:8562
void skip_whitespace()
Definition json.hpp:8576
lexer(InputAdapterType &&adapter, bool ignore_comments_=false) noexcept
Definition json.hpp:7191
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.hpp:8549
std::string get_token_string() const
return the last read token (for errors only).
Definition json.hpp:8524
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.hpp:8483
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.hpp:8516
token_type scan()
Definition json.hpp:8585
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.hpp:8489
typename lexer_base< BasicJsonType >::token_type token_type
Definition json.hpp:7189
lexer(lexer &&)=default
~lexer()=default
lexer & operator=(lexer &&)=default
lexer(const lexer &)=delete
lexer & operator=(lexer &)=delete
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.hpp:8501
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.hpp:8495
exception indicating other library errors
Definition json.hpp:4761
static other_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4764
exception indicating access out of the defined range
Definition json.hpp:4744
static out_of_range create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4747
output_adapter(StringType &s)
Definition json.hpp:15824
output_adapter(std::basic_ostream< CharType > &s)
Definition json.hpp:15820
output_adapter(std::vector< CharType, AllocatorType > &vec)
Definition json.hpp:15816
output adapter for output streams
Definition json.hpp:15765
output_stream_adapter(std::basic_ostream< CharType > &s) noexcept
Definition json.hpp:15767
void write_character(CharType c) override
Definition json.hpp:15771
output adapter for basic_string
Definition json.hpp:15790
void write_character(CharType c) override
Definition json.hpp:15796
output_string_adapter(StringType &s) noexcept
Definition json.hpp:15792
output adapter for byte vectors
Definition json.hpp:15740
output_vector_adapter(std::vector< CharType, AllocatorType > &vec) noexcept
Definition json.hpp:15742
void write_character(CharType c) override
Definition json.hpp:15746
exception indicating a parse error
Definition json.hpp:4656
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:4668
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4676
const std::size_t byte
byte index of the parse error
Definition json.hpp:4693
syntax analysis
Definition json.hpp:12977
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.hpp:13011
bool accept(const bool strict=true)
public accept interface
Definition json.hpp:13071
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:12987
primitive_iterator_t & operator++() noexcept
Definition json.hpp:13560
primitive_iterator_t & operator-=(difference_type n) noexcept
Definition json.hpp:13592
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition json.hpp:13527
primitive_iterator_t & operator--() noexcept
Definition json.hpp:13573
void set_end() noexcept
set iterator to a defined past the end
Definition json.hpp:13521
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13543
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition json.hpp:13533
primitive_iterator_t operator++(int) &noexcept
Definition json.hpp:13566
primitive_iterator_t & operator+=(difference_type n) noexcept
Definition json.hpp:13586
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13538
constexpr difference_type get_value() const noexcept
Definition json.hpp:13509
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13555
primitive_iterator_t operator+(difference_type n) noexcept
Definition json.hpp:13548
void set_begin() noexcept
set iterator to a defined beginning
Definition json.hpp:13515
primitive_iterator_t operator--(int) &noexcept
Definition json.hpp:13579
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:18876
serializer & operator=(const serializer &)=delete
~serializer()=default
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition json.hpp:19793
string_t indent_string
the indentation string
Definition json.hpp:19790
serializer & operator=(serializer &&)=delete
const char indent_char
the indentation character
Definition json.hpp:19788
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:18916
serializer(const serializer &)=delete
serializer(serializer &&)=delete
span_input_adapter(CharT b, std::size_t l)
Definition json.hpp:7022
span_input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:7029
contiguous_bytes_input_adapter && get()
Definition json.hpp:7032
exception indicating executing a member function with a wrong type
Definition json.hpp:4727
static type_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4730
std::size_t get_elements(T *, std::size_t=1)
Definition json.hpp:6857
std::char_traits< char >::int_type get_character() noexcept
Definition json.hpp:6838
wide_string_input_adapter(BaseInputAdapter base)
Definition json.hpp:6835
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition json.hpp:14615
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:14710
typename string_t_helper< RefStringType >::type string_t
Definition json.hpp:14637
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:14717
json_pointer(const string_t &s="")
create JSON pointer
Definition json.hpp:14641
bool empty() const noexcept
return whether pointer points to the root document
Definition json.hpp:14776
void pop_back()
remove last reference token
Definition json.hpp:14738
string_t to_string() const
return a string representation of the JSON pointer
Definition json.hpp:14647
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition json.hpp:14695
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14769
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition json.hpp:14677
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:14702
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition json.hpp:14724
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition json.hpp:14687
const string_t & back() const
return last reference token
Definition json.hpp:14750
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition json.hpp:14668
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14762
decltype( get< N >(std::declval< ::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
Definition json.hpp:5693
int n
Definition main.c:10
v[0]
Definition main.c:4
return
Definition main.c:20
int * p
Definition main.c:12
int E
Definition main.c:12
int * p2
Definition main.c:13
int * p1
Definition main.c:12
return ret
Definition sum.c:3
int B
Definition main.c:3
nlohmann::json json
Definition function.hpp:25
@ C
C programming language.
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
Definition json.hpp:2622
#define JSON_HEDLEY_CONST
Definition json.hpp:1829
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
Definition json.hpp:1113
#define JSON_INLINE_VARIABLE
Definition json.hpp:2521
#define JSON_HEDLEY_WARN_UNUSED_RESULT
Definition json.hpp:1459
#define JSON_PRIVATE_UNLESS_TESTED
Definition json.hpp:2581
#define NLOHMANN_JSON_VERSION_PATCH
Definition json.hpp:70
#define JSON_HEDLEY_LIKELY(expr)
Definition json.hpp:1724
bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15510
#define JSON_HEDLEY_NON_NULL(...)
Definition json.hpp:1617
#define JSON_INTERNAL_CATCH(exception)
Definition json.hpp:2548
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:25317
#define JSON_HEDLEY_RETURNS_NON_NULL
Definition json.hpp:2058
#define JSON_CATCH(exception)
Definition json.hpp:2547
#define JSON_ASSERT(x)
Definition json.hpp:2574
#define JSON_THROW(exception)
Definition json.hpp:2545
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
Definition json.hpp:81
#define NLOHMANN_JSON_VERSION_MAJOR
Definition json.hpp:68
bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15560
#define NLOHMANN_BASIC_JSON_TPL
Definition json.hpp:2632
#define JSON_HEDLEY_UNLIKELY(expr)
Definition json.hpp:1725
#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
Definition json.hpp:12866
#define JSON_TRY
Definition json.hpp:2546
#define NLOHMANN_JSON_NAMESPACE_END
Definition json.hpp:155
#define JSON_NO_UNIQUE_ADDRESS
Definition json.hpp:2527
#define NLOHMANN_JSON_VERSION_MINOR
Definition json.hpp:69
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)
Definition json.hpp:2916
bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15535
#define NLOHMANN_JSON_NAMESPACE_BEGIN
Definition json.hpp:145
#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
Definition json.hpp:12863
#define JSON_HEDLEY_DIAGNOSTIC_POP
Definition json.hpp:1114
#define JSON_EXPLICIT
Definition json.hpp:2953
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
Definition json.hpp:1407
#define JSON_HEDLEY_PURE
Definition json.hpp:1798
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)
Definition json.hpp:23713
#define JSON_DIAGNOSTIC_POSITIONS
Definition json.hpp:77
JSON_INLINE_VARIABLE constexpr const auto & from_json
Definition json.hpp:5394
JSON_INLINE_VARIABLE constexpr const auto & to_json
Definition json.hpp:6165
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
Definition json.hpp:18200
cached_power get_cached_power_for_binary_exponent(int e)
Definition json.hpp:18036
Target reinterpret_bits(const Source source)
Definition json.hpp:17756
boundaries compute_boundaries(FloatType value)
Definition json.hpp:17897
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:18254
constexpr int kAlpha
Definition json.hpp:18019
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition json.hpp:18536
constexpr int kGamma
Definition json.hpp:18020
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition json.hpp:18295
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition json.hpp:18636
constexpr bool is_transparent()
Definition json.hpp:4350
constexpr bool is_c_string()
Definition json.hpp:4322
detail namespace with internal helper functions
Definition json.hpp:260
make_integer_sequence< size_t, N > make_index_sequence
Definition json.hpp:3321
decltype(std::declval< StringType & >().append(std::declval< Arg && >())) string_can_append
Definition json.hpp:4425
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:4232
input_format_t
the supported input formats
Definition json.hpp:6529
typename detector< nonesuch, void, Op, Args... >::type detected_t
Definition json.hpp:311
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
Definition json.hpp:6110
decltype(T::to_json(std::declval< Args >()...)) to_json_function
Definition json.hpp:3649
decltype(std::declval< T & >().binary(std::declval< Binary & >())) binary_function_t
Definition json.hpp:9737
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:4166
is_detected< string_can_append_data, StringType, Arg > detect_string_can_append_data
Definition json.hpp:4446
decltype(std::declval< T & >().end_object()) end_object_function_t
Definition json.hpp:9749
OutStringType concat(Args &&... args)
Definition json.hpp:4505
typename T::value_type value_type_t
Definition json.hpp:3634
constexpr std::array< T, sizeof...(Args)> make_array(Args &&... args)
Definition json.hpp:3352
decltype(std::declval< T & >().boolean(std::declval< bool >())) boolean_function_t
Definition json.hpp:9717
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
Definition json.hpp:320
is_detected< string_can_append, StringType, Arg > detect_string_can_append
Definition json.hpp:4428
typename std::enable_if< B, T >::type enable_if_t
Definition json.hpp:3225
parse_event_t
Definition json.hpp:12951
@ 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
std::integral_constant< bool, all_signed< Types... >::value||all_unsigned< Types... >::value > same_sign
Definition json.hpp:4228
typename detector< nonesuch, void, Op, Args... >::value_t is_detected
Definition json.hpp:305
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:4148
typename T::pointer pointer_t
Definition json.hpp:3640
std::pair< A1, A2 > from_json_tuple_impl(BasicJsonType &&j, identity_tag< std::pair< A1, A2 > >, priority_tag< 0 >)
Definition json.hpp:5278
void from_json_array_impl(const BasicJsonType &j, typename BasicJsonType::array_t &arr, priority_tag< 3 >)
Definition json.hpp:5083
typename utility_internal::Gen< T, N >::type make_integer_sequence
Definition json.hpp:3313
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition json.hpp:15735
typename detected_or< Default, Op, Args... >::type detected_or_t
Definition json.hpp:317
decltype(std::declval< T & >().key(std::declval< String & >())) key_function_t
Definition json.hpp:9745
decltype(std::declval< T & >().null()) null_function_t
Definition json.hpp:9714
void int_to_string(StringType &target, std::size_t value)
Definition json.hpp:5475
T conditional_static_cast(U value)
Definition json.hpp:4206
typename T::difference_type difference_type_t
Definition json.hpp:3637
decltype(std::declval< T & >().start_object(std::declval< std::size_t >())) start_object_function_t
Definition json.hpp:9741
decltype(std::declval< T & >().number_float( std::declval< Float >(), std::declval< const String & >())) number_float_function_t
Definition json.hpp:9729
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.hpp:3101
decltype(std::declval< T & >().start_array(std::declval< std::size_t >())) start_array_function_t
Definition json.hpp:9752
is_detected< string_can_append_iter, StringType, Arg > detect_string_can_append_iter
Definition json.hpp:4440
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition json.hpp:5657
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:4179
typename actual_object_comparator< BasicJsonType >::type actual_object_comparator_t
Definition json.hpp:3728
decltype(std::declval< ObjectType & >().erase(std::declval< KeyType >())) detect_erase_with_key_type
Definition json.hpp:4175
decltype(input_adapter(std::declval< const char * >(), std::declval< const char * >())) contiguous_bytes_input_adapter
Definition json.hpp:6983
bool little_endianness(int num=1) noexcept
determine system byte order
Definition json.hpp:9877
cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:9864
@ store
store tags as binary type
@ error
throw a parse_error exception in case of a tag
value_type_t< iterator_traits< iterator_t< T > > > range_value_t
Definition json.hpp:3903
make_index_sequence< sizeof...(Ts)> index_sequence_for
Definition json.hpp:3329
void concat_into(OutStringType &)
Definition json.hpp:4421
constexpr bool value_in_range_of(T val)
Definition json.hpp:4306
value_t
the JSON type enumeration
Definition json.hpp:3003
@ 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)
decltype(T::from_json(std::declval< Args >()...)) from_json_function
Definition json.hpp:3652
constexpr std::size_t unknown_size()
Definition json.hpp:8843
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:5166
StringType to_string(std::size_t value)
Definition json.hpp:5483
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition json.hpp:6370
decltype(std::declval< T & >().number_integer(std::declval< Integer >())) number_integer_function_t
Definition json.hpp:9721
void unescape(StringType &s)
string unescaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3135
typename make_void< Ts... >::type void_t
Definition json.hpp:266
std::size_t combine(std::size_t seed, std::size_t h) noexcept
Definition json.hpp:6352
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:9759
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:3032
iterator_input_adapter_factory< IteratorType >::adapter_type input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:6919
enable_if_t< is_range< R >::value, result_of_begin< decltype(std::declval< R & >())> > iterator_t
Definition json.hpp:3900
typename T::iterator_category iterator_category_t
Definition json.hpp:3646
typename std::conditional< std::is_same< T, void >::value, json_default_base, T >::type json_base_class
Definition json.hpp:14565
error_handler_t
how to treat decoding errors
Definition json.hpp:18853
@ 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:4390
std::integral_constant< bool, Value > bool_constant
Definition json.hpp:4312
decltype(input_adapter(std::declval< std::string >())) string_input_adapter_type
Definition json.hpp:6959
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition json.hpp:3211
void from_json(const BasicJsonType &j, typename std::nullptr_t &n)
Definition json.hpp:4863
typename T::key_compare detect_key_compare
Definition json.hpp:3712
void to_json(BasicJsonType &j, T b) noexcept
Definition json.hpp:5971
void get_arithmetic_value(const BasicJsonType &j, ArithmeticType &val)
Definition json.hpp:4892
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
Definition json.hpp:323
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().begin(), std::declval< const Arg & >().end())) string_can_append_iter
Definition json.hpp:4437
decltype(std::declval< T & >().end_array()) end_array_function_t
Definition json.hpp:9756
std::tuple< Args... > from_json_tuple_impl_base(BasicJsonType &&j, index_sequence< Idx... >)
Definition json.hpp:5266
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().data(), std::declval< const Arg & >().size())) string_can_append_data
Definition json.hpp:4443
typename T::key_type key_type_t
Definition json.hpp:3631
typename T::reference reference_t
Definition json.hpp:3643
typename T::is_transparent detect_is_transparent
Definition json.hpp:4142
bjdata_version_t
how to encode BJData
Definition json.hpp:15848
is_detected< string_can_append_op, StringType, Arg > detect_string_can_append_op
Definition json.hpp:4434
typename T::mapped_type mapped_type_t
Definition json.hpp:3628
decltype(std::declval< StringType & >()+=std::declval< Arg && >()) string_can_append_op
Definition json.hpp:4431
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3120
decltype(std::declval< T & >().string(std::declval< String & >())) string_function_t
Definition json.hpp:9733
decltype(std::declval< T >().template get< U >()) get_template_function
Definition json.hpp:3655
decltype(std::declval< T & >().number_unsigned(std::declval< Unsigned >())) number_unsigned_function_t
Definition json.hpp:9725
std::function< bool(int, parse_event_t, BasicJsonType &)> parser_callback_t
Definition json.hpp:12967
name
Definition setup.py:13
Definition json.hpp:5678
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:25398
namespace for Niels Lohmann
Definition json.hpp:6181
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:6205
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:6195
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:6185
typename BasicJsonType::object_t object_t
Definition json.hpp:3721
typename BasicJsonType::default_object_comparator_t object_comparator_t
Definition json.hpp:3722
typename std::conditional< has_key_compare< object_t >::value, typename object_t::key_compare, object_comparator_t >::type type
Definition json.hpp:3723
static constexpr int_type eof() noexcept
Definition json.hpp:3781
static char_type to_char_type(int_type i) noexcept
Definition json.hpp:3776
static int_type to_int_type(char_type c) noexcept
Definition json.hpp:3771
static char_type to_char_type(int_type i) noexcept
Definition json.hpp:3752
static constexpr int_type eof() noexcept
Definition json.hpp:3757
static int_type to_int_type(char_type c) noexcept
Definition json.hpp:3747
std::false_type value_t
Definition json.hpp:293
Default type
Definition json.hpp:294
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition json.hpp:17790
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:17872
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition json.hpp:17855
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition json.hpp:17778
constexpr diyfp(std::uint64_t f_, int e_) noexcept
Definition json.hpp:17772
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
Definition json.hpp:5880
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
Definition json.hpp:5855
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
Definition json.hpp:5845
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
Definition json.hpp:5867
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
Definition json.hpp:5896
static void construct(BasicJsonType &j, const typename BasicJsonType::binary_t &b)
Definition json.hpp:5784
static void construct(BasicJsonType &j, typename BasicJsonType::binary_t &&b)
Definition json.hpp:5793
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
Definition json.hpp:5738
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
Definition json.hpp:5806
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
Definition json.hpp:5832
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
Definition json.hpp:5819
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
Definition json.hpp:5915
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
Definition json.hpp:5936
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
Definition json.hpp:5925
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
Definition json.hpp:5760
static void construct(BasicJsonType &j, const CompatibleStringType &str)
Definition json.hpp:5771
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
Definition json.hpp:5751
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:5377
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3674
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3689
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3704
static constexpr std::size_t size() noexcept
Definition json.hpp:3255
an iterator value
Definition json.hpp:13614
static constexpr auto value
Definition json.hpp:3975
ConstructibleStringType laundered_type
Definition json.hpp:3986
static constexpr auto value
Definition json.hpp:3989
static constexpr bool value
Definition json.hpp:3668
typename std::iterator_traits< T >::value_type value_type
Definition json.hpp:6896
static one test(decltype(&C::capacity))
static two test(...)
static constexpr bool value
Definition json.hpp:3896
iterator_input_adapter< iterator_type > adapter_type
Definition json.hpp:6885
typename std::iterator_traits< iterator_type >::value_type char_type
Definition json.hpp:6884
static adapter_type create(IteratorType first, IteratorType last)
Definition json.hpp:6887
Default base class of the basic_json class.
Definition json.hpp:14562
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:15721
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:3166
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:3170
std::size_t lines_read
the number of lines read
Definition json.hpp:3172
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:3168
static JSON_INLINE_VARIABLE constexpr T value
Definition json.hpp:3343
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:6150
typename Extend< typename Gen< T, N/2 >::type, N/2, N % 2 >::type type
Definition json.hpp:3293
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:6770
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:6712
SAX interface.
Definition json.hpp:8728
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:8729
typename BasicJsonType::string_t string_t
Definition json.hpp:8732
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:8731
virtual bool null()=0
a null value was read
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:8730
json_sax(json_sax &&) noexcept=default
typename BasicJsonType::binary_t binary_t
Definition json.hpp:8733
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:19835
std::vector< std::pair< const Key, T >, Allocator > Container
Definition json.hpp:19838
std::pair< iterator, bool > insert(value_type &&value)
Definition json.hpp:20129
typename Container::value_type value_type
Definition json.hpp:19842
std::equal_to< Key > key_compare
Definition json.hpp:19846
iterator erase(iterator pos)
Definition json.hpp:20007
ordered_map(const Allocator &alloc) noexcept(noexcept(Container(alloc)))
Definition json.hpp:19852
T & operator[](KeyType &&key)
Definition json.hpp:19894
typename Container::iterator iterator
Definition json.hpp:19839
const T & at(KeyType &&key) const
Definition json.hpp:19954
T & at(KeyType &&key)
Definition json.hpp:19926
const T & operator[](KeyType &&key) const
Definition json.hpp:19906
iterator find(const key_type &key)
Definition json.hpp:20091
iterator erase(iterator first, iterator last)
Definition json.hpp:20012
const T & at(const key_type &key) const
Definition json.hpp:19939
const_iterator find(const key_type &key) const
Definition json.hpp:20117
T & operator[](const key_type &key)
Definition json.hpp:19887
size_type erase(KeyType &&key)
Definition json.hpp:19988
typename Container::size_type size_type
Definition json.hpp:19841
ordered_map() noexcept(noexcept(Container()))
Definition json.hpp:19851
void insert(InputIt first, InputIt last)
Definition json.hpp:20152
size_type count(const key_type &key) const
Definition json.hpp:20065
std::pair< iterator, bool > emplace(KeyType &&key, T &&t)
Definition json.hpp:19874
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:20148
size_type erase(const key_type &key)
Definition json.hpp:19967
ordered_map(std::initializer_list< value_type > init, const Allocator &alloc=Allocator())
Definition json.hpp:19856
std::pair< iterator, bool > insert(const value_type &value)
Definition json.hpp:20134
size_type count(KeyType &&key) const
Definition json.hpp:20079
ordered_map(It first, It last, const Allocator &alloc=Allocator())
Definition json.hpp:19854
const T & operator[](const key_type &key) const
Definition json.hpp:19899
iterator find(KeyType &&key)
Definition json.hpp:20105
T & at(const key_type &key)
Definition json.hpp:19911
typename Container::const_iterator const_iterator
Definition json.hpp:19840
std::pair< iterator, bool > emplace(const key_type &key, T &&t)
Definition json.hpp:19859
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL &j) const
Definition json.hpp:25367
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:25381