Server
 
로딩중...
검색중...
일치하는것 없음
json.hpp
이 파일의 Documentation 페이지로 가기
1
6// __ _____ _____ _____
7// __| | __| | | | JSON for Modern C++
8// | | |__ | | | | | | version 3.12.0
9// |_____|_____|_____|_|___| https://github.com/nlohmann/json
10//
11// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
12// SPDX-License-Identifier: MIT
13
14/****************************************************************************\
15 * Note on documentation: The source files contain links to the online *
16 * documentation of the public API at https://json.nlohmann.me. This URL *
17 * contains the most recent documentation and should also be applicable to *
18 * previous versions; documentation for deprecated functions is not *
19 * removed, but marked deprecated. See "Generate documentation" section in *
20 * file docs/README.md. *
21\****************************************************************************/
22
23#ifndef INCLUDE_NLOHMANN_JSON_HPP_
24#define INCLUDE_NLOHMANN_JSON_HPP_
25
26#include <algorithm> // all_of, find, for_each
27#include <cstddef> // nullptr_t, ptrdiff_t, size_t
28#include <functional> // hash, less
29#include <initializer_list> // initializer_list
30#ifndef JSON_NO_IO
31 #include <iosfwd> // istream, ostream
32#endif // JSON_NO_IO
33#include <iterator> // random_access_iterator_tag
34#include <memory> // unique_ptr
35#include <string> // string, stoi, to_string
36#include <utility> // declval, forward, move, pair, swap
37#include <vector> // vector
38
39// #include <nlohmann/adl_serializer.hpp>
40// __ _____ _____ _____
41// __| | __| | | | JSON for Modern C++
42// | | |__ | | | | | | version 3.12.0
43// |_____|_____|_____|_|___| https://github.com/nlohmann/json
44//
45// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
46// SPDX-License-Identifier: MIT
47
48
49
50#include <utility>
51
52// #include <nlohmann/detail/abi_macros.hpp>
53// __ _____ _____ _____
54// __| | __| | | | JSON for Modern C++
55// | | |__ | | | | | | version 3.12.0
56// |_____|_____|_____|_|___| https://github.com/nlohmann/json
57//
58// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
59// SPDX-License-Identifier: MIT
60
61
62
63// This file contains all macro definitions affecting or depending on the ABI
64
65#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
66 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
67 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0
68 #warning "Already included a different version of the library!"
69 #endif
70 #endif
71#endif
72
73#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
74#define NLOHMANN_JSON_VERSION_MINOR 12 // NOLINT(modernize-macro-to-enum)
75#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum)
76
77#ifndef JSON_DIAGNOSTICS
78 #define JSON_DIAGNOSTICS 0
79#endif
80
81#ifndef JSON_DIAGNOSTIC_POSITIONS
82 #define JSON_DIAGNOSTIC_POSITIONS 0
83#endif
84
85#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
86 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
87#endif
88
89#if JSON_DIAGNOSTICS
90 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
91#else
92 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
93#endif
94
95#if JSON_DIAGNOSTIC_POSITIONS
96 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp
97#else
98 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS
99#endif
100
101#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
102 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
103#else
104 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
105#endif
106
107#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
108 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
109#endif
110
111// Construct the namespace ABI tags component
112#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c
113#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \
114 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c)
115
116#define NLOHMANN_JSON_ABI_TAGS \
117 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
118 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
119 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \
120 NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS)
121
122// Construct the namespace version component
123#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
124 _v ## major ## _ ## minor ## _ ## patch
125#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
126 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
127
128#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
129#define NLOHMANN_JSON_NAMESPACE_VERSION
130#else
131#define NLOHMANN_JSON_NAMESPACE_VERSION \
132 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
133 NLOHMANN_JSON_VERSION_MINOR, \
134 NLOHMANN_JSON_VERSION_PATCH)
135#endif
136
137// Combine namespace components
138#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
139#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
140 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
141
142#ifndef NLOHMANN_JSON_NAMESPACE
143#define NLOHMANN_JSON_NAMESPACE \
144 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
145 NLOHMANN_JSON_ABI_TAGS, \
146 NLOHMANN_JSON_NAMESPACE_VERSION)
147#endif
148
149#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
150#define NLOHMANN_JSON_NAMESPACE_BEGIN \
151 namespace nlohmann \
152 { \
153 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
154 NLOHMANN_JSON_ABI_TAGS, \
155 NLOHMANN_JSON_NAMESPACE_VERSION) \
156 {
157#endif
158
159#ifndef NLOHMANN_JSON_NAMESPACE_END
160#define NLOHMANN_JSON_NAMESPACE_END \
161 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
162 } // namespace nlohmann
163#endif
164
165// #include <nlohmann/detail/conversions/from_json.hpp>
166// __ _____ _____ _____
167// __| | __| | | | JSON for Modern C++
168// | | |__ | | | | | | version 3.12.0
169// |_____|_____|_____|_|___| https://github.com/nlohmann/json
170//
171// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
172// SPDX-License-Identifier: MIT
173
174
175
176#include <algorithm> // transform
177#include <array> // array
178#include <forward_list> // forward_list
179#include <iterator> // inserter, front_inserter, end
180#include <map> // map
181#include <string> // string
182#include <tuple> // tuple, make_tuple
183#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
184#include <unordered_map> // unordered_map
185#include <utility> // pair, declval
186#include <valarray> // valarray
187
188// #include <nlohmann/detail/exceptions.hpp>
189// __ _____ _____ _____
190// __| | __| | | | JSON for Modern C++
191// | | |__ | | | | | | version 3.12.0
192// |_____|_____|_____|_|___| https://github.com/nlohmann/json
193//
194// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
195// SPDX-License-Identifier: MIT
196
197
198
199#include <cstddef> // nullptr_t
200#include <exception> // exception
201#if JSON_DIAGNOSTICS
202 #include <numeric> // accumulate
203#endif
204#include <stdexcept> // runtime_error
205#include <string> // to_string
206#include <vector> // vector
207
208// #include <nlohmann/detail/value_t.hpp>
209// __ _____ _____ _____
210// __| | __| | | | JSON for Modern C++
211// | | |__ | | | | | | version 3.12.0
212// |_____|_____|_____|_|___| https://github.com/nlohmann/json
213//
214// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
215// SPDX-License-Identifier: MIT
216
217
218
219#include <array> // array
220#include <cstddef> // size_t
221#include <cstdint> // uint8_t
222#include <string> // string
223
224// #include <nlohmann/detail/macro_scope.hpp>
225// __ _____ _____ _____
226// __| | __| | | | JSON for Modern C++
227// | | |__ | | | | | | version 3.12.0
228// |_____|_____|_____|_|___| https://github.com/nlohmann/json
229//
230// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
231// SPDX-License-Identifier: MIT
232
233
234
235#include <utility> // declval, pair
236// #include <nlohmann/detail/meta/detected.hpp>
237// __ _____ _____ _____
238// __| | __| | | | JSON for Modern C++
239// | | |__ | | | | | | version 3.12.0
240// |_____|_____|_____|_|___| https://github.com/nlohmann/json
241//
242// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
243// SPDX-License-Identifier: MIT
244
245
246
247#include <type_traits>
248
249// #include <nlohmann/detail/meta/void_t.hpp>
250// __ _____ _____ _____
251// __| | __| | | | JSON for Modern C++
252// | | |__ | | | | | | version 3.12.0
253// |_____|_____|_____|_|___| https://github.com/nlohmann/json
254//
255// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
256// SPDX-License-Identifier: MIT
257
258
259
260// #include <nlohmann/detail/abi_macros.hpp>
261
262
263NLOHMANN_JSON_NAMESPACE_BEGIN
264namespace detail
265{
266
267template<typename ...Ts> struct make_void
268{
269 using type = void;
270};
271template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
272
273} // namespace detail
274NLOHMANN_JSON_NAMESPACE_END
275
276
277NLOHMANN_JSON_NAMESPACE_BEGIN
278namespace detail
279{
280
281// https://en.cppreference.com/w/cpp/experimental/is_detected
283{
284 nonesuch() = delete;
285 ~nonesuch() = delete;
286 nonesuch(nonesuch const&) = delete;
287 nonesuch(nonesuch const&&) = delete;
288 void operator=(nonesuch const&) = delete;
289 void operator=(nonesuch&&) = delete;
290};
291
292template<class Default,
293 class AlwaysVoid,
294 template<class...> class Op,
295 class... Args>
297{
298 using value_t = std::false_type;
299 using type = Default;
300};
301
302template<class Default, template<class...> class Op, class... Args>
303struct detector<Default, void_t<Op<Args...>>, Op, Args...>
304{
305 using value_t = std::true_type;
306 using type = Op<Args...>;
307};
308
309template<template<class...> class Op, class... Args>
310using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
311
312template<template<class...> class Op, class... Args>
313struct is_detected_lazy : is_detected<Op, Args...> { };
314
315template<template<class...> class Op, class... Args>
316using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
317
318template<class Default, template<class...> class Op, class... Args>
319using detected_or = detector<Default, void, Op, Args...>;
320
321template<class Default, template<class...> class Op, class... Args>
322using detected_or_t = typename detected_or<Default, Op, Args...>::type;
323
324template<class Expected, template<class...> class Op, class... Args>
325using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
326
327template<class To, template<class...> class Op, class... Args>
328using is_detected_convertible =
329 std::is_convertible<detected_t<Op, Args...>, To>;
330
331} // namespace detail
332NLOHMANN_JSON_NAMESPACE_END
333
334// #include <nlohmann/thirdparty/hedley/hedley.hpp>
335
336
337// __ _____ _____ _____
338// __| | __| | | | JSON for Modern C++
339// | | |__ | | | | | | version 3.12.0
340// |_____|_____|_____|_|___| https://github.com/nlohmann/json
341//
342// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
343// SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson <evan@nemerson.com>
344// SPDX-License-Identifier: MIT
345
346/* Hedley - https://nemequ.github.io/hedley
347 * Created by Evan Nemerson <evan@nemerson.com>
348 */
349
350#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
351#if defined(JSON_HEDLEY_VERSION)
352 #undef JSON_HEDLEY_VERSION
353#endif
354#define JSON_HEDLEY_VERSION 15
355
356#if defined(JSON_HEDLEY_STRINGIFY_EX)
357 #undef JSON_HEDLEY_STRINGIFY_EX
358#endif
359#define JSON_HEDLEY_STRINGIFY_EX(x) #x
360
361#if defined(JSON_HEDLEY_STRINGIFY)
362 #undef JSON_HEDLEY_STRINGIFY
363#endif
364#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
365
366#if defined(JSON_HEDLEY_CONCAT_EX)
367 #undef JSON_HEDLEY_CONCAT_EX
368#endif
369#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
370
371#if defined(JSON_HEDLEY_CONCAT)
372 #undef JSON_HEDLEY_CONCAT
373#endif
374#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
375
376#if defined(JSON_HEDLEY_CONCAT3_EX)
377 #undef JSON_HEDLEY_CONCAT3_EX
378#endif
379#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
380
381#if defined(JSON_HEDLEY_CONCAT3)
382 #undef JSON_HEDLEY_CONCAT3
383#endif
384#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
385
386#if defined(JSON_HEDLEY_VERSION_ENCODE)
387 #undef JSON_HEDLEY_VERSION_ENCODE
388#endif
389#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
390
391#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
392 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
393#endif
394#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
395
396#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
397 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
398#endif
399#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
400
401#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
402 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
403#endif
404#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
405
406#if defined(JSON_HEDLEY_GNUC_VERSION)
407 #undef JSON_HEDLEY_GNUC_VERSION
408#endif
409#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
410 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
411#elif defined(__GNUC__)
412 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
413#endif
414
415#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
416 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
417#endif
418#if defined(JSON_HEDLEY_GNUC_VERSION)
419 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
420#else
421 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
422#endif
423
424#if defined(JSON_HEDLEY_MSVC_VERSION)
425 #undef JSON_HEDLEY_MSVC_VERSION
426#endif
427#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
428 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
429#elif defined(_MSC_FULL_VER) && !defined(__ICL)
430 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
431#elif defined(_MSC_VER) && !defined(__ICL)
432 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
433#endif
434
435#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
436 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
437#endif
438#if !defined(JSON_HEDLEY_MSVC_VERSION)
439 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
440#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
441 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
442#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
443 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
444#else
445 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
446#endif
447
448#if defined(JSON_HEDLEY_INTEL_VERSION)
449 #undef JSON_HEDLEY_INTEL_VERSION
450#endif
451#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
452 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
453#elif defined(__INTEL_COMPILER) && !defined(__ICL)
454 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
455#endif
456
457#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
458 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
459#endif
460#if defined(JSON_HEDLEY_INTEL_VERSION)
461 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
462#else
463 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
464#endif
465
466#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
467 #undef JSON_HEDLEY_INTEL_CL_VERSION
468#endif
469#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
470 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
471#endif
472
473#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
474 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
475#endif
476#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
477 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
478#else
479 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
480#endif
481
482#if defined(JSON_HEDLEY_PGI_VERSION)
483 #undef JSON_HEDLEY_PGI_VERSION
484#endif
485#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
486 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
487#endif
488
489#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
490 #undef JSON_HEDLEY_PGI_VERSION_CHECK
491#endif
492#if defined(JSON_HEDLEY_PGI_VERSION)
493 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
494#else
495 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
496#endif
497
498#if defined(JSON_HEDLEY_SUNPRO_VERSION)
499 #undef JSON_HEDLEY_SUNPRO_VERSION
500#endif
501#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
502 #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)
503#elif defined(__SUNPRO_C)
504 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
505#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
506 #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)
507#elif defined(__SUNPRO_CC)
508 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
509#endif
510
511#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
512 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
513#endif
514#if defined(JSON_HEDLEY_SUNPRO_VERSION)
515 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
516#else
517 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
518#endif
519
520#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
521 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
522#endif
523#if defined(__EMSCRIPTEN__)
524 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
525#endif
526
527#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
528 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
529#endif
530#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
531 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
532#else
533 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
534#endif
535
536#if defined(JSON_HEDLEY_ARM_VERSION)
537 #undef JSON_HEDLEY_ARM_VERSION
538#endif
539#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
540 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
541#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
542 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
543#endif
544
545#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
546 #undef JSON_HEDLEY_ARM_VERSION_CHECK
547#endif
548#if defined(JSON_HEDLEY_ARM_VERSION)
549 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
550#else
551 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
552#endif
553
554#if defined(JSON_HEDLEY_IBM_VERSION)
555 #undef JSON_HEDLEY_IBM_VERSION
556#endif
557#if defined(__ibmxl__)
558 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
559#elif defined(__xlC__) && defined(__xlC_ver__)
560 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
561#elif defined(__xlC__)
562 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
563#endif
564
565#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
566 #undef JSON_HEDLEY_IBM_VERSION_CHECK
567#endif
568#if defined(JSON_HEDLEY_IBM_VERSION)
569 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
570#else
571 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
572#endif
573
574#if defined(JSON_HEDLEY_TI_VERSION)
575 #undef JSON_HEDLEY_TI_VERSION
576#endif
577#if \
578 defined(__TI_COMPILER_VERSION__) && \
579 ( \
580 defined(__TMS470__) || defined(__TI_ARM__) || \
581 defined(__MSP430__) || \
582 defined(__TMS320C2000__) \
583 )
584#if (__TI_COMPILER_VERSION__ >= 16000000)
585 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
586#endif
587#endif
588
589#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
590 #undef JSON_HEDLEY_TI_VERSION_CHECK
591#endif
592#if defined(JSON_HEDLEY_TI_VERSION)
593 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
594#else
595 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
596#endif
597
598#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
599 #undef JSON_HEDLEY_TI_CL2000_VERSION
600#endif
601#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
602 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
603#endif
604
605#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
606 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
607#endif
608#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
609 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
610#else
611 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
612#endif
613
614#if defined(JSON_HEDLEY_TI_CL430_VERSION)
615 #undef JSON_HEDLEY_TI_CL430_VERSION
616#endif
617#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
618 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
619#endif
620
621#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
622 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
623#endif
624#if defined(JSON_HEDLEY_TI_CL430_VERSION)
625 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
626#else
627 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
628#endif
629
630#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
631 #undef JSON_HEDLEY_TI_ARMCL_VERSION
632#endif
633#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
634 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
635#endif
636
637#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
638 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
639#endif
640#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
641 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
642#else
643 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
644#endif
645
646#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
647 #undef JSON_HEDLEY_TI_CL6X_VERSION
648#endif
649#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
650 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
651#endif
652
653#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
654 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
655#endif
656#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
657 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
658#else
659 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
660#endif
661
662#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
663 #undef JSON_HEDLEY_TI_CL7X_VERSION
664#endif
665#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
666 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
667#endif
668
669#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
670 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
671#endif
672#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
673 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
674#else
675 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
676#endif
677
678#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
679 #undef JSON_HEDLEY_TI_CLPRU_VERSION
680#endif
681#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
682 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
683#endif
684
685#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
686 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
687#endif
688#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
689 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
690#else
691 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
692#endif
693
694#if defined(JSON_HEDLEY_CRAY_VERSION)
695 #undef JSON_HEDLEY_CRAY_VERSION
696#endif
697#if defined(_CRAYC)
698 #if defined(_RELEASE_PATCHLEVEL)
699 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
700 #else
701 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
702 #endif
703#endif
704
705#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
706 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
707#endif
708#if defined(JSON_HEDLEY_CRAY_VERSION)
709 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
710#else
711 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
712#endif
713
714#if defined(JSON_HEDLEY_IAR_VERSION)
715 #undef JSON_HEDLEY_IAR_VERSION
716#endif
717#if defined(__IAR_SYSTEMS_ICC__)
718 #if __VER__ > 1000
719 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
720 #else
721 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
722 #endif
723#endif
724
725#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
726 #undef JSON_HEDLEY_IAR_VERSION_CHECK
727#endif
728#if defined(JSON_HEDLEY_IAR_VERSION)
729 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
730#else
731 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
732#endif
733
734#if defined(JSON_HEDLEY_TINYC_VERSION)
735 #undef JSON_HEDLEY_TINYC_VERSION
736#endif
737#if defined(__TINYC__)
738 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
739#endif
740
741#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
742 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
743#endif
744#if defined(JSON_HEDLEY_TINYC_VERSION)
745 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
746#else
747 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
748#endif
749
750#if defined(JSON_HEDLEY_DMC_VERSION)
751 #undef JSON_HEDLEY_DMC_VERSION
752#endif
753#if defined(__DMC__)
754 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
755#endif
756
757#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
758 #undef JSON_HEDLEY_DMC_VERSION_CHECK
759#endif
760#if defined(JSON_HEDLEY_DMC_VERSION)
761 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
762#else
763 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
764#endif
765
766#if defined(JSON_HEDLEY_COMPCERT_VERSION)
767 #undef JSON_HEDLEY_COMPCERT_VERSION
768#endif
769#if defined(__COMPCERT_VERSION__)
770 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
771#endif
772
773#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
774 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
775#endif
776#if defined(JSON_HEDLEY_COMPCERT_VERSION)
777 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
778#else
779 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
780#endif
781
782#if defined(JSON_HEDLEY_PELLES_VERSION)
783 #undef JSON_HEDLEY_PELLES_VERSION
784#endif
785#if defined(__POCC__)
786 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
787#endif
788
789#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
790 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
791#endif
792#if defined(JSON_HEDLEY_PELLES_VERSION)
793 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
794#else
795 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
796#endif
797
798#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
799 #undef JSON_HEDLEY_MCST_LCC_VERSION
800#endif
801#if defined(__LCC__) && defined(__LCC_MINOR__)
802 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
803#endif
804
805#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
806 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
807#endif
808#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
809 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
810#else
811 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
812#endif
813
814#if defined(JSON_HEDLEY_GCC_VERSION)
815 #undef JSON_HEDLEY_GCC_VERSION
816#endif
817#if \
818 defined(JSON_HEDLEY_GNUC_VERSION) && \
819 !defined(__clang__) && \
820 !defined(JSON_HEDLEY_INTEL_VERSION) && \
821 !defined(JSON_HEDLEY_PGI_VERSION) && \
822 !defined(JSON_HEDLEY_ARM_VERSION) && \
823 !defined(JSON_HEDLEY_CRAY_VERSION) && \
824 !defined(JSON_HEDLEY_TI_VERSION) && \
825 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
826 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
827 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
828 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
829 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
830 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
831 !defined(__COMPCERT__) && \
832 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
833 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
834#endif
835
836#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
837 #undef JSON_HEDLEY_GCC_VERSION_CHECK
838#endif
839#if defined(JSON_HEDLEY_GCC_VERSION)
840 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
841#else
842 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
843#endif
844
845#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
846 #undef JSON_HEDLEY_HAS_ATTRIBUTE
847#endif
848#if \
849 defined(__has_attribute) && \
850 ( \
851 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
852 )
853# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
854#else
855# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
856#endif
857
858#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
859 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
860#endif
861#if defined(__has_attribute)
862 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
863#else
864 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
865#endif
866
867#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
868 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
869#endif
870#if defined(__has_attribute)
871 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
872#else
873 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
874#endif
875
876#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
877 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
878#endif
879#if \
880 defined(__has_cpp_attribute) && \
881 defined(__cplusplus) && \
882 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
883 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
884#else
885 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
886#endif
887
888#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
889 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
890#endif
891#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
892 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
893#elif \
894 !defined(JSON_HEDLEY_PGI_VERSION) && \
895 !defined(JSON_HEDLEY_IAR_VERSION) && \
896 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
897 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
898 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
899#else
900 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
901#endif
902
903#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
904 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
905#endif
906#if defined(__has_cpp_attribute) && defined(__cplusplus)
907 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
908#else
909 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
910#endif
911
912#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
913 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
914#endif
915#if defined(__has_cpp_attribute) && defined(__cplusplus)
916 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
917#else
918 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
919#endif
920
921#if defined(JSON_HEDLEY_HAS_BUILTIN)
922 #undef JSON_HEDLEY_HAS_BUILTIN
923#endif
924#if defined(__has_builtin)
925 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
926#else
927 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
928#endif
929
930#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
931 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
932#endif
933#if defined(__has_builtin)
934 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
935#else
936 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
937#endif
938
939#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
940 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
941#endif
942#if defined(__has_builtin)
943 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
944#else
945 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
946#endif
947
948#if defined(JSON_HEDLEY_HAS_FEATURE)
949 #undef JSON_HEDLEY_HAS_FEATURE
950#endif
951#if defined(__has_feature)
952 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
953#else
954 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
955#endif
956
957#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
958 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
959#endif
960#if defined(__has_feature)
961 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
962#else
963 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
964#endif
965
966#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
967 #undef JSON_HEDLEY_GCC_HAS_FEATURE
968#endif
969#if defined(__has_feature)
970 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
971#else
972 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
973#endif
974
975#if defined(JSON_HEDLEY_HAS_EXTENSION)
976 #undef JSON_HEDLEY_HAS_EXTENSION
977#endif
978#if defined(__has_extension)
979 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
980#else
981 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
982#endif
983
984#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
985 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
986#endif
987#if defined(__has_extension)
988 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
989#else
990 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
991#endif
992
993#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
994 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
995#endif
996#if defined(__has_extension)
997 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
998#else
999 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1000#endif
1001
1002#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
1003 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
1004#endif
1005#if defined(__has_declspec_attribute)
1006 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
1007#else
1008 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
1009#endif
1010
1011#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1012 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1013#endif
1014#if defined(__has_declspec_attribute)
1015 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1016#else
1017 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1018#endif
1019
1020#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1021 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1022#endif
1023#if defined(__has_declspec_attribute)
1024 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1025#else
1026 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1027#endif
1028
1029#if defined(JSON_HEDLEY_HAS_WARNING)
1030 #undef JSON_HEDLEY_HAS_WARNING
1031#endif
1032#if defined(__has_warning)
1033 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1034#else
1035 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1036#endif
1037
1038#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1039 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1040#endif
1041#if defined(__has_warning)
1042 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1043#else
1044 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1045#endif
1046
1047#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1048 #undef JSON_HEDLEY_GCC_HAS_WARNING
1049#endif
1050#if defined(__has_warning)
1051 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1052#else
1053 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1054#endif
1055
1056#if \
1057 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1058 defined(__clang__) || \
1059 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1060 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1061 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1062 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1063 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1064 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1065 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1066 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1067 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1068 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1069 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1070 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1071 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1072 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1073 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1074 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1075 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1076#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1077 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1078#else
1079 #define JSON_HEDLEY_PRAGMA(value)
1080#endif
1081
1082#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1083 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1084#endif
1085#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1086 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1087#endif
1088#if defined(__clang__)
1089 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1090 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1091#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1092 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1093 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1094#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1095 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1096 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1097#elif \
1098 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1099 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1100 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1101 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1102#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1103 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1104 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1105#elif \
1106 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1107 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1108 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1109 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1110 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1111 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1112 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1113 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1114#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1115 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1116 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1117#else
1118 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1119 #define JSON_HEDLEY_DIAGNOSTIC_POP
1120#endif
1121
1122/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1123 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1124#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1125 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1126#endif
1127#if defined(__cplusplus)
1128# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1129# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1130# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1131# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1132 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1133 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1134 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1135 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1136 xpr \
1137 JSON_HEDLEY_DIAGNOSTIC_POP
1138# else
1139# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1140 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1141 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1142 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1143 xpr \
1144 JSON_HEDLEY_DIAGNOSTIC_POP
1145# endif
1146# else
1147# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1148 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1149 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1150 xpr \
1151 JSON_HEDLEY_DIAGNOSTIC_POP
1152# endif
1153# endif
1154#endif
1155#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1156 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1157#endif
1158
1159#if defined(JSON_HEDLEY_CONST_CAST)
1160 #undef JSON_HEDLEY_CONST_CAST
1161#endif
1162#if defined(__cplusplus)
1163# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1164#elif \
1165 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1166 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1167 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1168# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1169 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1170 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1171 ((T) (expr)); \
1172 JSON_HEDLEY_DIAGNOSTIC_POP \
1173 }))
1174#else
1175# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1176#endif
1177
1178#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1179 #undef JSON_HEDLEY_REINTERPRET_CAST
1180#endif
1181#if defined(__cplusplus)
1182 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1183#else
1184 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1185#endif
1186
1187#if defined(JSON_HEDLEY_STATIC_CAST)
1188 #undef JSON_HEDLEY_STATIC_CAST
1189#endif
1190#if defined(__cplusplus)
1191 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1192#else
1193 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1194#endif
1195
1196#if defined(JSON_HEDLEY_CPP_CAST)
1197 #undef JSON_HEDLEY_CPP_CAST
1198#endif
1199#if defined(__cplusplus)
1200# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1201# define JSON_HEDLEY_CPP_CAST(T, expr) \
1202 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1203 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1204 ((T) (expr)) \
1205 JSON_HEDLEY_DIAGNOSTIC_POP
1206# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1207# define JSON_HEDLEY_CPP_CAST(T, expr) \
1208 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1209 _Pragma("diag_suppress=Pe137") \
1210 JSON_HEDLEY_DIAGNOSTIC_POP
1211# else
1212# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1213# endif
1214#else
1215# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1216#endif
1217
1218#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1219 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1220#endif
1221#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1222 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1223#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1224 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1225#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1226 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1227#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1228 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1229#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1230 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1231#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1232 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1233#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1234 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1235#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1236 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1237#elif \
1238 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1239 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1240 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1241 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1242 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1243 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1244 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1245 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1246 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1247 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1248 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1249 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1250#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1251 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1252#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1253 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1254#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1255 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1256#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1257 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1258#else
1259 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1260#endif
1261
1262#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1263 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1264#endif
1265#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1266 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1267#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1268 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1269#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1270 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1271#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1272 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1273#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1274 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1275#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1276 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1277#elif \
1278 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1279 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1280 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1281 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1282 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1283#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1284 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1285#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1286 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1287#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1288 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1289#else
1290 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1291#endif
1292
1293#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1294 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1295#endif
1296#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1297 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1298#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1299 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1300#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1301 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1302#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1303 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1304#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1305 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1306#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1307 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1308#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1309 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1310#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1311 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1312#elif \
1313 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1314 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1315 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1316 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1317#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1318 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1319#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1320 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1321#else
1322 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1323#endif
1324
1325#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1326 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1327#endif
1328#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1329 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1330#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1331 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1332#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1333 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1334#else
1335 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1336#endif
1337
1338#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1339 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1340#endif
1341#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1342 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1343#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1344 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1345#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1346 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1347#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1348 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1349#else
1350 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1351#endif
1352
1353#if defined(JSON_HEDLEY_DEPRECATED)
1354 #undef JSON_HEDLEY_DEPRECATED
1355#endif
1356#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1357 #undef JSON_HEDLEY_DEPRECATED_FOR
1358#endif
1359#if \
1360 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1361 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1362 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1363 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1364#elif \
1365 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1366 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1367 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1368 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1369 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1370 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1371 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1372 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1373 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1374 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1375 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1376 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1377 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1378 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1379#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1380 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1381 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1382#elif \
1383 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1384 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1385 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1386 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1387 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1388 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1389 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1390 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1391 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1392 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1393 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1394 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1395 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1396 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1397 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1398 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1399 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1400 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1401#elif \
1402 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1403 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1404 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1405 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1406 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1407#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1408 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1409 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1410#else
1411 #define JSON_HEDLEY_DEPRECATED(since)
1412 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1413#endif
1414
1415#if defined(JSON_HEDLEY_UNAVAILABLE)
1416 #undef JSON_HEDLEY_UNAVAILABLE
1417#endif
1418#if \
1419 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1420 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1421 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1422 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1423 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1424#else
1425 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1426#endif
1427
1428#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1429 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1430#endif
1431#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1432 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1433#endif
1434#if \
1435 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1436 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1437 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1438 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1439 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1440 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1441 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1442 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1443 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1444 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1445 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1446 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1447 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1448 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1449 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1450 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1451 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1452 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1453 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1454#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1455 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1456 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1457#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1458 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1459 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1460#elif defined(_Check_return_) /* SAL */
1461 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1462 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1463#else
1464 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1465 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1466#endif
1467
1468#if defined(JSON_HEDLEY_SENTINEL)
1469 #undef JSON_HEDLEY_SENTINEL
1470#endif
1471#if \
1472 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1473 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1474 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1475 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1476 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1477 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1478#else
1479 #define JSON_HEDLEY_SENTINEL(position)
1480#endif
1481
1482#if defined(JSON_HEDLEY_NO_RETURN)
1483 #undef JSON_HEDLEY_NO_RETURN
1484#endif
1485#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1486 #define JSON_HEDLEY_NO_RETURN __noreturn
1487#elif \
1488 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1489 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1490 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1491#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1492 #define JSON_HEDLEY_NO_RETURN _Noreturn
1493#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1494 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1495#elif \
1496 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1497 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1498 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1499 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1500 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1501 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1502 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1503 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1504 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1505 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1506 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1507 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1508 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1509 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1510 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1511 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1512 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1513 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1514#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1515 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1516#elif \
1517 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1518 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1519 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1520#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1521 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1522#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1523 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1524#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1525 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1526#else
1527 #define JSON_HEDLEY_NO_RETURN
1528#endif
1529
1530#if defined(JSON_HEDLEY_NO_ESCAPE)
1531 #undef JSON_HEDLEY_NO_ESCAPE
1532#endif
1533#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1534 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1535#else
1536 #define JSON_HEDLEY_NO_ESCAPE
1537#endif
1538
1539#if defined(JSON_HEDLEY_UNREACHABLE)
1540 #undef JSON_HEDLEY_UNREACHABLE
1541#endif
1542#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1543 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1544#endif
1545#if defined(JSON_HEDLEY_ASSUME)
1546 #undef JSON_HEDLEY_ASSUME
1547#endif
1548#if \
1549 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1550 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1551 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1552 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1553#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1554 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1555#elif \
1556 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1557 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1558 #if defined(__cplusplus)
1559 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1560 #else
1561 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1562 #endif
1563#endif
1564#if \
1565 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1566 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1567 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1568 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1569 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1570 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1571 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1572 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1573#elif defined(JSON_HEDLEY_ASSUME)
1574 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1575#endif
1576#if !defined(JSON_HEDLEY_ASSUME)
1577 #if defined(JSON_HEDLEY_UNREACHABLE)
1578 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1579 #else
1580 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1581 #endif
1582#endif
1583#if defined(JSON_HEDLEY_UNREACHABLE)
1584 #if \
1585 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1586 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1587 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1588 #else
1589 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1590 #endif
1591#else
1592 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1593#endif
1594#if !defined(JSON_HEDLEY_UNREACHABLE)
1595 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1596#endif
1597
1598JSON_HEDLEY_DIAGNOSTIC_PUSH
1599#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1600 #pragma clang diagnostic ignored "-Wpedantic"
1601#endif
1602#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1603 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1604#endif
1605#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1606 #if defined(__clang__)
1607 #pragma clang diagnostic ignored "-Wvariadic-macros"
1608 #elif defined(JSON_HEDLEY_GCC_VERSION)
1609 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1610 #endif
1611#endif
1612#if defined(JSON_HEDLEY_NON_NULL)
1613 #undef JSON_HEDLEY_NON_NULL
1614#endif
1615#if \
1616 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1617 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1618 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1619 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1620 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1621#else
1622 #define JSON_HEDLEY_NON_NULL(...)
1623#endif
1624JSON_HEDLEY_DIAGNOSTIC_POP
1625
1626#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1627 #undef JSON_HEDLEY_PRINTF_FORMAT
1628#endif
1629#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1630 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1631#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1632 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1633#elif \
1634 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1635 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1636 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1637 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1638 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1639 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1640 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1641 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1642 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1643 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1644 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1645 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1646 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1647 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1648 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1649 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1650 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1651 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1652#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1653 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1654#else
1655 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1656#endif
1657
1658#if defined(JSON_HEDLEY_CONSTEXPR)
1659 #undef JSON_HEDLEY_CONSTEXPR
1660#endif
1661#if defined(__cplusplus)
1662 #if __cplusplus >= 201103L
1663 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1664 #endif
1665#endif
1666#if !defined(JSON_HEDLEY_CONSTEXPR)
1667 #define JSON_HEDLEY_CONSTEXPR
1668#endif
1669
1670#if defined(JSON_HEDLEY_PREDICT)
1671 #undef JSON_HEDLEY_PREDICT
1672#endif
1673#if defined(JSON_HEDLEY_LIKELY)
1674 #undef JSON_HEDLEY_LIKELY
1675#endif
1676#if defined(JSON_HEDLEY_UNLIKELY)
1677 #undef JSON_HEDLEY_UNLIKELY
1678#endif
1679#if defined(JSON_HEDLEY_UNPREDICTABLE)
1680 #undef JSON_HEDLEY_UNPREDICTABLE
1681#endif
1682#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1683 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1684#endif
1685#if \
1686 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1687 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1688 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1689# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1690# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1691# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1692# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1693# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1694#elif \
1695 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1696 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1697 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1698 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1699 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1700 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1701 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1702 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1703 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1704 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1705 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1706 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1707 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1708 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1709 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1710 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1711# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1712 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1713# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1714 (__extension__ ({ \
1715 double hedley_probability_ = (probability); \
1716 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1717 }))
1718# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1719 (__extension__ ({ \
1720 double hedley_probability_ = (probability); \
1721 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1722 }))
1723# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1724# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1725#else
1726# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1727# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1728# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1729# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1730# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1731#endif
1732#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1733 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1734#endif
1735
1736#if defined(JSON_HEDLEY_MALLOC)
1737 #undef JSON_HEDLEY_MALLOC
1738#endif
1739#if \
1740 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1741 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1742 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1743 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1744 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1745 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1746 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1747 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1748 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1749 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1750 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1751 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1752 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1753 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1754 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1755 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1756 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1757 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1758 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1759#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1760 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1761#elif \
1762 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1763 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1764 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1765#else
1766 #define JSON_HEDLEY_MALLOC
1767#endif
1768
1769#if defined(JSON_HEDLEY_PURE)
1770 #undef JSON_HEDLEY_PURE
1771#endif
1772#if \
1773 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1774 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1775 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1776 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1777 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1778 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1779 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1780 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1781 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1782 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1783 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1784 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1785 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1786 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1787 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1788 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1789 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1790 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1791 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1792# define JSON_HEDLEY_PURE __attribute__((__pure__))
1793#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1794# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1795#elif defined(__cplusplus) && \
1796 ( \
1797 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1798 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1799 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1800 )
1801# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1802#else
1803# define JSON_HEDLEY_PURE
1804#endif
1805
1806#if defined(JSON_HEDLEY_CONST)
1807 #undef JSON_HEDLEY_CONST
1808#endif
1809#if \
1810 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1811 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1812 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1813 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1814 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1815 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1816 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1817 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1818 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1819 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1820 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1821 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1822 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1823 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1824 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1825 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1826 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1827 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1828 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1829 #define JSON_HEDLEY_CONST __attribute__((__const__))
1830#elif \
1831 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1832 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1833#else
1834 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1835#endif
1836
1837#if defined(JSON_HEDLEY_RESTRICT)
1838 #undef JSON_HEDLEY_RESTRICT
1839#endif
1840#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1841 #define JSON_HEDLEY_RESTRICT restrict
1842#elif \
1843 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1844 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1845 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1846 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1847 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1848 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1849 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1850 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1851 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1852 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1853 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1854 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1855 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1856 defined(__clang__) || \
1857 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1858 #define JSON_HEDLEY_RESTRICT __restrict
1859#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1860 #define JSON_HEDLEY_RESTRICT _Restrict
1861#else
1862 #define JSON_HEDLEY_RESTRICT
1863#endif
1864
1865#if defined(JSON_HEDLEY_INLINE)
1866 #undef JSON_HEDLEY_INLINE
1867#endif
1868#if \
1869 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1870 (defined(__cplusplus) && (__cplusplus >= 199711L))
1871 #define JSON_HEDLEY_INLINE inline
1872#elif \
1873 defined(JSON_HEDLEY_GCC_VERSION) || \
1874 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1875 #define JSON_HEDLEY_INLINE __inline__
1876#elif \
1877 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1878 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1879 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1880 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1881 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1882 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1883 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1884 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1885 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1886 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1887 #define JSON_HEDLEY_INLINE __inline
1888#else
1889 #define JSON_HEDLEY_INLINE
1890#endif
1891
1892#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1893 #undef JSON_HEDLEY_ALWAYS_INLINE
1894#endif
1895#if \
1896 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1897 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1898 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1899 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1900 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1901 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1902 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1903 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1904 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1905 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1906 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1907 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1908 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1909 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1910 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1911 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1912 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1913 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1914 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1915# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1916#elif \
1917 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1918 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1919# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1920#elif defined(__cplusplus) && \
1921 ( \
1922 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1923 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1924 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1925 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1926 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1927 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1928 )
1929# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1930#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1931# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1932#else
1933# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1934#endif
1935
1936#if defined(JSON_HEDLEY_NEVER_INLINE)
1937 #undef JSON_HEDLEY_NEVER_INLINE
1938#endif
1939#if \
1940 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1941 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1942 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1943 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1944 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1945 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1946 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1947 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1948 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1949 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1950 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1951 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1952 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1953 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1954 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1955 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1956 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1957 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1958 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1959 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1960#elif \
1961 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1962 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1963 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1964#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1965 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1966#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1967 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1968#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1969 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1970#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1971 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1972#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1973 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1974#else
1975 #define JSON_HEDLEY_NEVER_INLINE
1976#endif
1977
1978#if defined(JSON_HEDLEY_PRIVATE)
1979 #undef JSON_HEDLEY_PRIVATE
1980#endif
1981#if defined(JSON_HEDLEY_PUBLIC)
1982 #undef JSON_HEDLEY_PUBLIC
1983#endif
1984#if defined(JSON_HEDLEY_IMPORT)
1985 #undef JSON_HEDLEY_IMPORT
1986#endif
1987#if defined(_WIN32) || defined(__CYGWIN__)
1988# define JSON_HEDLEY_PRIVATE
1989# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1990# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1991#else
1992# if \
1993 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1994 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1995 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1996 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1997 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1998 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1999 ( \
2000 defined(__TI_EABI__) && \
2001 ( \
2002 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
2003 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
2004 ) \
2005 ) || \
2006 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2007# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
2008# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
2009# else
2010# define JSON_HEDLEY_PRIVATE
2011# define JSON_HEDLEY_PUBLIC
2012# endif
2013# define JSON_HEDLEY_IMPORT extern
2014#endif
2015
2016#if defined(JSON_HEDLEY_NO_THROW)
2017 #undef JSON_HEDLEY_NO_THROW
2018#endif
2019#if \
2020 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2021 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2022 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2023 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2024 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2025#elif \
2026 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2027 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2028 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2029 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2030#else
2031 #define JSON_HEDLEY_NO_THROW
2032#endif
2033
2034#if defined(JSON_HEDLEY_FALL_THROUGH)
2035 #undef JSON_HEDLEY_FALL_THROUGH
2036#endif
2037#if \
2038 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2039 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2040 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2041 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2042#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2043 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2044#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2045 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2046#elif defined(__fallthrough) /* SAL */
2047 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2048#else
2049 #define JSON_HEDLEY_FALL_THROUGH
2050#endif
2051
2052#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2053 #undef JSON_HEDLEY_RETURNS_NON_NULL
2054#endif
2055#if \
2056 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2057 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2058 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2059 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2060#elif defined(_Ret_notnull_) /* SAL */
2061 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2062#else
2063 #define JSON_HEDLEY_RETURNS_NON_NULL
2064#endif
2065
2066#if defined(JSON_HEDLEY_ARRAY_PARAM)
2067 #undef JSON_HEDLEY_ARRAY_PARAM
2068#endif
2069#if \
2070 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2071 !defined(__STDC_NO_VLA__) && \
2072 !defined(__cplusplus) && \
2073 !defined(JSON_HEDLEY_PGI_VERSION) && \
2074 !defined(JSON_HEDLEY_TINYC_VERSION)
2075 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2076#else
2077 #define JSON_HEDLEY_ARRAY_PARAM(name)
2078#endif
2079
2080#if defined(JSON_HEDLEY_IS_CONSTANT)
2081 #undef JSON_HEDLEY_IS_CONSTANT
2082#endif
2083#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2084 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2085#endif
2086/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2087 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2088#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2089 #undef JSON_HEDLEY_IS_CONSTEXPR_
2090#endif
2091#if \
2092 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2093 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2094 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2095 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2096 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2097 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2098 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2099 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2100 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2101 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2102 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2103#endif
2104#if !defined(__cplusplus)
2105# if \
2106 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2107 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2108 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2109 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2110 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2111 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2112 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2113#if defined(__INTPTR_TYPE__)
2114 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2115#else
2116 #include <stdint.h>
2117 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2118#endif
2119# elif \
2120 ( \
2121 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2122 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2123 !defined(JSON_HEDLEY_PGI_VERSION) && \
2124 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2125 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2126 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2127 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2128 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2129 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2130#if defined(__INTPTR_TYPE__)
2131 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2132#else
2133 #include <stdint.h>
2134 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2135#endif
2136# elif \
2137 defined(JSON_HEDLEY_GCC_VERSION) || \
2138 defined(JSON_HEDLEY_INTEL_VERSION) || \
2139 defined(JSON_HEDLEY_TINYC_VERSION) || \
2140 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2141 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2142 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2143 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2144 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2145 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2146 defined(__clang__)
2147# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2148 sizeof(void) != \
2149 sizeof(*( \
2150 1 ? \
2151 ((void*) ((expr) * 0L) ) : \
2152((struct { char v[sizeof(void) * 2]; } *) 1) \
2153 ) \
2154 ) \
2155 )
2156# endif
2157#endif
2158#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2159 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2160 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2161 #endif
2162 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2163#else
2164 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2165 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2166 #endif
2167 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2168#endif
2169
2170#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2171 #undef JSON_HEDLEY_BEGIN_C_DECLS
2172#endif
2173#if defined(JSON_HEDLEY_END_C_DECLS)
2174 #undef JSON_HEDLEY_END_C_DECLS
2175#endif
2176#if defined(JSON_HEDLEY_C_DECL)
2177 #undef JSON_HEDLEY_C_DECL
2178#endif
2179#if defined(__cplusplus)
2180 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2181 #define JSON_HEDLEY_END_C_DECLS }
2182 #define JSON_HEDLEY_C_DECL extern "C"
2183#else
2184 #define JSON_HEDLEY_BEGIN_C_DECLS
2185 #define JSON_HEDLEY_END_C_DECLS
2186 #define JSON_HEDLEY_C_DECL
2187#endif
2188
2189#if defined(JSON_HEDLEY_STATIC_ASSERT)
2190 #undef JSON_HEDLEY_STATIC_ASSERT
2191#endif
2192#if \
2193 !defined(__cplusplus) && ( \
2194 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2195 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2196 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2197 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2198 defined(_Static_assert) \
2199 )
2200# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2201#elif \
2202 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2203 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2204 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2205# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2206#else
2207# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2208#endif
2209
2210#if defined(JSON_HEDLEY_NULL)
2211 #undef JSON_HEDLEY_NULL
2212#endif
2213#if defined(__cplusplus)
2214 #if __cplusplus >= 201103L
2215 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2216 #elif defined(NULL)
2217 #define JSON_HEDLEY_NULL NULL
2218 #else
2219 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2220 #endif
2221#elif defined(NULL)
2222 #define JSON_HEDLEY_NULL NULL
2223#else
2224 #define JSON_HEDLEY_NULL ((void*) 0)
2225#endif
2226
2227#if defined(JSON_HEDLEY_MESSAGE)
2228 #undef JSON_HEDLEY_MESSAGE
2229#endif
2230#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2231# define JSON_HEDLEY_MESSAGE(msg) \
2232 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2233 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2234 JSON_HEDLEY_PRAGMA(message msg) \
2235 JSON_HEDLEY_DIAGNOSTIC_POP
2236#elif \
2237 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2238 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2239# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2240#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2241# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2242#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2243# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2244#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2245# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2246#else
2247# define JSON_HEDLEY_MESSAGE(msg)
2248#endif
2249
2250#if defined(JSON_HEDLEY_WARNING)
2251 #undef JSON_HEDLEY_WARNING
2252#endif
2253#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2254# define JSON_HEDLEY_WARNING(msg) \
2255 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2256 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2257 JSON_HEDLEY_PRAGMA(clang warning msg) \
2258 JSON_HEDLEY_DIAGNOSTIC_POP
2259#elif \
2260 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2261 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2262 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2263# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2264#elif \
2265 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2266 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2267# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2268#else
2269# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2270#endif
2271
2272#if defined(JSON_HEDLEY_REQUIRE)
2273 #undef JSON_HEDLEY_REQUIRE
2274#endif
2275#if defined(JSON_HEDLEY_REQUIRE_MSG)
2276 #undef JSON_HEDLEY_REQUIRE_MSG
2277#endif
2278#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2279# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2280# define JSON_HEDLEY_REQUIRE(expr) \
2281 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2282 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2283 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2284 JSON_HEDLEY_DIAGNOSTIC_POP
2285# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2286 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2287 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2288 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2289 JSON_HEDLEY_DIAGNOSTIC_POP
2290# else
2291# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2292# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2293# endif
2294#else
2295# define JSON_HEDLEY_REQUIRE(expr)
2296# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2297#endif
2298
2299#if defined(JSON_HEDLEY_FLAGS)
2300 #undef JSON_HEDLEY_FLAGS
2301#endif
2302#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2303 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2304#else
2305 #define JSON_HEDLEY_FLAGS
2306#endif
2307
2308#if defined(JSON_HEDLEY_FLAGS_CAST)
2309 #undef JSON_HEDLEY_FLAGS_CAST
2310#endif
2311#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2312# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2313 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2314 _Pragma("warning(disable:188)") \
2315 ((T) (expr)); \
2316 JSON_HEDLEY_DIAGNOSTIC_POP \
2317 }))
2318#else
2319# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2320#endif
2321
2322#if defined(JSON_HEDLEY_EMPTY_BASES)
2323 #undef JSON_HEDLEY_EMPTY_BASES
2324#endif
2325#if \
2326 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2327 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2328 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2329#else
2330 #define JSON_HEDLEY_EMPTY_BASES
2331#endif
2332
2333/* Remaining macros are deprecated. */
2334
2335#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2336 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2337#endif
2338#if defined(__clang__)
2339 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2340#else
2341 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2342#endif
2343
2344#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2345 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2346#endif
2347#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2348
2349#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2350 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2351#endif
2352#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2353
2354#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2355 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2356#endif
2357#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2358
2359#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2360 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2361#endif
2362#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2363
2364#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2365 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2366#endif
2367#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2368
2369#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2370 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2371#endif
2372#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2373
2374#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2375 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2376#endif
2377#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2378
2379#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2380
2381
2382// This file contains all internal macro definitions (except those affecting ABI)
2383// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2384
2385// #include <nlohmann/detail/abi_macros.hpp>
2386
2387
2388// exclude unsupported compilers
2389#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2390 #if defined(__clang__)
2391 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2392 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2393 #endif
2394 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2395 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2396 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2397 #endif
2398 #endif
2399#endif
2400
2401// C++ language standard detection
2402// if the user manually specified the used C++ version, this is skipped
2403#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)
2404 #if (defined(__cplusplus) && __cplusplus > 202302L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202302L)
2405 #define JSON_HAS_CPP_26
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 > 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L)
2411 #define JSON_HAS_CPP_23
2412 #define JSON_HAS_CPP_20
2413 #define JSON_HAS_CPP_17
2414 #define JSON_HAS_CPP_14
2415 #elif (defined(__cplusplus) && __cplusplus > 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L)
2416 #define JSON_HAS_CPP_20
2417 #define JSON_HAS_CPP_17
2418 #define JSON_HAS_CPP_14
2419 #elif (defined(__cplusplus) && __cplusplus > 201402L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2420 #define JSON_HAS_CPP_17
2421 #define JSON_HAS_CPP_14
2422 #elif (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2423 #define JSON_HAS_CPP_14
2424 #endif
2425 // the cpp 11 flag is always specified because it is the minimal required version
2426 #define JSON_HAS_CPP_11
2427#endif
2428
2429#ifdef __has_include
2430 #if __has_include(<version>)
2431 #include <version>
2432 #endif
2433#endif
2434
2435#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2436 #ifdef JSON_HAS_CPP_17
2437 #if defined(__cpp_lib_filesystem)
2438 #define JSON_HAS_FILESYSTEM 1
2439 #elif defined(__cpp_lib_experimental_filesystem)
2440 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2441 #elif !defined(__has_include)
2442 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2443 #elif __has_include(<filesystem>)
2444 #define JSON_HAS_FILESYSTEM 1
2445 #elif __has_include(<experimental/filesystem>)
2446 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2447 #endif
2448
2449 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2450 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2451 #undef JSON_HAS_FILESYSTEM
2452 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2453 #endif
2454
2455 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2456 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2457 #undef JSON_HAS_FILESYSTEM
2458 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2459 #endif
2460
2461 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2462 #if defined(__clang_major__) && __clang_major__ < 7
2463 #undef JSON_HAS_FILESYSTEM
2464 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2465 #endif
2466
2467 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2468 #if defined(_MSC_VER) && _MSC_VER < 1914
2469 #undef JSON_HAS_FILESYSTEM
2470 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2471 #endif
2472
2473 // no filesystem support before iOS 13
2474 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2475 #undef JSON_HAS_FILESYSTEM
2476 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2477 #endif
2478
2479 // no filesystem support before macOS Catalina
2480 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2481 #undef JSON_HAS_FILESYSTEM
2482 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2483 #endif
2484 #endif
2485#endif
2486
2487#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2488 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2489#endif
2490
2491#ifndef JSON_HAS_FILESYSTEM
2492 #define JSON_HAS_FILESYSTEM 0
2493#endif
2494
2495#ifndef JSON_HAS_THREE_WAY_COMPARISON
2496 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2497 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2498 #define JSON_HAS_THREE_WAY_COMPARISON 1
2499 #else
2500 #define JSON_HAS_THREE_WAY_COMPARISON 0
2501 #endif
2502#endif
2503
2504#ifndef JSON_HAS_RANGES
2505 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has a syntax error
2506 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2507 #define JSON_HAS_RANGES 0
2508 #elif defined(__cpp_lib_ranges)
2509 #define JSON_HAS_RANGES 1
2510 #else
2511 #define JSON_HAS_RANGES 0
2512 #endif
2513#endif
2514
2515#ifndef JSON_HAS_STATIC_RTTI
2516 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2517 #define JSON_HAS_STATIC_RTTI 1
2518 #else
2519 #define JSON_HAS_STATIC_RTTI 0
2520 #endif
2521#endif
2522
2523#ifdef JSON_HAS_CPP_17
2524 #define JSON_INLINE_VARIABLE inline
2525#else
2526 #define JSON_INLINE_VARIABLE
2527#endif
2528
2529#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2530 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2531#else
2532 #define JSON_NO_UNIQUE_ADDRESS
2533#endif
2534
2535// disable documentation warnings on clang
2536#if defined(__clang__)
2537 #pragma clang diagnostic push
2538 #pragma clang diagnostic ignored "-Wdocumentation"
2539 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2540#endif
2541
2542// allow disabling exceptions
2543#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2544 #define JSON_THROW(exception) throw exception
2545 #define JSON_TRY try
2546 #define JSON_CATCH(exception) catch(exception)
2547 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2548#else
2549 #include <cstdlib>
2550 #define JSON_THROW(exception) std::abort()
2551 #define JSON_TRY if(true)
2552 #define JSON_CATCH(exception) if(false)
2553 #define JSON_INTERNAL_CATCH(exception) if(false)
2554#endif
2555
2556// override exception macros
2557#if defined(JSON_THROW_USER)
2558 #undef JSON_THROW
2559 #define JSON_THROW JSON_THROW_USER
2560#endif
2561#if defined(JSON_TRY_USER)
2562 #undef JSON_TRY
2563 #define JSON_TRY JSON_TRY_USER
2564#endif
2565#if defined(JSON_CATCH_USER)
2566 #undef JSON_CATCH
2567 #define JSON_CATCH JSON_CATCH_USER
2568 #undef JSON_INTERNAL_CATCH
2569 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2570#endif
2571#if defined(JSON_INTERNAL_CATCH_USER)
2572 #undef JSON_INTERNAL_CATCH
2573 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2574#endif
2575
2576// allow overriding assert
2577#if !defined(JSON_ASSERT)
2578 #include <cassert> // assert
2579 #define JSON_ASSERT(x) assert(x)
2580#endif
2581
2582// allow accessing some private functions (needed by the test suite)
2583#if defined(JSON_TESTS_PRIVATE)
2584 #define JSON_PRIVATE_UNLESS_TESTED public
2585#else
2586 #define JSON_PRIVATE_UNLESS_TESTED private
2587#endif
2588
2594#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2595 template<typename BasicJsonType> \
2596 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2597 { \
2598 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2599 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2600 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2601 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2602 auto it = std::find_if(std::begin(m), std::end(m), \
2603 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2604 { \
2605 return ej_pair.first == e; \
2606 }); \
2607 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2608 } \
2609 template<typename BasicJsonType> \
2610 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2611 { \
2612 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2613 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2614 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2615 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2616 auto it = std::find_if(std::begin(m), std::end(m), \
2617 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2618 { \
2619 return ej_pair.second == j; \
2620 }); \
2621 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2622 }
2623
2624// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2625// may be removed in the future once the class is split.
2626
2627#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2628 template<template<typename, typename, typename...> class ObjectType, \
2629 template<typename, typename...> class ArrayType, \
2630 class StringType, class BooleanType, class NumberIntegerType, \
2631 class NumberUnsignedType, class NumberFloatType, \
2632 template<typename> class AllocatorType, \
2633 template<typename, typename = void> class JSONSerializer, \
2634 class BinaryType, \
2635 class CustomBaseClass>
2636
2637#define NLOHMANN_BASIC_JSON_TPL \
2638 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2639 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2640 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2641
2642// Macros to simplify conversion from/to types
2643
2644#define NLOHMANN_JSON_EXPAND( x ) x
2645#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
2646#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2647 NLOHMANN_JSON_PASTE64, \
2648 NLOHMANN_JSON_PASTE63, \
2649 NLOHMANN_JSON_PASTE62, \
2650 NLOHMANN_JSON_PASTE61, \
2651 NLOHMANN_JSON_PASTE60, \
2652 NLOHMANN_JSON_PASTE59, \
2653 NLOHMANN_JSON_PASTE58, \
2654 NLOHMANN_JSON_PASTE57, \
2655 NLOHMANN_JSON_PASTE56, \
2656 NLOHMANN_JSON_PASTE55, \
2657 NLOHMANN_JSON_PASTE54, \
2658 NLOHMANN_JSON_PASTE53, \
2659 NLOHMANN_JSON_PASTE52, \
2660 NLOHMANN_JSON_PASTE51, \
2661 NLOHMANN_JSON_PASTE50, \
2662 NLOHMANN_JSON_PASTE49, \
2663 NLOHMANN_JSON_PASTE48, \
2664 NLOHMANN_JSON_PASTE47, \
2665 NLOHMANN_JSON_PASTE46, \
2666 NLOHMANN_JSON_PASTE45, \
2667 NLOHMANN_JSON_PASTE44, \
2668 NLOHMANN_JSON_PASTE43, \
2669 NLOHMANN_JSON_PASTE42, \
2670 NLOHMANN_JSON_PASTE41, \
2671 NLOHMANN_JSON_PASTE40, \
2672 NLOHMANN_JSON_PASTE39, \
2673 NLOHMANN_JSON_PASTE38, \
2674 NLOHMANN_JSON_PASTE37, \
2675 NLOHMANN_JSON_PASTE36, \
2676 NLOHMANN_JSON_PASTE35, \
2677 NLOHMANN_JSON_PASTE34, \
2678 NLOHMANN_JSON_PASTE33, \
2679 NLOHMANN_JSON_PASTE32, \
2680 NLOHMANN_JSON_PASTE31, \
2681 NLOHMANN_JSON_PASTE30, \
2682 NLOHMANN_JSON_PASTE29, \
2683 NLOHMANN_JSON_PASTE28, \
2684 NLOHMANN_JSON_PASTE27, \
2685 NLOHMANN_JSON_PASTE26, \
2686 NLOHMANN_JSON_PASTE25, \
2687 NLOHMANN_JSON_PASTE24, \
2688 NLOHMANN_JSON_PASTE23, \
2689 NLOHMANN_JSON_PASTE22, \
2690 NLOHMANN_JSON_PASTE21, \
2691 NLOHMANN_JSON_PASTE20, \
2692 NLOHMANN_JSON_PASTE19, \
2693 NLOHMANN_JSON_PASTE18, \
2694 NLOHMANN_JSON_PASTE17, \
2695 NLOHMANN_JSON_PASTE16, \
2696 NLOHMANN_JSON_PASTE15, \
2697 NLOHMANN_JSON_PASTE14, \
2698 NLOHMANN_JSON_PASTE13, \
2699 NLOHMANN_JSON_PASTE12, \
2700 NLOHMANN_JSON_PASTE11, \
2701 NLOHMANN_JSON_PASTE10, \
2702 NLOHMANN_JSON_PASTE9, \
2703 NLOHMANN_JSON_PASTE8, \
2704 NLOHMANN_JSON_PASTE7, \
2705 NLOHMANN_JSON_PASTE6, \
2706 NLOHMANN_JSON_PASTE5, \
2707 NLOHMANN_JSON_PASTE4, \
2708 NLOHMANN_JSON_PASTE3, \
2709 NLOHMANN_JSON_PASTE2, \
2710 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2711#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2712#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2713#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2714#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2715#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2716#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)
2717#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)
2718#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)
2719#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)
2720#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)
2721#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)
2722#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)
2723#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)
2724#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)
2725#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)
2726#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)
2727#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)
2728#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)
2729#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)
2730#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)
2731#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)
2732#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)
2733#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)
2734#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)
2735#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)
2736#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)
2737#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)
2738#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)
2739#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)
2740#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)
2741#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)
2742#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)
2743#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)
2744#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)
2745#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)
2746#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)
2747#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)
2748#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)
2749#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)
2750#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)
2751#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)
2752#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)
2753#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)
2754#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)
2755#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)
2756#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)
2757#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)
2758#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)
2759#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)
2760#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)
2761#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)
2762#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)
2763#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)
2764#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)
2765#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)
2766#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)
2767#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)
2768#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)
2769#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)
2770#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)
2771#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)
2772#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)
2773#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)
2774
2775#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2776#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2777#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;
2778
2785#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2786 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2787 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2788 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2789 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2790
2797#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2798 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2799 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2800 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2801 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__)) }
2802
2809#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2810 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2811 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2812
2819#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2820 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2821 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2822 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2823 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2824
2831#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2832 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2833 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2834 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2835 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__)) }
2836
2843#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2844 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2845 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2846
2853#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \
2854 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2855 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__)) } \
2856 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2857 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__)) }
2858
2865#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2866 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2867 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__)) } \
2868 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2869 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__)) }
2870
2877#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2878 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2879 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__)) }
2880
2887#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \
2888 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2889 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__)) } \
2890 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2891 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__)) }
2892
2899#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2900 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2901 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__)) } \
2902 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2903 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__)) }
2904
2911#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2912 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2913 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__)) }
2914
2915// inspired from https://stackoverflow.com/a/26745591
2916// allows calling any std function as if (e.g., with begin):
2917// using std::begin; begin(x);
2918//
2919// it allows using the detected idiom to retrieve the return type
2920// of such an expression
2921#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2922 namespace detail { \
2923 using std::std_name; \
2924 \
2925 template<typename... T> \
2926 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2927 } \
2928 \
2929 namespace detail2 { \
2930 struct std_name##_tag \
2931 { \
2932 }; \
2933 \
2934 template<typename... T> \
2935 std_name##_tag std_name(T&&...); \
2936 \
2937 template<typename... T> \
2938 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2939 \
2940 template<typename... T> \
2941 struct would_call_std_##std_name \
2942 { \
2943 static constexpr auto const value = ::nlohmann::detail:: \
2944 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2945 }; \
2946 } /* namespace detail2 */ \
2947 \
2948 template<typename... T> \
2949 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2950 { \
2951 }
2952
2953#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2954 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2955#endif
2956
2957#if JSON_USE_IMPLICIT_CONVERSIONS
2958 #define JSON_EXPLICIT
2959#else
2960 #define JSON_EXPLICIT explicit
2961#endif
2962
2963#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2964 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2965#endif
2966
2967#ifndef JSON_USE_GLOBAL_UDLS
2968 #define JSON_USE_GLOBAL_UDLS 1
2969#endif
2970
2971#if JSON_HAS_THREE_WAY_COMPARISON
2972 #include <compare> // partial_ordering
2973#endif
2974
2975NLOHMANN_JSON_NAMESPACE_BEGIN
2976namespace detail
2977{
2978
2980// JSON type enumeration //
2982
3007enum class value_t : std::uint8_t
3008{
3009 null,
3010 object,
3011 array,
3012 string,
3013 boolean,
3016 number_float,
3017 binary,
3018 discarded
3019};
3020
3034#if JSON_HAS_THREE_WAY_COMPARISON
3035 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
3036#else
3037 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3038#endif
3039{
3040 static constexpr std::array<std::uint8_t, 9> order = {{
3041 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
3042 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
3043 6 /* binary */
3044 }
3045 };
3046
3047 const auto l_index = static_cast<std::size_t>(lhs);
3048 const auto r_index = static_cast<std::size_t>(rhs);
3049#if JSON_HAS_THREE_WAY_COMPARISON
3050 if (l_index < order.size() && r_index < order.size())
3051 {
3052 return order[l_index] <=> order[r_index]; // *NOPAD*
3053 }
3054 return std::partial_ordering::unordered;
3055#else
3056 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
3057#endif
3058}
3059
3060// GCC selects the built-in operator< over an operator rewritten from
3061// a user-defined spaceship operator
3062// Clang, MSVC, and ICC select the rewritten candidate
3063// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
3064#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
3065inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3066{
3067 return std::is_lt(lhs <=> rhs); // *NOPAD*
3068}
3069#endif
3070
3071} // namespace detail
3072NLOHMANN_JSON_NAMESPACE_END
3073
3074// #include <nlohmann/detail/string_escape.hpp>
3075// __ _____ _____ _____
3076// __| | __| | | | JSON for Modern C++
3077// | | |__ | | | | | | version 3.12.0
3078// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3079//
3080// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3081// SPDX-License-Identifier: MIT
3082
3083
3084
3085// #include <nlohmann/detail/abi_macros.hpp>
3086
3087
3088NLOHMANN_JSON_NAMESPACE_BEGIN
3089namespace detail
3090{
3091
3105template<typename StringType>
3106inline void replace_substring(StringType& s, const StringType& f,
3107 const StringType& t)
3108{
3109 JSON_ASSERT(!f.empty());
3110 for (auto pos = s.find(f); // find the first occurrence of f
3111 pos != StringType::npos; // make sure f was found
3112 s.replace(pos, f.size(), t), // replace with t, and
3113 pos = s.find(f, pos + t.size())) // find the next occurrence of f
3114 {}
3115}
3116
3124template<typename StringType>
3125inline StringType escape(StringType s)
3126{
3127 replace_substring(s, StringType{"~"}, StringType{"~0"});
3128 replace_substring(s, StringType{"/"}, StringType{"~1"});
3129 return s;
3130}
3131
3139template<typename StringType>
3140inline void unescape(StringType& s)
3141{
3142 replace_substring(s, StringType{"~1"}, StringType{"/"});
3143 replace_substring(s, StringType{"~0"}, StringType{"~"});
3144}
3145
3146} // namespace detail
3147NLOHMANN_JSON_NAMESPACE_END
3148
3149// #include <nlohmann/detail/input/position_t.hpp>
3150// __ _____ _____ _____
3151// __| | __| | | | JSON for Modern C++
3152// | | |__ | | | | | | version 3.12.0
3153// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3154//
3155// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3156// SPDX-License-Identifier: MIT
3157
3158
3159
3160#include <cstddef> // size_t
3161
3162// #include <nlohmann/detail/abi_macros.hpp>
3163
3164
3165NLOHMANN_JSON_NAMESPACE_BEGIN
3166namespace detail
3167{
3168
3171{
3173 std::size_t chars_read_total = 0;
3177 std::size_t lines_read = 0;
3178
3180 constexpr operator size_t() const
3181 {
3182 return chars_read_total;
3183 }
3184};
3185
3186} // namespace detail
3187NLOHMANN_JSON_NAMESPACE_END
3188
3189// #include <nlohmann/detail/macro_scope.hpp>
3190
3191// #include <nlohmann/detail/meta/cpp_future.hpp>
3192// __ _____ _____ _____
3193// __| | __| | | | JSON for Modern C++
3194// | | |__ | | | | | | version 3.12.0
3195// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3196//
3197// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3198// SPDX-FileCopyrightText: 2018 The Abseil Authors
3199// SPDX-License-Identifier: MIT
3200
3201
3202
3203#include <array> // array
3204#include <cstddef> // size_t
3205#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3206#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3207
3208// #include <nlohmann/detail/macro_scope.hpp>
3209
3210
3211NLOHMANN_JSON_NAMESPACE_BEGIN
3212namespace detail
3213{
3214
3215template<typename T>
3216using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3217
3218#ifdef JSON_HAS_CPP_14
3219
3220// the following utilities are natively available in C++14
3221using std::enable_if_t;
3222using std::index_sequence;
3223using std::make_index_sequence;
3224using std::index_sequence_for;
3225
3226#else
3227
3228// alias templates to reduce boilerplate
3229template<bool B, typename T = void>
3230using enable_if_t = typename std::enable_if<B, T>::type;
3231
3232// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3233// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3234
3236
3237// integer_sequence
3238//
3239// Class template representing a compile-time integer sequence. An instantiation
3240// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3241// type through its template arguments (which is a common need when
3242// working with C++11 variadic templates). `absl::integer_sequence` is designed
3243// to be a drop-in replacement for C++14's `std::integer_sequence`.
3244//
3245// Example:
3246//
3247// template< class T, T... Ints >
3248// void user_function(integer_sequence<T, Ints...>);
3249//
3250// int main()
3251// {
3252// // user_function's `T` will be deduced to `int` and `Ints...`
3253// // will be deduced to `0, 1, 2, 3, 4`.
3254// user_function(make_integer_sequence<int, 5>());
3255// }
3256template <typename T, T... Ints>
3258{
3259 using value_type = T;
3260 static constexpr std::size_t size() noexcept
3261 {
3262 return sizeof...(Ints);
3263 }
3264};
3265
3266// index_sequence
3267//
3268// A helper template for an `integer_sequence` of `size_t`,
3269// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3270// `std::index_sequence`.
3271template <size_t... Ints>
3272using index_sequence = integer_sequence<size_t, Ints...>;
3273
3274namespace utility_internal
3275{
3276
3277template <typename Seq, size_t SeqSize, size_t Rem>
3278struct Extend;
3279
3280// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3281template <typename T, T... Ints, size_t SeqSize>
3282struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3283{
3284 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3285};
3286
3287template <typename T, T... Ints, size_t SeqSize>
3288struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3289{
3290 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3291};
3292
3293// Recursion helper for 'make_integer_sequence<T, N>'.
3294// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3295template <typename T, size_t N>
3296struct Gen
3297{
3298 using type =
3299 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3300};
3301
3302template <typename T>
3303struct Gen<T, 0>
3304{
3305 using type = integer_sequence<T>;
3306};
3307
3308} // namespace utility_internal
3309
3310// Compile-time sequences of integers
3311
3312// make_integer_sequence
3313//
3314// This template alias is equivalent to
3315// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3316// replacement for C++14's `std::make_integer_sequence`.
3317template <typename T, T N>
3318using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3319
3320// make_index_sequence
3321//
3322// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3323// and is designed to be a drop-in replacement for C++14's
3324// `std::make_index_sequence`.
3325template <size_t N>
3326using make_index_sequence = make_integer_sequence<size_t, N>;
3327
3328// index_sequence_for
3329//
3330// Converts a typename pack into an index sequence of the same length, and
3331// is designed to be a drop-in replacement for C++14's
3332// `std::index_sequence_for()`
3333template <typename... Ts>
3334using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3335
3337
3338#endif
3339
3340// dispatch utility (taken from ranges-v3)
3341template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3342template<> struct priority_tag<0> {};
3343
3344// taken from ranges-v3
3345template<typename T>
3347{
3348 static JSON_INLINE_VARIABLE constexpr T value{};
3349};
3350
3351#ifndef JSON_HAS_CPP_17
3352 template<typename T>
3353 constexpr T static_const<T>::value;
3354#endif
3355
3356template<typename T, typename... Args>
3357constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3358{
3359 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3360}
3361
3362} // namespace detail
3363NLOHMANN_JSON_NAMESPACE_END
3364
3365// #include <nlohmann/detail/meta/type_traits.hpp>
3366// __ _____ _____ _____
3367// __| | __| | | | JSON for Modern C++
3368// | | |__ | | | | | | version 3.12.0
3369// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3370//
3371// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3372// SPDX-License-Identifier: MIT
3373
3374
3375
3376#include <limits> // numeric_limits
3377#include <string> // char_traits
3378#include <tuple> // tuple
3379#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3380#include <utility> // declval
3381#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3382 #include <cstddef> // byte
3383#endif
3384// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3385// __ _____ _____ _____
3386// __| | __| | | | JSON for Modern C++
3387// | | |__ | | | | | | version 3.12.0
3388// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3389//
3390// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3391// SPDX-License-Identifier: MIT
3392
3393
3394
3395#include <iterator> // random_access_iterator_tag
3396
3397// #include <nlohmann/detail/abi_macros.hpp>
3398
3399// #include <nlohmann/detail/meta/void_t.hpp>
3400
3401// #include <nlohmann/detail/meta/cpp_future.hpp>
3402
3403
3404NLOHMANN_JSON_NAMESPACE_BEGIN
3405namespace detail
3406{
3407
3408template<typename It, typename = void>
3410
3411template<typename It>
3413 It,
3414 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3415 typename It::reference, typename It::iterator_category >>
3416{
3417 using difference_type = typename It::difference_type;
3418 using value_type = typename It::value_type;
3419 using pointer = typename It::pointer;
3420 using reference = typename It::reference;
3421 using iterator_category = typename It::iterator_category;
3422};
3423
3424// This is required as some compilers implement std::iterator_traits in a way that
3425// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3426template<typename T, typename = void>
3428{
3429};
3430
3431template<typename T>
3432struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3433 : iterator_types<T>
3434{
3435};
3436
3437template<typename T>
3438struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
3439{
3440 using iterator_category = std::random_access_iterator_tag;
3441 using value_type = T;
3442 using difference_type = ptrdiff_t;
3443 using pointer = T*;
3444 using reference = T&;
3445};
3446
3447} // namespace detail
3448NLOHMANN_JSON_NAMESPACE_END
3449
3450// #include <nlohmann/detail/macro_scope.hpp>
3451
3452// #include <nlohmann/detail/meta/call_std/begin.hpp>
3453// __ _____ _____ _____
3454// __| | __| | | | JSON for Modern C++
3455// | | |__ | | | | | | version 3.12.0
3456// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3457//
3458// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3459// SPDX-License-Identifier: MIT
3460
3461
3462
3463// #include <nlohmann/detail/macro_scope.hpp>
3464
3465
3466NLOHMANN_JSON_NAMESPACE_BEGIN
3467
3468NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3469
3470NLOHMANN_JSON_NAMESPACE_END
3471
3472// #include <nlohmann/detail/meta/call_std/end.hpp>
3473// __ _____ _____ _____
3474// __| | __| | | | JSON for Modern C++
3475// | | |__ | | | | | | version 3.12.0
3476// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3477//
3478// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3479// SPDX-License-Identifier: MIT
3480
3481
3482
3483// #include <nlohmann/detail/macro_scope.hpp>
3484
3485
3486NLOHMANN_JSON_NAMESPACE_BEGIN
3487
3488NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3489
3490NLOHMANN_JSON_NAMESPACE_END
3491
3492// #include <nlohmann/detail/meta/cpp_future.hpp>
3493
3494// #include <nlohmann/detail/meta/detected.hpp>
3495
3496// #include <nlohmann/json_fwd.hpp>
3497// __ _____ _____ _____
3498// __| | __| | | | JSON for Modern C++
3499// | | |__ | | | | | | version 3.12.0
3500// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3501//
3502// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3503// SPDX-License-Identifier: MIT
3504
3505#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3506 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3507
3508 #include <cstdint> // int64_t, uint64_t
3509 #include <map> // map
3510 #include <memory> // allocator
3511 #include <string> // string
3512 #include <vector> // vector
3513
3514 // #include <nlohmann/detail/abi_macros.hpp>
3515
3516
3522 NLOHMANN_JSON_NAMESPACE_BEGIN
3523
3531 template<typename T = void, typename SFINAE = void>
3532 struct adl_serializer;
3533
3536 template<template<typename U, typename V, typename... Args> class ObjectType =
3537 std::map,
3538 template<typename U, typename... Args> class ArrayType = std::vector,
3539 class StringType = std::string, class BooleanType = bool,
3540 class NumberIntegerType = std::int64_t,
3541 class NumberUnsignedType = std::uint64_t,
3542 class NumberFloatType = double,
3543 template<typename U> class AllocatorType = std::allocator,
3544 template<typename T, typename SFINAE = void> class JSONSerializer =
3546 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3547 class CustomBaseClass = void>
3548 class basic_json;
3549
3552 template<typename RefStringType>
3553 class json_pointer;
3554
3560
3563 template<class Key, class T, class IgnoredLess, class Allocator>
3564 struct ordered_map;
3565
3569
3570 NLOHMANN_JSON_NAMESPACE_END
3571
3572#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3573
3574
3575NLOHMANN_JSON_NAMESPACE_BEGIN
3584namespace detail
3585{
3586
3588// helpers //
3590
3591// Note to maintainers:
3592//
3593// Every trait in this file expects a non-CV-qualified type.
3594// The only exceptions are in the 'aliases for detected' section
3595// (i.e., those of the form: decltype(T::member_function(std::declval<T>())))
3596//
3597// In this case, T has to be properly CV-qualified to constraint the function arguments
3598// (e.g., to_json(BasicJsonType&, const T&))
3599
3600template<typename> struct is_basic_json : std::false_type {};
3601
3602NLOHMANN_BASIC_JSON_TPL_DECLARATION
3603struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3604
3605// used by exceptions create() member functions
3606// true_type for the pointer to possibly cv-qualified basic_json or std::nullptr_t
3607// false_type otherwise
3608template<typename BasicJsonContext>
3610 std::integral_constant < bool,
3611 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3612 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3613{};
3614
3616// json_ref helpers //
3618
3619template<typename>
3620class json_ref;
3621
3622template<typename>
3623struct is_json_ref : std::false_type {};
3624
3625template<typename T>
3626struct is_json_ref<json_ref<T>> : std::true_type {};
3627
3629// aliases for detected //
3631
3632template<typename T>
3633using mapped_type_t = typename T::mapped_type;
3634
3635template<typename T>
3636using key_type_t = typename T::key_type;
3637
3638template<typename T>
3639using value_type_t = typename T::value_type;
3640
3641template<typename T>
3642using difference_type_t = typename T::difference_type;
3643
3644template<typename T>
3645using pointer_t = typename T::pointer;
3646
3647template<typename T>
3648using reference_t = typename T::reference;
3649
3650template<typename T>
3651using iterator_category_t = typename T::iterator_category;
3652
3653template<typename T, typename... Args>
3654using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3655
3656template<typename T, typename... Args>
3657using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3658
3659template<typename T, typename U>
3660using get_template_function = decltype(std::declval<T>().template get<U>());
3661
3662// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3663template<typename BasicJsonType, typename T, typename = void>
3664struct has_from_json : std::false_type {};
3665
3666// trait checking if j.get<T> is valid
3667// use this trait instead of std::is_constructible or std::is_convertible,
3668// both rely on, or make use of implicit conversions, and thus fail when T
3669// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3670template <typename BasicJsonType, typename T>
3672{
3673 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3674};
3675
3676template<typename BasicJsonType, typename T>
3677struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3678{
3679 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3680
3681 static constexpr bool value =
3682 is_detected_exact<void, from_json_function, serializer,
3683 const BasicJsonType&, T&>::value;
3684};
3685
3686// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3687// this overload is used for non-default-constructible user-defined-types
3688template<typename BasicJsonType, typename T, typename = void>
3689struct has_non_default_from_json : std::false_type {};
3690
3691template<typename BasicJsonType, typename T>
3692struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3693{
3694 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3695
3696 static constexpr bool value =
3697 is_detected_exact<T, from_json_function, serializer,
3698 const BasicJsonType&>::value;
3699};
3700
3701// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3702// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3703template<typename BasicJsonType, typename T, typename = void>
3704struct has_to_json : std::false_type {};
3705
3706template<typename BasicJsonType, typename T>
3707struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3708{
3709 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3710
3711 static constexpr bool value =
3712 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3713 T>::value;
3714};
3715
3716template<typename T>
3717using detect_key_compare = typename T::key_compare;
3718
3719template<typename T>
3720struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3721
3722// obtains the actual object key comparator
3723template<typename BasicJsonType>
3725{
3726 using object_t = typename BasicJsonType::object_t;
3727 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3728 using type = typename std::conditional < has_key_compare<object_t>::value,
3729 typename object_t::key_compare, object_comparator_t>::type;
3730};
3731
3732template<typename BasicJsonType>
3733using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
3734
3736// char_traits //
3738
3739// Primary template of char_traits calls std char_traits
3740template<typename T>
3741struct char_traits : std::char_traits<T>
3742{};
3743
3744// Explicitly define char traits for unsigned char since it is not standard
3745template<>
3746struct char_traits<unsigned char> : std::char_traits<char>
3747{
3748 using char_type = unsigned char;
3749 using int_type = uint64_t;
3750
3751 // Redefine to_int_type function
3752 static int_type to_int_type(char_type c) noexcept
3753 {
3754 return static_cast<int_type>(c);
3755 }
3756
3757 static char_type to_char_type(int_type i) noexcept
3758 {
3759 return static_cast<char_type>(i);
3760 }
3761
3762 static constexpr int_type eof() noexcept
3763 {
3764 return static_cast<int_type>(std::char_traits<char>::eof());
3765 }
3766};
3767
3768// Explicitly define char traits for signed char since it is not standard
3769template<>
3770struct char_traits<signed char> : std::char_traits<char>
3771{
3772 using char_type = signed char;
3773 using int_type = uint64_t;
3774
3775 // Redefine to_int_type function
3776 static int_type to_int_type(char_type c) noexcept
3777 {
3778 return static_cast<int_type>(c);
3779 }
3780
3781 static char_type to_char_type(int_type i) noexcept
3782 {
3783 return static_cast<char_type>(i);
3784 }
3785
3786 static constexpr int_type eof() noexcept
3787 {
3788 return static_cast<int_type>(std::char_traits<char>::eof());
3789 }
3790};
3791
3792#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3793template<>
3794struct char_traits<std::byte> : std::char_traits<char>
3795{
3796 using char_type = std::byte;
3797 using int_type = uint64_t;
3798
3799 static int_type to_int_type(char_type c) noexcept
3800 {
3801 return static_cast<int_type>(std::to_integer<unsigned char>(c));
3802 }
3803
3804 static char_type to_char_type(int_type i) noexcept
3805 {
3806 return std::byte(static_cast<unsigned char>(i));
3807 }
3808
3809 static constexpr int_type eof() noexcept
3810 {
3811 return static_cast<int_type>(std::char_traits<char>::eof());
3812 }
3813};
3814#endif
3815
3817// is_ functions //
3819
3820// https://en.cppreference.com/w/cpp/types/conjunction
3821template<class...> struct conjunction : std::true_type { };
3822template<class B> struct conjunction<B> : B { };
3823template<class B, class... Bn>
3824struct conjunction<B, Bn...>
3825: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3826
3827// https://en.cppreference.com/w/cpp/types/negation
3828template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3829
3830// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3831// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3832// This causes compile errors in e.g., Clang 3.5 or GCC 4.9.
3833template <typename T>
3834struct is_default_constructible : std::is_default_constructible<T> {};
3835
3836template <typename T1, typename T2>
3837struct is_default_constructible<std::pair<T1, T2>>
3838 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3839
3840template <typename T1, typename T2>
3841struct is_default_constructible<const std::pair<T1, T2>>
3842 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3843
3844template <typename... Ts>
3845struct is_default_constructible<std::tuple<Ts...>>
3846 : conjunction<is_default_constructible<Ts>...> {};
3847
3848template <typename... Ts>
3849struct is_default_constructible<const std::tuple<Ts...>>
3850 : conjunction<is_default_constructible<Ts>...> {};
3851
3852template <typename T, typename... Args>
3853struct is_constructible : std::is_constructible<T, Args...> {};
3854
3855template <typename T1, typename T2>
3856struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3857
3858template <typename T1, typename T2>
3859struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3860
3861template <typename... Ts>
3862struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3863
3864template <typename... Ts>
3865struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3866
3867template<typename T, typename = void>
3868struct is_iterator_traits : std::false_type {};
3869
3870template<typename T>
3872{
3873 private:
3874 using traits = iterator_traits<T>;
3875
3876 public:
3877 static constexpr auto value =
3878 is_detected<value_type_t, traits>::value &&
3879 is_detected<difference_type_t, traits>::value &&
3880 is_detected<pointer_t, traits>::value &&
3881 is_detected<iterator_category_t, traits>::value &&
3882 is_detected<reference_t, traits>::value;
3883};
3884
3885template<typename T>
3887{
3888 private:
3889 using t_ref = typename std::add_lvalue_reference<T>::type;
3890
3891 using iterator = detected_t<result_of_begin, t_ref>;
3892 using sentinel = detected_t<result_of_end, t_ref>;
3893
3894 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3895 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3896 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3897 static constexpr auto is_iterator_begin =
3899
3900 public:
3901 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3902};
3903
3904template<typename R>
3905using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3906
3907template<typename T>
3908using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3909
3910// The following implementation of is_complete_type is taken from
3911// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3912// and is written by Xiang Fan who agreed to use it in this library.
3913
3914template<typename T, typename = void>
3915struct is_complete_type : std::false_type {};
3916
3917template<typename T>
3918struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3919
3920template<typename BasicJsonType, typename CompatibleObjectType,
3921 typename = void>
3922struct is_compatible_object_type_impl : std::false_type {};
3923
3924template<typename BasicJsonType, typename CompatibleObjectType>
3926 BasicJsonType, CompatibleObjectType,
3927 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3928 is_detected<key_type_t, CompatibleObjectType>::value >>
3929{
3930 using object_t = typename BasicJsonType::object_t;
3931
3932 // macOS's is_constructible does not play well with nonesuch...
3933 static constexpr bool value =
3934 is_constructible<typename object_t::key_type,
3935 typename CompatibleObjectType::key_type>::value &&
3936 is_constructible<typename object_t::mapped_type,
3937 typename CompatibleObjectType::mapped_type>::value;
3938};
3939
3940template<typename BasicJsonType, typename CompatibleObjectType>
3942 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3943
3944template<typename BasicJsonType, typename ConstructibleObjectType,
3945 typename = void>
3946struct is_constructible_object_type_impl : std::false_type {};
3947
3948template<typename BasicJsonType, typename ConstructibleObjectType>
3950 BasicJsonType, ConstructibleObjectType,
3951 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3952 is_detected<key_type_t, ConstructibleObjectType>::value >>
3953{
3954 using object_t = typename BasicJsonType::object_t;
3955
3956 static constexpr bool value =
3958 (std::is_move_assignable<ConstructibleObjectType>::value ||
3959 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3960 (is_constructible<typename ConstructibleObjectType::key_type,
3961 typename object_t::key_type>::value &&
3962 std::is_same <
3963 typename object_t::mapped_type,
3964 typename ConstructibleObjectType::mapped_type >::value)) ||
3965 (has_from_json<BasicJsonType,
3966 typename ConstructibleObjectType::mapped_type>::value ||
3968 BasicJsonType,
3969 typename ConstructibleObjectType::mapped_type >::value);
3970};
3971
3972template<typename BasicJsonType, typename ConstructibleObjectType>
3974 : is_constructible_object_type_impl<BasicJsonType,
3975 ConstructibleObjectType> {};
3976
3977template<typename BasicJsonType, typename CompatibleStringType>
3983
3984template<typename BasicJsonType, typename ConstructibleStringType>
3986{
3987 // launder type through decltype() to fix compilation failure on ICPC
3988#ifdef __INTEL_COMPILER
3989 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3990#else
3991 using laundered_type = ConstructibleStringType;
3992#endif
3993
3994 static constexpr auto value =
3995 conjunction <
3997 is_detected_exact<typename BasicJsonType::string_t::value_type,
3998 value_type_t, laundered_type >>::value;
3999};
4000
4001template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
4002struct is_compatible_array_type_impl : std::false_type {};
4003
4004template<typename BasicJsonType, typename CompatibleArrayType>
4006 BasicJsonType, CompatibleArrayType,
4007 enable_if_t <
4008 is_detected<iterator_t, CompatibleArrayType>::value&&
4009 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
4010// special case for types like std::filesystem::path whose iterator's value_type are themselves
4011// c.f. https://github.com/nlohmann/json/pull/3073
4012 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
4013{
4014 static constexpr bool value =
4015 is_constructible<BasicJsonType,
4016 range_value_t<CompatibleArrayType>>::value;
4017};
4018
4019template<typename BasicJsonType, typename CompatibleArrayType>
4021 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
4022
4023template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
4024struct is_constructible_array_type_impl : std::false_type {};
4025
4026template<typename BasicJsonType, typename ConstructibleArrayType>
4028 BasicJsonType, ConstructibleArrayType,
4029 enable_if_t<std::is_same<ConstructibleArrayType,
4030 typename BasicJsonType::value_type>::value >>
4031 : std::true_type {};
4032
4033template<typename BasicJsonType, typename ConstructibleArrayType>
4035 BasicJsonType, ConstructibleArrayType,
4036 enable_if_t < !std::is_same<ConstructibleArrayType,
4037 typename BasicJsonType::value_type>::value&&
4038 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4039 is_default_constructible<ConstructibleArrayType>::value&&
4040(std::is_move_assignable<ConstructibleArrayType>::value ||
4041 std::is_copy_assignable<ConstructibleArrayType>::value)&&
4042is_detected<iterator_t, ConstructibleArrayType>::value&&
4043is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
4044is_detected<range_value_t, ConstructibleArrayType>::value&&
4045// special case for types like std::filesystem::path whose iterator's value_type are themselves
4046// c.f. https://github.com/nlohmann/json/pull/3073
4047!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
4049detected_t<range_value_t, ConstructibleArrayType >>::value >>
4050{
4051 using value_type = range_value_t<ConstructibleArrayType>;
4052
4053 static constexpr bool value =
4054 std::is_same<value_type,
4055 typename BasicJsonType::array_t::value_type>::value ||
4056 has_from_json<BasicJsonType,
4057 value_type>::value ||
4059 BasicJsonType,
4060 value_type >::value;
4061};
4062
4063template<typename BasicJsonType, typename ConstructibleArrayType>
4065 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
4066
4067template<typename RealIntegerType, typename CompatibleNumberIntegerType,
4068 typename = void>
4069struct is_compatible_integer_type_impl : std::false_type {};
4070
4071template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4073 RealIntegerType, CompatibleNumberIntegerType,
4074 enable_if_t < std::is_integral<RealIntegerType>::value&&
4075 std::is_integral<CompatibleNumberIntegerType>::value&&
4076 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
4077{
4078 // is there an assert somewhere on overflows?
4079 using RealLimits = std::numeric_limits<RealIntegerType>;
4080 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
4081
4082 static constexpr auto value =
4083 is_constructible<RealIntegerType,
4084 CompatibleNumberIntegerType>::value &&
4085 CompatibleLimits::is_integer &&
4086 RealLimits::is_signed == CompatibleLimits::is_signed;
4087};
4088
4089template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4091 : is_compatible_integer_type_impl<RealIntegerType,
4092 CompatibleNumberIntegerType> {};
4093
4094template<typename BasicJsonType, typename CompatibleType, typename = void>
4095struct is_compatible_type_impl: std::false_type {};
4096
4097template<typename BasicJsonType, typename CompatibleType>
4099 BasicJsonType, CompatibleType,
4100 enable_if_t<is_complete_type<CompatibleType>::value >>
4101{
4102 static constexpr bool value =
4104};
4105
4106template<typename BasicJsonType, typename CompatibleType>
4108 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
4109
4110template<typename T1, typename T2>
4111struct is_constructible_tuple : std::false_type {};
4112
4113template<typename T1, typename... Args>
4114struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
4115
4116template<typename BasicJsonType, typename T>
4117struct is_json_iterator_of : std::false_type {};
4118
4119template<typename BasicJsonType>
4120struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
4121
4122template<typename BasicJsonType>
4123struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
4124{};
4125
4126// checks if a given type T is a template specialization of Primary
4127template<template <typename...> class Primary, typename T>
4128struct is_specialization_of : std::false_type {};
4129
4130template<template <typename...> class Primary, typename... Args>
4131struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
4132
4133template<typename T>
4135
4136// checks if A and B are comparable using Compare functor
4137template<typename Compare, typename A, typename B, typename = void>
4138struct is_comparable : std::false_type {};
4139
4140template<typename Compare, typename A, typename B>
4141struct is_comparable<Compare, A, B, void_t<
4142decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
4143decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
4144>> : std::true_type {};
4145
4146template<typename T>
4147using detect_is_transparent = typename T::is_transparent;
4148
4149// type trait to check if KeyType can be used as an object key (without a BasicJsonType)
4150// see is_usable_as_basic_json_key_type below
4151template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4152 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4153using is_usable_as_key_type = typename std::conditional <
4155 && !(ExcludeObjectKeyType && std::is_same<KeyType,
4156 ObjectKeyType>::value)
4157 && (!RequireTransparentComparator
4158 || is_detected <detect_is_transparent, Comparator>::value)
4159 && !is_json_pointer<KeyType>::value,
4160 std::true_type,
4161 std::false_type >::type;
4162
4163// type trait to check if KeyType can be used as an object key
4164// true if:
4165// - KeyType is comparable with BasicJsonType::object_t::key_type
4166// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4167// - the comparator is transparent or RequireTransparentComparator is false
4168// - KeyType is not a JSON iterator or json_pointer
4169template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4170 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4171using is_usable_as_basic_json_key_type = typename std::conditional <
4172 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4173 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4174 RequireTransparentComparator, ExcludeObjectKeyType>::value
4176 std::true_type,
4177 std::false_type >::type;
4178
4179template<typename ObjectType, typename KeyType>
4180using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4181
4182// type trait to check if object_t has an erase() member functions accepting KeyType
4183template<typename BasicJsonType, typename KeyType>
4184using has_erase_with_key_type = typename std::conditional <
4185 is_detected <
4186 detect_erase_with_key_type,
4187 typename BasicJsonType::object_t, KeyType >::value,
4188 std::true_type,
4189 std::false_type >::type;
4190
4191// a naive helper to check if a type is an ordered_map (exploits the fact that
4192// ordered_map inherits capacity() from std::vector)
4193template <typename T>
4195{
4196 using one = char;
4197
4198 struct two
4199 {
4200 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4201 };
4202
4203 template <typename C> static one test( decltype(&C::capacity) ) ;
4204 template <typename C> static two test(...);
4205
4206 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4207};
4208
4209// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4210template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4211T conditional_static_cast(U value)
4212{
4213 return static_cast<T>(value);
4214}
4215
4216template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4217T conditional_static_cast(U value)
4218{
4219 return value;
4220}
4221
4222template<typename... Types>
4223using all_integral = conjunction<std::is_integral<Types>...>;
4224
4225template<typename... Types>
4226using all_signed = conjunction<std::is_signed<Types>...>;
4227
4228template<typename... Types>
4229using all_unsigned = conjunction<std::is_unsigned<Types>...>;
4230
4231// there's a disjunction trait in another PR; replace when merged
4232template<typename... Types>
4233using same_sign = std::integral_constant < bool,
4234 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4235
4236template<typename OfType, typename T>
4237using never_out_of_range = std::integral_constant < bool,
4238 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4239 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4240
4241template<typename OfType, typename T,
4242 bool OfTypeSigned = std::is_signed<OfType>::value,
4243 bool TSigned = std::is_signed<T>::value>
4245
4246template<typename OfType, typename T>
4247struct value_in_range_of_impl2<OfType, T, false, false>
4248{
4249 static constexpr bool test(T val)
4250 {
4251 using CommonType = typename std::common_type<OfType, T>::type;
4252 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4253 }
4254};
4255
4256template<typename OfType, typename T>
4257struct value_in_range_of_impl2<OfType, T, true, false>
4258{
4259 static constexpr bool test(T val)
4260 {
4261 using CommonType = typename std::common_type<OfType, T>::type;
4262 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4263 }
4264};
4265
4266template<typename OfType, typename T>
4267struct value_in_range_of_impl2<OfType, T, false, true>
4268{
4269 static constexpr bool test(T val)
4270 {
4271 using CommonType = typename std::common_type<OfType, T>::type;
4272 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4273 }
4274};
4275
4276template<typename OfType, typename T>
4277struct value_in_range_of_impl2<OfType, T, true, true>
4278{
4279 static constexpr bool test(T val)
4280 {
4281 using CommonType = typename std::common_type<OfType, T>::type;
4282 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4283 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4284 }
4285};
4286
4287template<typename OfType, typename T,
4288 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4289 typename = detail::enable_if_t<all_integral<OfType, T>::value>>
4291
4292template<typename OfType, typename T>
4293struct value_in_range_of_impl1<OfType, T, false>
4294{
4295 static constexpr bool test(T val)
4296 {
4298 }
4299};
4300
4301template<typename OfType, typename T>
4302struct value_in_range_of_impl1<OfType, T, true>
4303{
4304 static constexpr bool test(T /*val*/)
4305 {
4306 return true;
4307 }
4308};
4309
4310template<typename OfType, typename T>
4311constexpr bool value_in_range_of(T val)
4312{
4314}
4315
4316template<bool Value>
4317using bool_constant = std::integral_constant<bool, Value>;
4318
4320// is_c_string
4322
4323namespace impl
4324{
4325
4326template<typename T>
4327constexpr bool is_c_string()
4328{
4329 using TUnExt = typename std::remove_extent<T>::type;
4330 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4331 using TUnPtr = typename std::remove_pointer<T>::type;
4332 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4333 return
4334 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4335 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4336}
4337
4338} // namespace impl
4339
4340// checks whether T is a [cv] char */[cv] char[] C string
4341template<typename T>
4342struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4343
4344template<typename T>
4345using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
4346
4348// is_transparent
4350
4351namespace impl
4352{
4353
4354template<typename T>
4355constexpr bool is_transparent()
4356{
4357 return is_detected<detect_is_transparent, T>::value;
4358}
4359
4360} // namespace impl
4361
4362// checks whether T has a member named is_transparent
4363template<typename T>
4364struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4365
4367
4368} // namespace detail
4369NLOHMANN_JSON_NAMESPACE_END
4370
4371// #include <nlohmann/detail/string_concat.hpp>
4372// __ _____ _____ _____
4373// __| | __| | | | JSON for Modern C++
4374// | | |__ | | | | | | version 3.12.0
4375// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4376//
4377// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4378// SPDX-License-Identifier: MIT
4379
4380
4381
4382#include <cstring> // strlen
4383#include <string> // string
4384#include <utility> // forward
4385
4386// #include <nlohmann/detail/meta/cpp_future.hpp>
4387
4388// #include <nlohmann/detail/meta/detected.hpp>
4389
4390
4391NLOHMANN_JSON_NAMESPACE_BEGIN
4392namespace detail
4393{
4394
4395inline std::size_t concat_length()
4396{
4397 return 0;
4398}
4399
4400template<typename... Args>
4401inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4402
4403template<typename StringType, typename... Args>
4404inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4405
4406template<typename... Args>
4407inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4408{
4409 return 1 + concat_length(rest...);
4410}
4411
4412template<typename... Args>
4413inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4414{
4415 // cppcheck-suppress ignoredReturnValue
4416 return ::strlen(cstr) + concat_length(rest...);
4417}
4418
4419template<typename StringType, typename... Args>
4420inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4421{
4422 return str.size() + concat_length(rest...);
4423}
4424
4425template<typename OutStringType>
4426inline void concat_into(OutStringType& /*out*/)
4427{}
4428
4429template<typename StringType, typename Arg>
4430using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4431
4432template<typename StringType, typename Arg>
4433using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
4434
4435template<typename StringType, typename Arg>
4436using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4437
4438template<typename StringType, typename Arg>
4439using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
4440
4441template<typename StringType, typename Arg>
4442using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4443
4444template<typename StringType, typename Arg>
4445using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
4446
4447template<typename StringType, typename Arg>
4448using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4449
4450template<typename StringType, typename Arg>
4451using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
4452
4453template < typename OutStringType, typename Arg, typename... Args,
4454 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4455 && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
4456inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4457
4458template < typename OutStringType, typename Arg, typename... Args,
4459 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4460 && !detect_string_can_append_op<OutStringType, Arg>::value
4461 && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
4462inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4463
4464template < typename OutStringType, typename Arg, typename... Args,
4465 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4466 && !detect_string_can_append_op<OutStringType, Arg>::value
4467 && !detect_string_can_append_iter<OutStringType, Arg>::value
4468 && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
4469inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4470
4471template<typename OutStringType, typename Arg, typename... Args,
4472 enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
4473inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4474{
4475 out.append(std::forward<Arg>(arg));
4476 concat_into(out, std::forward<Args>(rest)...);
4477}
4478
4479template < typename OutStringType, typename Arg, typename... Args,
4480 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4481 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4482inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4483{
4484 out += std::forward<Arg>(arg);
4485 concat_into(out, std::forward<Args>(rest)...);
4486}
4487
4488template < typename OutStringType, typename Arg, typename... Args,
4489 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4490 && !detect_string_can_append_op<OutStringType, Arg>::value
4491 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4492inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4493{
4494 out.append(arg.begin(), arg.end());
4495 concat_into(out, std::forward<Args>(rest)...);
4496}
4497
4498template < typename OutStringType, typename Arg, typename... Args,
4499 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4500 && !detect_string_can_append_op<OutStringType, Arg>::value
4501 && !detect_string_can_append_iter<OutStringType, Arg>::value
4502 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4503inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4504{
4505 out.append(arg.data(), arg.size());
4506 concat_into(out, std::forward<Args>(rest)...);
4507}
4508
4509template<typename OutStringType = std::string, typename... Args>
4510inline OutStringType concat(Args && ... args)
4511{
4512 OutStringType str;
4513 str.reserve(concat_length(args...));
4514 concat_into(str, std::forward<Args>(args)...);
4515 return str;
4516}
4517
4518} // namespace detail
4519NLOHMANN_JSON_NAMESPACE_END
4520
4521
4522// With -Wweak-vtables, Clang will complain about the exception classes as they
4523// have no out-of-line virtual method definitions and their vtable will be
4524// emitted in every translation unit. This issue cannot be fixed with a
4525// header-only library as there is no implementation file to move these
4526// functions to. As a result, we suppress this warning here to avoid client
4527// code stumbling over this. See https://github.com/nlohmann/json/issues/4087
4528// for a discussion.
4529#if defined(__clang__)
4530 #pragma clang diagnostic push
4531 #pragma clang diagnostic ignored "-Wweak-vtables"
4532#endif
4533
4534NLOHMANN_JSON_NAMESPACE_BEGIN
4535namespace detail
4536{
4537
4539// exceptions //
4541
4544class exception : public std::exception
4545{
4546 public:
4548 const char* what() const noexcept override
4549 {
4550 return m.what();
4551 }
4552
4554 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4555
4556 protected:
4557 JSON_HEDLEY_NON_NULL(3)
4558 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4559
4560 static std::string name(const std::string& ename, int id_)
4561 {
4562 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4563 }
4564
4565 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4566 {
4567 return "";
4568 }
4569
4570 template<typename BasicJsonType>
4571 static std::string diagnostics(const BasicJsonType* leaf_element)
4572 {
4573#if JSON_DIAGNOSTICS
4574 std::vector<std::string> tokens;
4575 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4576 {
4577 switch (current->m_parent->type())
4578 {
4579 case value_t::array:
4580 {
4581 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4582 {
4583 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4584 {
4585 tokens.emplace_back(std::to_string(i));
4586 break;
4587 }
4588 }
4589 break;
4590 }
4591
4592 case value_t::object:
4593 {
4594 for (const auto& element : *current->m_parent->m_data.m_value.object)
4595 {
4596 if (&element.second == current)
4597 {
4598 tokens.emplace_back(element.first.c_str());
4599 break;
4600 }
4601 }
4602 break;
4603 }
4604
4605 case value_t::null: // LCOV_EXCL_LINE
4606 case value_t::string: // LCOV_EXCL_LINE
4607 case value_t::boolean: // LCOV_EXCL_LINE
4608 case value_t::number_integer: // LCOV_EXCL_LINE
4609 case value_t::number_unsigned: // LCOV_EXCL_LINE
4610 case value_t::number_float: // LCOV_EXCL_LINE
4611 case value_t::binary: // LCOV_EXCL_LINE
4612 case value_t::discarded: // LCOV_EXCL_LINE
4613 default: // LCOV_EXCL_LINE
4614 break; // LCOV_EXCL_LINE
4615 }
4616 }
4617
4618 if (tokens.empty())
4619 {
4620 return "";
4621 }
4622
4623 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4624 [](const std::string & a, const std::string & b)
4625 {
4626 return concat(a, '/', detail::escape(b));
4627 });
4628
4629 return concat('(', str, ") ", get_byte_positions(leaf_element));
4630#else
4631 return get_byte_positions(leaf_element);
4632#endif
4633 }
4634
4635 private:
4637 std::runtime_error m;
4638#if JSON_DIAGNOSTIC_POSITIONS
4639 template<typename BasicJsonType>
4640 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4641 {
4642 if ((leaf_element->start_pos() != std::string::npos) && (leaf_element->end_pos() != std::string::npos))
4643 {
4644 return concat("(bytes ", std::to_string(leaf_element->start_pos()), "-", std::to_string(leaf_element->end_pos()), ") ");
4645 }
4646 return "";
4647 }
4648#else
4649 template<typename BasicJsonType>
4650 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4651 {
4652 static_cast<void>(leaf_element);
4653 return "";
4654 }
4655#endif
4656};
4657
4661{
4662 public:
4672 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4673 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4674 {
4675 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4676 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4677 return {id_, pos.chars_read_total, w.c_str()};
4678 }
4679
4680 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4681 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4682 {
4683 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4684 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4685 ": ", exception::diagnostics(context), what_arg);
4686 return {id_, byte_, w.c_str()};
4687 }
4688
4698 const std::size_t byte;
4699
4700 private:
4701 parse_error(int id_, std::size_t byte_, const char* what_arg)
4702 : exception(id_, what_arg), byte(byte_) {}
4703
4704 static std::string position_string(const position_t& pos)
4705 {
4706 return concat(" at line ", std::to_string(pos.lines_read + 1),
4707 ", column ", std::to_string(pos.chars_read_current_line));
4708 }
4709};
4710
4714{
4715 public:
4716 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4717 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4718 {
4719 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4720 return {id_, w.c_str()};
4721 }
4722
4723 private:
4724 JSON_HEDLEY_NON_NULL(3)
4725 invalid_iterator(int id_, const char* what_arg)
4726 : exception(id_, what_arg) {}
4727};
4728
4731class type_error : public exception
4732{
4733 public:
4734 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4735 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4736 {
4737 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4738 return {id_, w.c_str()};
4739 }
4740
4741 private:
4742 JSON_HEDLEY_NON_NULL(3)
4743 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4744};
4745
4749{
4750 public:
4751 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4752 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4753 {
4754 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4755 return {id_, w.c_str()};
4756 }
4757
4758 private:
4759 JSON_HEDLEY_NON_NULL(3)
4760 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4761};
4762
4766{
4767 public:
4768 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4769 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4770 {
4771 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4772 return {id_, w.c_str()};
4773 }
4774
4775 private:
4776 JSON_HEDLEY_NON_NULL(3)
4777 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4778};
4779
4780} // namespace detail
4781NLOHMANN_JSON_NAMESPACE_END
4782
4783#if defined(__clang__)
4784 #pragma clang diagnostic pop
4785#endif
4786
4787// #include <nlohmann/detail/macro_scope.hpp>
4788
4789// #include <nlohmann/detail/meta/cpp_future.hpp>
4790
4791// #include <nlohmann/detail/meta/identity_tag.hpp>
4792// __ _____ _____ _____
4793// __| | __| | | | JSON for Modern C++
4794// | | |__ | | | | | | version 3.12.0
4795// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4796//
4797// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4798// SPDX-License-Identifier: MIT
4799
4800
4801
4802// #include <nlohmann/detail/abi_macros.hpp>
4803
4804
4805NLOHMANN_JSON_NAMESPACE_BEGIN
4806namespace detail
4807{
4808
4809// dispatching helper struct
4810template <class T> struct identity_tag {};
4811
4812} // namespace detail
4813NLOHMANN_JSON_NAMESPACE_END
4814
4815// #include <nlohmann/detail/meta/std_fs.hpp>
4816// __ _____ _____ _____
4817// __| | __| | | | JSON for Modern C++
4818// | | |__ | | | | | | version 3.12.0
4819// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4820//
4821// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4822// SPDX-License-Identifier: MIT
4823
4824
4825
4826// #include <nlohmann/detail/macro_scope.hpp>
4827
4828
4829#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4830#include <experimental/filesystem>
4831NLOHMANN_JSON_NAMESPACE_BEGIN
4832namespace detail
4833{
4834namespace std_fs = std::experimental::filesystem;
4835} // namespace detail
4836NLOHMANN_JSON_NAMESPACE_END
4837#elif JSON_HAS_FILESYSTEM
4838#include <filesystem> // NOLINT(build/c++17)
4839NLOHMANN_JSON_NAMESPACE_BEGIN
4840namespace detail
4841{
4842namespace std_fs = std::filesystem;
4843} // namespace detail
4844NLOHMANN_JSON_NAMESPACE_END
4845#endif
4846
4847// #include <nlohmann/detail/meta/type_traits.hpp>
4848
4849// #include <nlohmann/detail/string_concat.hpp>
4850
4851// #include <nlohmann/detail/value_t.hpp>
4852
4853
4854// include after macro_scope.hpp
4855#ifdef JSON_HAS_CPP_17
4856 #include <optional> // optional
4857#endif
4858
4859#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4860 #include <string_view> // u8string_view
4861#endif
4862
4863NLOHMANN_JSON_NAMESPACE_BEGIN
4864namespace detail
4865{
4866
4867template<typename BasicJsonType>
4868inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4869{
4870 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4871 {
4872 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4873 }
4874 n = nullptr;
4875}
4876
4877#ifdef JSON_HAS_CPP_17
4878template<typename BasicJsonType, typename T>
4879void from_json(const BasicJsonType& j, std::optional<T>& opt)
4880{
4881 if (j.is_null())
4882 {
4883 opt = std::nullopt;
4884 }
4885 else
4886 {
4887 opt.emplace(j.template get<T>());
4888 }
4889}
4890#endif // JSON_HAS_CPP_17
4891
4892// overloads for basic_json template parameters
4893template < typename BasicJsonType, typename ArithmeticType,
4894 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4895 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4896 int > = 0 >
4897void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4898{
4899 switch (static_cast<value_t>(j))
4900 {
4902 {
4903 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4904 break;
4905 }
4907 {
4908 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4909 break;
4910 }
4912 {
4913 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4914 break;
4915 }
4916
4917 case value_t::null:
4918 case value_t::object:
4919 case value_t::array:
4920 case value_t::string:
4921 case value_t::boolean:
4922 case value_t::binary:
4923 case value_t::discarded:
4924 default:
4925 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4926 }
4927}
4928
4929template<typename BasicJsonType>
4930inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4931{
4932 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4933 {
4934 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4935 }
4936 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4937}
4938
4939template<typename BasicJsonType>
4940inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4941{
4942 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4943 {
4944 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4945 }
4946 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4947}
4948
4949template <
4950 typename BasicJsonType, typename StringType,
4951 enable_if_t <
4952 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4953 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4954 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4955 && !is_json_ref<StringType>::value, int > = 0 >
4956inline void from_json(const BasicJsonType& j, StringType& s)
4957{
4958 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4959 {
4960 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4961 }
4962
4963 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4964}
4965
4966template<typename BasicJsonType>
4967inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4968{
4969 get_arithmetic_value(j, val);
4970}
4971
4972template<typename BasicJsonType>
4973inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4974{
4975 get_arithmetic_value(j, val);
4976}
4977
4978template<typename BasicJsonType>
4979inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4980{
4981 get_arithmetic_value(j, val);
4982}
4983
4984#if !JSON_DISABLE_ENUM_SERIALIZATION
4985template<typename BasicJsonType, typename EnumType,
4986 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4987inline void from_json(const BasicJsonType& j, EnumType& e)
4988{
4989 typename std::underlying_type<EnumType>::type val;
4990 get_arithmetic_value(j, val);
4991 e = static_cast<EnumType>(val);
4992}
4993#endif // JSON_DISABLE_ENUM_SERIALIZATION
4994
4995// forward_list doesn't have an insert method
4996template<typename BasicJsonType, typename T, typename Allocator,
4997 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4998inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4999{
5000 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5001 {
5002 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5003 }
5004 l.clear();
5005 std::transform(j.rbegin(), j.rend(),
5006 std::front_inserter(l), [](const BasicJsonType & i)
5007 {
5008 return i.template get<T>();
5009 });
5010}
5011
5012// valarray doesn't have an insert method
5013template<typename BasicJsonType, typename T,
5014 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
5015inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
5016{
5017 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5018 {
5019 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5020 }
5021 l.resize(j.size());
5022 std::transform(j.begin(), j.end(), std::begin(l),
5023 [](const BasicJsonType & elem)
5024 {
5025 return elem.template get<T>();
5026 });
5027}
5028
5029template<typename BasicJsonType, typename T, std::size_t N>
5030auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5031-> decltype(j.template get<T>(), void())
5032{
5033 for (std::size_t i = 0; i < N; ++i)
5034 {
5035 arr[i] = j.at(i).template get<T>();
5036 }
5037}
5038
5039template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2>
5040auto from_json(const BasicJsonType& j, T (&arr)[N1][N2]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5041-> decltype(j.template get<T>(), void())
5042{
5043 for (std::size_t i1 = 0; i1 < N1; ++i1)
5044 {
5045 for (std::size_t i2 = 0; i2 < N2; ++i2)
5046 {
5047 arr[i1][i2] = j.at(i1).at(i2).template get<T>();
5048 }
5049 }
5050}
5051
5052template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3>
5053auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5054-> decltype(j.template get<T>(), void())
5055{
5056 for (std::size_t i1 = 0; i1 < N1; ++i1)
5057 {
5058 for (std::size_t i2 = 0; i2 < N2; ++i2)
5059 {
5060 for (std::size_t i3 = 0; i3 < N3; ++i3)
5061 {
5062 arr[i1][i2][i3] = j.at(i1).at(i2).at(i3).template get<T>();
5063 }
5064 }
5065 }
5066}
5067
5068template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3, std::size_t N4>
5069auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3][N4]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5070-> decltype(j.template get<T>(), void())
5071{
5072 for (std::size_t i1 = 0; i1 < N1; ++i1)
5073 {
5074 for (std::size_t i2 = 0; i2 < N2; ++i2)
5075 {
5076 for (std::size_t i3 = 0; i3 < N3; ++i3)
5077 {
5078 for (std::size_t i4 = 0; i4 < N4; ++i4)
5079 {
5080 arr[i1][i2][i3][i4] = j.at(i1).at(i2).at(i3).at(i4).template get<T>();
5081 }
5082 }
5083 }
5084 }
5085}
5086
5087template<typename BasicJsonType>
5088inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
5089{
5090 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
5091}
5092
5093template<typename BasicJsonType, typename T, std::size_t N>
5094auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
5095 priority_tag<2> /*unused*/)
5096-> decltype(j.template get<T>(), void())
5097{
5098 for (std::size_t i = 0; i < N; ++i)
5099 {
5100 arr[i] = j.at(i).template get<T>();
5101 }
5102}
5103
5104template<typename BasicJsonType, typename ConstructibleArrayType,
5105 enable_if_t<
5106 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5107 int> = 0>
5108auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
5109-> decltype(
5110 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
5111 j.template get<typename ConstructibleArrayType::value_type>(),
5112 void())
5113{
5114 using std::end;
5115
5116 ConstructibleArrayType ret;
5117 ret.reserve(j.size());
5118 std::transform(j.begin(), j.end(),
5119 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
5120 {
5121 // get<BasicJsonType>() returns *this, this won't call a from_json
5122 // method when value_type is BasicJsonType
5123 return i.template get<typename ConstructibleArrayType::value_type>();
5124 });
5125 arr = std::move(ret);
5126}
5127
5128template<typename BasicJsonType, typename ConstructibleArrayType,
5129 enable_if_t<
5130 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5131 int> = 0>
5132inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
5133 priority_tag<0> /*unused*/)
5134{
5135 using std::end;
5136
5137 ConstructibleArrayType ret;
5138 std::transform(
5139 j.begin(), j.end(), std::inserter(ret, end(ret)),
5140 [](const BasicJsonType & i)
5141 {
5142 // get<BasicJsonType>() returns *this, this won't call a from_json
5143 // method when value_type is BasicJsonType
5144 return i.template get<typename ConstructibleArrayType::value_type>();
5145 });
5146 arr = std::move(ret);
5147}
5148
5149template < typename BasicJsonType, typename ConstructibleArrayType,
5150 enable_if_t <
5151 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
5152 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
5153 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
5154 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
5155 !is_basic_json<ConstructibleArrayType>::value,
5156 int > = 0 >
5157auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
5158-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
5159j.template get<typename ConstructibleArrayType::value_type>(),
5160void())
5161{
5162 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5163 {
5164 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5165 }
5166
5167 from_json_array_impl(j, arr, priority_tag<3> {});
5168}
5169
5170template < typename BasicJsonType, typename T, std::size_t... Idx >
5171std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
5172 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
5173{
5174 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
5175}
5176
5177template < typename BasicJsonType, typename T, std::size_t N >
5178auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
5179-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
5180{
5181 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5182 {
5183 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5184 }
5185
5186 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
5187}
5188
5189template<typename BasicJsonType>
5190inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
5191{
5192 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
5193 {
5194 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
5195 }
5196
5197 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
5198}
5199
5200template<typename BasicJsonType, typename ConstructibleObjectType,
5201 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
5202inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
5203{
5204 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
5205 {
5206 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
5207 }
5208
5209 ConstructibleObjectType ret;
5210 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
5211 using value_type = typename ConstructibleObjectType::value_type;
5212 std::transform(
5213 inner_object->begin(), inner_object->end(),
5214 std::inserter(ret, ret.begin()),
5215 [](typename BasicJsonType::object_t::value_type const & p)
5216 {
5217 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
5218 });
5219 obj = std::move(ret);
5220}
5221
5222// overload for arithmetic types, not chosen for basic_json template arguments
5223// (BooleanType, etc.); note: Is it really necessary to provide explicit
5224// overloads for boolean_t etc. in case of a custom BooleanType which is not
5225// an arithmetic type?
5226template < typename BasicJsonType, typename ArithmeticType,
5227 enable_if_t <
5228 std::is_arithmetic<ArithmeticType>::value&&
5229 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
5230 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
5231 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
5232 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
5233 int > = 0 >
5234inline void from_json(const BasicJsonType& j, ArithmeticType& val)
5235{
5236 switch (static_cast<value_t>(j))
5237 {
5239 {
5240 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
5241 break;
5242 }
5244 {
5245 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5246 break;
5247 }
5249 {
5250 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5251 break;
5252 }
5253 case value_t::boolean:
5254 {
5255 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5256 break;
5257 }
5258
5259 case value_t::null:
5260 case value_t::object:
5261 case value_t::array:
5262 case value_t::string:
5263 case value_t::binary:
5264 case value_t::discarded:
5265 default:
5266 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5267 }
5268}
5269
5270template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5271std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5272{
5273 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5274}
5275
5276template<typename BasicJsonType>
5277std::tuple<> from_json_tuple_impl_base(BasicJsonType& /*unused*/, index_sequence<> /*unused*/)
5278{
5279 return {};
5280}
5281
5282template < typename BasicJsonType, class A1, class A2 >
5283std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5284{
5285 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5286 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5287}
5288
5289template<typename BasicJsonType, typename A1, typename A2>
5290inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5291{
5292 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5293}
5294
5295template<typename BasicJsonType, typename... Args>
5296std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5297{
5298 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5299}
5300
5301template<typename BasicJsonType, typename... Args>
5302inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5303{
5304 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5305}
5306
5307template<typename BasicJsonType, typename TupleRelated>
5308auto from_json(BasicJsonType&& j, TupleRelated&& t)
5309-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5310{
5311 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5312 {
5313 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5314 }
5315
5316 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5317}
5318
5319template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5320 typename = enable_if_t < !std::is_constructible <
5321 typename BasicJsonType::string_t, Key >::value >>
5322inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5323{
5324 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5325 {
5326 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5327 }
5328 m.clear();
5329 for (const auto& p : j)
5330 {
5331 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5332 {
5333 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5334 }
5335 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5336 }
5337}
5338
5339template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5340 typename = enable_if_t < !std::is_constructible <
5341 typename BasicJsonType::string_t, Key >::value >>
5342inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5343{
5344 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5345 {
5346 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5347 }
5348 m.clear();
5349 for (const auto& p : j)
5350 {
5351 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5352 {
5353 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5354 }
5355 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5356 }
5357}
5358
5359#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5360template<typename BasicJsonType>
5361inline void from_json(const BasicJsonType& j, std_fs::path& p)
5362{
5363 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5364 {
5365 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5366 }
5367 const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5368 // Checking for C++20 standard or later can be insufficient in case the
5369 // library support for char8_t is either incomplete or was disabled
5370 // altogether. Use the __cpp_lib_char8_t feature test instead.
5371#if defined(__cpp_lib_char8_t) && (__cpp_lib_char8_t >= 201907L)
5372 p = std_fs::path(std::u8string_view(reinterpret_cast<const char8_t*>(s.data()), s.size()));
5373#else
5374 p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20
5375#endif
5376}
5377#endif
5378
5379struct from_json_fn
5380{
5381 template<typename BasicJsonType, typename T>
5382 auto operator()(const BasicJsonType& j, T&& val) const
5383 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5384 -> decltype(from_json(j, std::forward<T>(val)))
5385 {
5386 return from_json(j, std::forward<T>(val));
5387 }
5388};
5389
5390} // namespace detail
5391
5392#ifndef JSON_HAS_CPP_17
5396namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5397{
5398#endif
5399JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5401#ifndef JSON_HAS_CPP_17
5402} // namespace
5403#endif
5404
5405NLOHMANN_JSON_NAMESPACE_END
5406
5407// #include <nlohmann/detail/conversions/to_json.hpp>
5408// __ _____ _____ _____
5409// __| | __| | | | JSON for Modern C++
5410// | | |__ | | | | | | version 3.12.0
5411// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5412//
5413// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5414// SPDX-License-Identifier: MIT
5415
5416
5417
5418// #include <nlohmann/detail/macro_scope.hpp>
5419// JSON_HAS_CPP_17
5420#ifdef JSON_HAS_CPP_17
5421 #include <optional> // optional
5422#endif
5423
5424#include <algorithm> // copy
5425#include <iterator> // begin, end
5426#include <memory> // allocator_traits
5427#include <string> // basic_string, char_traits
5428#include <tuple> // tuple, get
5429#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5430#include <utility> // move, forward, declval, pair
5431#include <valarray> // valarray
5432#include <vector> // vector
5433
5434// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5435// __ _____ _____ _____
5436// __| | __| | | | JSON for Modern C++
5437// | | |__ | | | | | | version 3.12.0
5438// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5439//
5440// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5441// SPDX-License-Identifier: MIT
5442
5443
5444
5445#include <cstddef> // size_t
5446#include <iterator> // forward_iterator_tag
5447#include <tuple> // tuple_size, get, tuple_element
5448#include <utility> // move
5449
5450#if JSON_HAS_RANGES
5451 #include <ranges> // enable_borrowed_range
5452#endif
5453
5454// #include <nlohmann/detail/abi_macros.hpp>
5455
5456// #include <nlohmann/detail/meta/type_traits.hpp>
5457
5458// #include <nlohmann/detail/string_utils.hpp>
5459// __ _____ _____ _____
5460// __| | __| | | | JSON for Modern C++
5461// | | |__ | | | | | | version 3.12.0
5462// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5463//
5464// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5465// SPDX-License-Identifier: MIT
5466
5467
5468
5469#include <cstddef> // size_t
5470#include <string> // string, to_string
5471
5472// #include <nlohmann/detail/abi_macros.hpp>
5473
5474
5475NLOHMANN_JSON_NAMESPACE_BEGIN
5476namespace detail
5477{
5478
5479template<typename StringType>
5480void int_to_string(StringType& target, std::size_t value)
5481{
5482 // For ADL
5483 using std::to_string;
5484 target = to_string(value);
5485}
5486
5487template<typename StringType>
5488StringType to_string(std::size_t value)
5489{
5490 StringType result;
5491 int_to_string(result, value);
5492 return result;
5493}
5494
5495} // namespace detail
5496NLOHMANN_JSON_NAMESPACE_END
5497
5498// #include <nlohmann/detail/value_t.hpp>
5499
5500
5501NLOHMANN_JSON_NAMESPACE_BEGIN
5502namespace detail
5503{
5504
5505template<typename IteratorType> class iteration_proxy_value
5506{
5507 public:
5508 using difference_type = std::ptrdiff_t;
5510 using pointer = value_type *;
5511 using reference = value_type &;
5512 using iterator_category = std::forward_iterator_tag;
5513 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5514
5515 private:
5517 IteratorType anchor{};
5519 std::size_t array_index = 0;
5521 mutable std::size_t array_index_last = 0;
5523 mutable string_type array_index_str = "0";
5525 string_type empty_str{};
5526
5527 public:
5528 explicit iteration_proxy_value() = default;
5529 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5530 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5531 && std::is_nothrow_default_constructible<string_type>::value)
5532 : anchor(std::move(it))
5533 , array_index(array_index_)
5534 {}
5535
5537 iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
5538 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5540 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5541 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5543 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5544 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5545 ~iteration_proxy_value() = default;
5546
5549 {
5550 return *this;
5551 }
5552
5555 {
5556 ++anchor;
5557 ++array_index;
5558
5559 return *this;
5560 }
5561
5562 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5563 {
5564 auto tmp = iteration_proxy_value(anchor, array_index);
5565 ++anchor;
5566 ++array_index;
5567 return tmp;
5568 }
5569
5572 {
5573 return anchor == o.anchor;
5574 }
5575
5578 {
5579 return anchor != o.anchor;
5580 }
5581
5583 const string_type& key() const
5584 {
5585 JSON_ASSERT(anchor.m_object != nullptr);
5586
5587 switch (anchor.m_object->type())
5588 {
5589 // use integer array index as key
5590 case value_t::array:
5591 {
5592 if (array_index != array_index_last)
5593 {
5594 int_to_string( array_index_str, array_index );
5595 array_index_last = array_index;
5596 }
5597 return array_index_str;
5598 }
5599
5600 // use key from the object
5601 case value_t::object:
5602 return anchor.key();
5603
5604 // use an empty key for all primitive types
5605 case value_t::null:
5606 case value_t::string:
5607 case value_t::boolean:
5611 case value_t::binary:
5612 case value_t::discarded:
5613 default:
5614 return empty_str;
5615 }
5616 }
5617
5619 typename IteratorType::reference value() const
5620 {
5621 return anchor.value();
5622 }
5623};
5624
5626template<typename IteratorType> class iteration_proxy
5627{
5628 private:
5630 typename IteratorType::pointer container = nullptr;
5631
5632 public:
5633 explicit iteration_proxy() = default;
5634
5636 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5637 : container(&cont) {}
5638
5639 iteration_proxy(iteration_proxy const&) = default;
5640 iteration_proxy& operator=(iteration_proxy const&) = default;
5641 iteration_proxy(iteration_proxy&&) noexcept = default;
5642 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5643 ~iteration_proxy() = default;
5644
5646 iteration_proxy_value<IteratorType> begin() const noexcept
5647 {
5648 return iteration_proxy_value<IteratorType>(container->begin());
5649 }
5650
5653 {
5654 return iteration_proxy_value<IteratorType>(container->end());
5655 }
5656};
5657
5658// Structured Bindings Support
5659// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5660// And see https://github.com/nlohmann/json/pull/1391
5661template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5662auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5663{
5664 return i.key();
5665}
5666// Structured Bindings Support
5667// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5668// And see https://github.com/nlohmann/json/pull/1391
5669template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5670auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5671{
5672 return i.value();
5673}
5674
5675} // namespace detail
5676NLOHMANN_JSON_NAMESPACE_END
5677
5678// The Addition to the STD Namespace is required to add
5679// Structured Bindings Support to the iteration_proxy_value class
5680// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5681// And see https://github.com/nlohmann/json/pull/1391
5682namespace std
5683{
5684
5685#if defined(__clang__)
5686 // Fix: https://github.com/nlohmann/json/issues/1401
5687 #pragma clang diagnostic push
5688 #pragma clang diagnostic ignored "-Wmismatched-tags"
5689#endif
5690template<typename IteratorType>
5691class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5692 : public std::integral_constant<std::size_t, 2> {};
5693
5694template<std::size_t N, typename IteratorType>
5695class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5696{
5697 public:
5698 using type = decltype(
5699 get<N>(std::declval <
5700 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5701};
5702#if defined(__clang__)
5703 #pragma clang diagnostic pop
5704#endif
5705
5706} // namespace std
5707
5708#if JSON_HAS_RANGES
5709 template <typename IteratorType>
5710 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5711#endif
5712
5713// #include <nlohmann/detail/meta/cpp_future.hpp>
5714
5715// #include <nlohmann/detail/meta/std_fs.hpp>
5716
5717// #include <nlohmann/detail/meta/type_traits.hpp>
5718
5719// #include <nlohmann/detail/value_t.hpp>
5720
5721
5722NLOHMANN_JSON_NAMESPACE_BEGIN
5723namespace detail
5724{
5725
5727// constructors //
5729
5730/*
5731 * Note all external_constructor<>::construct functions need to call
5732 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5733 * allocated value (e.g., a string). See bug issue
5734 * https://github.com/nlohmann/json/issues/2865 for more information.
5735 */
5736
5737template<value_t> struct external_constructor;
5738
5739template<>
5741{
5742 template<typename BasicJsonType>
5743 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5744 {
5745 j.m_data.m_value.destroy(j.m_data.m_type);
5746 j.m_data.m_type = value_t::boolean;
5747 j.m_data.m_value = b;
5748 j.assert_invariant();
5749 }
5750};
5751
5752template<>
5754{
5755 template<typename BasicJsonType>
5756 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5757 {
5758 j.m_data.m_value.destroy(j.m_data.m_type);
5759 j.m_data.m_type = value_t::string;
5760 j.m_data.m_value = s;
5761 j.assert_invariant();
5762 }
5763
5764 template<typename BasicJsonType>
5765 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5766 {
5767 j.m_data.m_value.destroy(j.m_data.m_type);
5768 j.m_data.m_type = value_t::string;
5769 j.m_data.m_value = std::move(s);
5770 j.assert_invariant();
5771 }
5772
5773 template < typename BasicJsonType, typename CompatibleStringType,
5774 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5775 int > = 0 >
5776 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5777 {
5778 j.m_data.m_value.destroy(j.m_data.m_type);
5779 j.m_data.m_type = value_t::string;
5780 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5781 j.assert_invariant();
5782 }
5783};
5784
5785template<>
5787{
5788 template<typename BasicJsonType>
5789 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5790 {
5791 j.m_data.m_value.destroy(j.m_data.m_type);
5792 j.m_data.m_type = value_t::binary;
5793 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5794 j.assert_invariant();
5795 }
5796
5797 template<typename BasicJsonType>
5798 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5799 {
5800 j.m_data.m_value.destroy(j.m_data.m_type);
5801 j.m_data.m_type = value_t::binary;
5802 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5803 j.assert_invariant();
5804 }
5805};
5806
5807template<>
5809{
5810 template<typename BasicJsonType>
5811 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5812 {
5813 j.m_data.m_value.destroy(j.m_data.m_type);
5814 j.m_data.m_type = value_t::number_float;
5815 j.m_data.m_value = val;
5816 j.assert_invariant();
5817 }
5818};
5819
5820template<>
5822{
5823 template<typename BasicJsonType>
5824 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5825 {
5826 j.m_data.m_value.destroy(j.m_data.m_type);
5827 j.m_data.m_type = value_t::number_unsigned;
5828 j.m_data.m_value = val;
5829 j.assert_invariant();
5830 }
5831};
5832
5833template<>
5835{
5836 template<typename BasicJsonType>
5837 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5838 {
5839 j.m_data.m_value.destroy(j.m_data.m_type);
5840 j.m_data.m_type = value_t::number_integer;
5841 j.m_data.m_value = val;
5842 j.assert_invariant();
5843 }
5844};
5845
5846template<>
5848{
5849 template<typename BasicJsonType>
5850 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5851 {
5852 j.m_data.m_value.destroy(j.m_data.m_type);
5853 j.m_data.m_type = value_t::array;
5854 j.m_data.m_value = arr;
5855 j.set_parents();
5856 j.assert_invariant();
5857 }
5858
5859 template<typename BasicJsonType>
5860 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5861 {
5862 j.m_data.m_value.destroy(j.m_data.m_type);
5863 j.m_data.m_type = value_t::array;
5864 j.m_data.m_value = std::move(arr);
5865 j.set_parents();
5866 j.assert_invariant();
5867 }
5868
5869 template < typename BasicJsonType, typename CompatibleArrayType,
5870 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5871 int > = 0 >
5872 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5873 {
5874 using std::begin;
5875 using std::end;
5876
5877 j.m_data.m_value.destroy(j.m_data.m_type);
5878 j.m_data.m_type = value_t::array;
5879 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5880 j.set_parents();
5881 j.assert_invariant();
5882 }
5883
5884 template<typename BasicJsonType>
5885 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5886 {
5887 j.m_data.m_value.destroy(j.m_data.m_type);
5888 j.m_data.m_type = value_t::array;
5889 j.m_data.m_value = value_t::array;
5890 j.m_data.m_value.array->reserve(arr.size());
5891 for (const bool x : arr)
5892 {
5893 j.m_data.m_value.array->push_back(x);
5894 j.set_parent(j.m_data.m_value.array->back());
5895 }
5896 j.assert_invariant();
5897 }
5898
5899 template<typename BasicJsonType, typename T,
5900 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5901 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5902 {
5903 j.m_data.m_value.destroy(j.m_data.m_type);
5904 j.m_data.m_type = value_t::array;
5905 j.m_data.m_value = value_t::array;
5906 j.m_data.m_value.array->resize(arr.size());
5907 if (arr.size() > 0)
5908 {
5909 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5910 }
5911 j.set_parents();
5912 j.assert_invariant();
5913 }
5914};
5915
5916template<>
5918{
5919 template<typename BasicJsonType>
5920 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5921 {
5922 j.m_data.m_value.destroy(j.m_data.m_type);
5923 j.m_data.m_type = value_t::object;
5924 j.m_data.m_value = obj;
5925 j.set_parents();
5926 j.assert_invariant();
5927 }
5928
5929 template<typename BasicJsonType>
5930 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5931 {
5932 j.m_data.m_value.destroy(j.m_data.m_type);
5933 j.m_data.m_type = value_t::object;
5934 j.m_data.m_value = std::move(obj);
5935 j.set_parents();
5936 j.assert_invariant();
5937 }
5938
5939 template < typename BasicJsonType, typename CompatibleObjectType,
5940 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5941 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5942 {
5943 using std::begin;
5944 using std::end;
5945
5946 j.m_data.m_value.destroy(j.m_data.m_type);
5947 j.m_data.m_type = value_t::object;
5948 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5949 j.set_parents();
5950 j.assert_invariant();
5951 }
5952};
5953
5955// to_json //
5957
5958#ifdef JSON_HAS_CPP_17
5959template<typename BasicJsonType, typename T,
5960 enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
5961void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept
5962{
5963 if (opt.has_value())
5964 {
5965 j = *opt;
5966 }
5967 else
5968 {
5969 j = nullptr;
5970 }
5971}
5972#endif
5973
5974template<typename BasicJsonType, typename T,
5975 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5976inline void to_json(BasicJsonType& j, T b) noexcept
5977{
5978 external_constructor<value_t::boolean>::construct(j, b);
5979}
5980
5981template < typename BasicJsonType, typename BoolRef,
5982 enable_if_t <
5983 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5984 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5985 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5986 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5987 typename BasicJsonType::boolean_t >::value))
5988 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5989inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5990{
5991 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5992}
5993
5994template<typename BasicJsonType, typename CompatibleString,
5995 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5996inline void to_json(BasicJsonType& j, const CompatibleString& s)
5997{
5998 external_constructor<value_t::string>::construct(j, s);
5999}
6000
6001template<typename BasicJsonType>
6002inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
6003{
6004 external_constructor<value_t::string>::construct(j, std::move(s));
6005}
6006
6007template<typename BasicJsonType, typename FloatType,
6008 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
6009inline void to_json(BasicJsonType& j, FloatType val) noexcept
6010{
6011 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
6012}
6013
6014template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
6015 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
6016inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
6017{
6018 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
6019}
6020
6021template<typename BasicJsonType, typename CompatibleNumberIntegerType,
6022 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
6023inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
6024{
6025 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
6026}
6027
6028#if !JSON_DISABLE_ENUM_SERIALIZATION
6029template<typename BasicJsonType, typename EnumType,
6030 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
6031inline void to_json(BasicJsonType& j, EnumType e) noexcept
6032{
6033 using underlying_type = typename std::underlying_type<EnumType>::type;
6034 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
6035 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
6036}
6037#endif // JSON_DISABLE_ENUM_SERIALIZATION
6038
6039template<typename BasicJsonType>
6040inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
6041{
6042 external_constructor<value_t::array>::construct(j, e);
6043}
6044
6045template < typename BasicJsonType, typename CompatibleArrayType,
6046 enable_if_t < is_compatible_array_type<BasicJsonType,
6047 CompatibleArrayType>::value&&
6048 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
6049 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
6050 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
6051 !is_basic_json<CompatibleArrayType>::value,
6052 int > = 0 >
6053inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
6054{
6055 external_constructor<value_t::array>::construct(j, arr);
6056}
6057
6058template<typename BasicJsonType>
6059inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
6060{
6061 external_constructor<value_t::binary>::construct(j, bin);
6062}
6063
6064template<typename BasicJsonType, typename T,
6065 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
6066inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
6067{
6068 external_constructor<value_t::array>::construct(j, std::move(arr));
6069}
6070
6071template<typename BasicJsonType>
6072inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
6073{
6074 external_constructor<value_t::array>::construct(j, std::move(arr));
6075}
6076
6077template < typename BasicJsonType, typename CompatibleObjectType,
6078 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
6079inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
6080{
6081 external_constructor<value_t::object>::construct(j, obj);
6082}
6083
6084template<typename BasicJsonType>
6085inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
6086{
6087 external_constructor<value_t::object>::construct(j, std::move(obj));
6088}
6089
6090template <
6091 typename BasicJsonType, typename T, std::size_t N,
6092 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
6093 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6094 int > = 0 >
6095inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6096{
6097 external_constructor<value_t::array>::construct(j, arr);
6098}
6099
6100template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
6101inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
6102{
6103 j = { p.first, p.second };
6104}
6105
6106// for https://github.com/nlohmann/json/pull/1134
6107template<typename BasicJsonType, typename T,
6108 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
6109inline void to_json(BasicJsonType& j, const T& b)
6110{
6111 j = { {b.key(), b.value()} };
6112}
6113
6114template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
6115inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
6116{
6117 j = { std::get<Idx>(t)... };
6118}
6119
6120template<typename BasicJsonType, typename Tuple>
6121inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& /*unused*/, index_sequence<> /*unused*/)
6122{
6123 using array_t = typename BasicJsonType::array_t;
6124 j = array_t();
6125}
6126
6127template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
6128inline void to_json(BasicJsonType& j, const T& t)
6129{
6130 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
6131}
6132
6133#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
6134#if defined(__cpp_lib_char8_t)
6135template<typename BasicJsonType, typename Tr, typename Allocator>
6136inline void to_json(BasicJsonType& j, const std::basic_string<char8_t, Tr, Allocator>& s)
6137{
6138 using OtherAllocator = typename std::allocator_traits<Allocator>::template rebind_alloc<char>;
6139 j = std::basic_string<char, std::char_traits<char>, OtherAllocator>(s.begin(), s.end(), s.get_allocator());
6140}
6141#endif
6142
6143template<typename BasicJsonType>
6144inline void to_json(BasicJsonType& j, const std_fs::path& p)
6145{
6146 // Returns either a std::string or a std::u8string depending whether library
6147 // support for char8_t is enabled.
6148 j = p.u8string();
6149}
6150#endif
6151
6153{
6154 template<typename BasicJsonType, typename T>
6155 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
6156 -> decltype(to_json(j, std::forward<T>(val)), void())
6157 {
6158 return to_json(j, std::forward<T>(val));
6159 }
6160};
6161} // namespace detail
6162
6163#ifndef JSON_HAS_CPP_17
6167namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
6168{
6169#endif
6170JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
6172#ifndef JSON_HAS_CPP_17
6173} // namespace
6174#endif
6175
6176NLOHMANN_JSON_NAMESPACE_END
6177
6178// #include <nlohmann/detail/meta/identity_tag.hpp>
6179
6180
6181NLOHMANN_JSON_NAMESPACE_BEGIN
6182
6184template<typename ValueType, typename>
6186{
6189 template<typename BasicJsonType, typename TargetType = ValueType>
6190 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
6191 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
6192 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
6193 {
6194 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
6195 }
6196
6199 template<typename BasicJsonType, typename TargetType = ValueType>
6200 static auto from_json(BasicJsonType && j) noexcept(
6201 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
6202 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
6203 {
6204 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
6205 }
6206
6209 template<typename BasicJsonType, typename TargetType = ValueType>
6210 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
6211 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
6212 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
6213 {
6214 ::nlohmann::to_json(j, std::forward<TargetType>(val));
6215 }
6216};
6217
6218NLOHMANN_JSON_NAMESPACE_END
6219
6220// #include <nlohmann/byte_container_with_subtype.hpp>
6221// __ _____ _____ _____
6222// __| | __| | | | JSON for Modern C++
6223// | | |__ | | | | | | version 3.12.0
6224// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6225//
6226// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6227// SPDX-License-Identifier: MIT
6228
6229
6230
6231#include <cstdint> // uint8_t, uint64_t
6232#include <tuple> // tie
6233#include <utility> // move
6234
6235// #include <nlohmann/detail/abi_macros.hpp>
6236
6237
6238NLOHMANN_JSON_NAMESPACE_BEGIN
6239
6242template<typename BinaryType>
6243class byte_container_with_subtype : public BinaryType
6244{
6245 public:
6246 using container_type = BinaryType;
6247 using subtype_type = std::uint64_t;
6248
6250 byte_container_with_subtype() noexcept(noexcept(container_type()))
6251 : container_type()
6252 {}
6253
6255 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
6256 : container_type(b)
6257 {}
6258
6260 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
6261 : container_type(std::move(b))
6262 {}
6263
6265 byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
6266 : container_type(b)
6267 , m_subtype(subtype_)
6268 , m_has_subtype(true)
6269 {}
6270
6272 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
6273 : container_type(std::move(b))
6274 , m_subtype(subtype_)
6275 , m_has_subtype(true)
6276 {}
6277
6278 bool operator==(const byte_container_with_subtype& rhs) const
6279 {
6280 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
6281 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
6282 }
6283
6284 bool operator!=(const byte_container_with_subtype& rhs) const
6285 {
6286 return !(rhs == *this);
6287 }
6288
6291 void set_subtype(subtype_type subtype_) noexcept
6292 {
6293 m_subtype = subtype_;
6294 m_has_subtype = true;
6295 }
6296
6299 constexpr subtype_type subtype() const noexcept
6300 {
6301 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
6302 }
6303
6306 constexpr bool has_subtype() const noexcept
6307 {
6308 return m_has_subtype;
6309 }
6310
6313 void clear_subtype() noexcept
6314 {
6315 m_subtype = 0;
6316 m_has_subtype = false;
6317 }
6318
6319 private:
6320 subtype_type m_subtype = 0;
6321 bool m_has_subtype = false;
6322};
6323
6324NLOHMANN_JSON_NAMESPACE_END
6325
6326// #include <nlohmann/detail/conversions/from_json.hpp>
6327
6328// #include <nlohmann/detail/conversions/to_json.hpp>
6329
6330// #include <nlohmann/detail/exceptions.hpp>
6331
6332// #include <nlohmann/detail/hash.hpp>
6333// __ _____ _____ _____
6334// __| | __| | | | JSON for Modern C++
6335// | | |__ | | | | | | version 3.12.0
6336// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6337//
6338// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6339// SPDX-License-Identifier: MIT
6340
6341
6342
6343#include <cstdint> // uint8_t
6344#include <cstddef> // size_t
6345#include <functional> // hash
6346
6347// #include <nlohmann/detail/abi_macros.hpp>
6348
6349// #include <nlohmann/detail/value_t.hpp>
6350
6351
6352NLOHMANN_JSON_NAMESPACE_BEGIN
6353namespace detail
6354{
6355
6356// boost::hash_combine
6357inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6358{
6359 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6360 return seed;
6361}
6362
6374template<typename BasicJsonType>
6375std::size_t hash(const BasicJsonType& j)
6376{
6377 using string_t = typename BasicJsonType::string_t;
6378 using number_integer_t = typename BasicJsonType::number_integer_t;
6379 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6380 using number_float_t = typename BasicJsonType::number_float_t;
6381
6382 const auto type = static_cast<std::size_t>(j.type());
6383 switch (j.type())
6384 {
6385 case BasicJsonType::value_t::null:
6386 case BasicJsonType::value_t::discarded:
6387 {
6388 return combine(type, 0);
6389 }
6390
6391 case BasicJsonType::value_t::object:
6392 {
6393 auto seed = combine(type, j.size());
6394 for (const auto& element : j.items())
6395 {
6396 const auto h = std::hash<string_t> {}(element.key());
6397 seed = combine(seed, h);
6398 seed = combine(seed, hash(element.value()));
6399 }
6400 return seed;
6401 }
6402
6403 case BasicJsonType::value_t::array:
6404 {
6405 auto seed = combine(type, j.size());
6406 for (const auto& element : j)
6407 {
6408 seed = combine(seed, hash(element));
6409 }
6410 return seed;
6411 }
6412
6413 case BasicJsonType::value_t::string:
6414 {
6415 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6416 return combine(type, h);
6417 }
6418
6419 case BasicJsonType::value_t::boolean:
6420 {
6421 const auto h = std::hash<bool> {}(j.template get<bool>());
6422 return combine(type, h);
6423 }
6424
6425 case BasicJsonType::value_t::number_integer:
6426 {
6427 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6428 return combine(type, h);
6429 }
6430
6431 case BasicJsonType::value_t::number_unsigned:
6432 {
6433 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6434 return combine(type, h);
6435 }
6436
6437 case BasicJsonType::value_t::number_float:
6438 {
6439 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6440 return combine(type, h);
6441 }
6442
6443 case BasicJsonType::value_t::binary:
6444 {
6445 auto seed = combine(type, j.get_binary().size());
6446 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6447 seed = combine(seed, h);
6448 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6449 for (const auto byte : j.get_binary())
6450 {
6451 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6452 }
6453 return seed;
6454 }
6455
6456 default: // LCOV_EXCL_LINE
6457 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6458 return 0; // LCOV_EXCL_LINE
6459 }
6460}
6461
6462} // namespace detail
6463NLOHMANN_JSON_NAMESPACE_END
6464
6465// #include <nlohmann/detail/input/binary_reader.hpp>
6466// __ _____ _____ _____
6467// __| | __| | | | JSON for Modern C++
6468// | | |__ | | | | | | version 3.12.0
6469// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6470//
6471// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6472// SPDX-License-Identifier: MIT
6473
6474
6475
6476#include <algorithm> // generate_n
6477#include <array> // array
6478#include <cmath> // ldexp
6479#include <cstddef> // size_t
6480#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6481#include <cstdio> // snprintf
6482#include <cstring> // memcpy
6483#include <iterator> // back_inserter
6484#include <limits> // numeric_limits
6485#include <string> // char_traits, string
6486#include <utility> // make_pair, move
6487#include <vector> // vector
6488#ifdef __cpp_lib_byteswap
6489 #include <bit> //byteswap
6490#endif
6491
6492// #include <nlohmann/detail/exceptions.hpp>
6493
6494// #include <nlohmann/detail/input/input_adapters.hpp>
6495// __ _____ _____ _____
6496// __| | __| | | | JSON for Modern C++
6497// | | |__ | | | | | | version 3.12.0
6498// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6499//
6500// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6501// SPDX-License-Identifier: MIT
6502
6503
6504
6505#include <array> // array
6506#include <cstddef> // size_t
6507#include <cstring> // strlen
6508#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6509#include <memory> // shared_ptr, make_shared, addressof
6510#include <numeric> // accumulate
6511#include <streambuf> // streambuf
6512#include <string> // string, char_traits
6513#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6514#include <utility> // pair, declval
6515
6516#ifndef JSON_NO_IO
6517 #include <cstdio> // FILE *
6518 #include <istream> // istream
6519#endif // JSON_NO_IO
6520
6521// #include <nlohmann/detail/exceptions.hpp>
6522
6523// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6524
6525// #include <nlohmann/detail/macro_scope.hpp>
6526
6527// #include <nlohmann/detail/meta/type_traits.hpp>
6528
6529
6530NLOHMANN_JSON_NAMESPACE_BEGIN
6531namespace detail
6532{
6533
6535enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
6536
6538// input adapters //
6540
6541#ifndef JSON_NO_IO
6546class file_input_adapter
6547{
6548 public:
6549 using char_type = char;
6550
6551 JSON_HEDLEY_NON_NULL(2)
6552 explicit file_input_adapter(std::FILE* f) noexcept
6553 : m_file(f)
6554 {
6555 JSON_ASSERT(m_file != nullptr);
6556 }
6557
6558 // make class move-only
6559 file_input_adapter(const file_input_adapter&) = delete;
6560 file_input_adapter(file_input_adapter&&) noexcept = default;
6561 file_input_adapter& operator=(const file_input_adapter&) = delete;
6562 file_input_adapter& operator=(file_input_adapter&&) = delete;
6563 ~file_input_adapter() = default;
6564
6565 std::char_traits<char>::int_type get_character() noexcept
6566 {
6567 return std::fgetc(m_file);
6568 }
6569
6570 // returns the number of characters successfully read
6571 template<class T>
6572 std::size_t get_elements(T* dest, std::size_t count = 1)
6573 {
6574 return fread(dest, 1, sizeof(T) * count, m_file);
6575 }
6576
6577 private:
6579 std::FILE* m_file;
6580};
6581
6591class input_stream_adapter
6592{
6593 public:
6594 using char_type = char;
6595
6596 ~input_stream_adapter()
6597 {
6598 // clear stream flags; we use underlying streambuf I/O, do not
6599 // maintain ifstream flags, except eof
6600 if (is != nullptr)
6601 {
6602 is->clear(is->rdstate() & std::ios::eofbit);
6603 }
6604 }
6605
6606 explicit input_stream_adapter(std::istream& i)
6607 : is(&i), sb(i.rdbuf())
6608 {}
6609
6610 // deleted because of pointer members
6611 input_stream_adapter(const input_stream_adapter&) = delete;
6612 input_stream_adapter& operator=(input_stream_adapter&) = delete;
6613 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
6614
6615 input_stream_adapter(input_stream_adapter&& rhs) noexcept
6616 : is(rhs.is), sb(rhs.sb)
6617 {
6618 rhs.is = nullptr;
6619 rhs.sb = nullptr;
6620 }
6621
6622 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6623 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6624 // end up as the same value, e.g., 0xFFFFFFFF.
6625 std::char_traits<char>::int_type get_character()
6626 {
6627 auto res = sb->sbumpc();
6628 // set eof manually, as we don't use the istream interface.
6629 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6630 {
6631 is->clear(is->rdstate() | std::ios::eofbit);
6632 }
6633 return res;
6634 }
6635
6636 template<class T>
6637 std::size_t get_elements(T* dest, std::size_t count = 1)
6638 {
6639 auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
6640 if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T)))
6641 {
6642 is->clear(is->rdstate() | std::ios::eofbit);
6643 }
6644 return res;
6645 }
6646
6647 private:
6649 std::istream* is = nullptr;
6650 std::streambuf* sb = nullptr;
6651};
6652#endif // JSON_NO_IO
6653
6654// General-purpose iterator-based adapter. It might not be as fast as
6655// theoretically possible for some containers, but it is extremely versatile.
6656template<typename IteratorType>
6657class iterator_input_adapter
6658{
6659 public:
6660 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6661
6662 iterator_input_adapter(IteratorType first, IteratorType last)
6663 : current(std::move(first)), end(std::move(last))
6664 {}
6665
6666 typename char_traits<char_type>::int_type get_character()
6667 {
6668 if (JSON_HEDLEY_LIKELY(current != end))
6669 {
6670 auto result = char_traits<char_type>::to_int_type(*current);
6671 std::advance(current, 1);
6672 return result;
6673 }
6674
6675 return char_traits<char_type>::eof();
6676 }
6677
6678 // for general iterators, we cannot really do something better than falling back to processing the range one-by-one
6679 template<class T>
6680 std::size_t get_elements(T* dest, std::size_t count = 1)
6681 {
6682 auto* ptr = reinterpret_cast<char*>(dest);
6683 for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index)
6684 {
6685 if (JSON_HEDLEY_LIKELY(current != end))
6686 {
6687 ptr[read_index] = static_cast<char>(*current);
6688 std::advance(current, 1);
6689 }
6690 else
6691 {
6692 return read_index;
6693 }
6694 }
6695 return count * sizeof(T);
6696 }
6697
6698 private:
6699 IteratorType current;
6700 IteratorType end;
6701
6702 template<typename BaseInputAdapter, size_t T>
6703 friend struct wide_string_input_helper;
6704
6705 bool empty() const
6706 {
6707 return current == end;
6708 }
6709};
6710
6711template<typename BaseInputAdapter, size_t T>
6712struct wide_string_input_helper;
6713
6714template<typename BaseInputAdapter>
6715struct wide_string_input_helper<BaseInputAdapter, 4>
6716{
6717 // UTF-32
6718 static void fill_buffer(BaseInputAdapter& input,
6719 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6720 size_t& utf8_bytes_index,
6721 size_t& utf8_bytes_filled)
6722 {
6723 utf8_bytes_index = 0;
6724
6725 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6726 {
6727 utf8_bytes[0] = std::char_traits<char>::eof();
6728 utf8_bytes_filled = 1;
6729 }
6730 else
6731 {
6732 // get the current character
6733 const auto wc = input.get_character();
6734
6735 // UTF-32 to UTF-8 encoding
6736 if (wc < 0x80)
6737 {
6738 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6739 utf8_bytes_filled = 1;
6740 }
6741 else if (wc <= 0x7FF)
6742 {
6743 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6744 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6745 utf8_bytes_filled = 2;
6746 }
6747 else if (wc <= 0xFFFF)
6748 {
6749 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6750 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6751 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6752 utf8_bytes_filled = 3;
6753 }
6754 else if (wc <= 0x10FFFF)
6755 {
6756 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6757 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6758 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6759 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6760 utf8_bytes_filled = 4;
6761 }
6762 else
6763 {
6764 // unknown character
6765 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6766 utf8_bytes_filled = 1;
6767 }
6768 }
6769 }
6770};
6771
6772template<typename BaseInputAdapter>
6773struct wide_string_input_helper<BaseInputAdapter, 2>
6774{
6775 // UTF-16
6776 static void fill_buffer(BaseInputAdapter& input,
6777 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6778 size_t& utf8_bytes_index,
6779 size_t& utf8_bytes_filled)
6780 {
6781 utf8_bytes_index = 0;
6782
6783 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6784 {
6785 utf8_bytes[0] = std::char_traits<char>::eof();
6786 utf8_bytes_filled = 1;
6787 }
6788 else
6789 {
6790 // get the current character
6791 const auto wc = input.get_character();
6792
6793 // UTF-16 to UTF-8 encoding
6794 if (wc < 0x80)
6795 {
6796 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6797 utf8_bytes_filled = 1;
6798 }
6799 else if (wc <= 0x7FF)
6800 {
6801 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6802 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6803 utf8_bytes_filled = 2;
6804 }
6805 else if (0xD800 > wc || wc >= 0xE000)
6806 {
6807 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6808 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6809 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6810 utf8_bytes_filled = 3;
6811 }
6812 else
6813 {
6814 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6815 {
6816 const auto wc2 = static_cast<unsigned int>(input.get_character());
6817 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6818 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6819 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6820 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6821 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6822 utf8_bytes_filled = 4;
6823 }
6824 else
6825 {
6826 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6827 utf8_bytes_filled = 1;
6828 }
6829 }
6830 }
6831 }
6832};
6833
6834// Wraps another input adapter to convert wide character types into individual bytes.
6835template<typename BaseInputAdapter, typename WideCharType>
6836class wide_string_input_adapter
6837{
6838 public:
6839 using char_type = char;
6840
6841 wide_string_input_adapter(BaseInputAdapter base)
6842 : base_adapter(base) {}
6843
6844 typename std::char_traits<char>::int_type get_character() noexcept
6845 {
6846 // check if the buffer needs to be filled
6847 if (utf8_bytes_index == utf8_bytes_filled)
6848 {
6849 fill_buffer<sizeof(WideCharType)>();
6850
6851 JSON_ASSERT(utf8_bytes_filled > 0);
6852 JSON_ASSERT(utf8_bytes_index == 0);
6853 }
6854
6855 // use buffer
6856 JSON_ASSERT(utf8_bytes_filled > 0);
6857 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6858 return utf8_bytes[utf8_bytes_index++];
6859 }
6860
6861 // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
6862 template<class T>
6863 std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
6864 {
6865 JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
6866 }
6867
6868 private:
6869 BaseInputAdapter base_adapter;
6870
6871 template<size_t T>
6872 void fill_buffer()
6873 {
6874 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6875 }
6876
6878 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6879
6881 std::size_t utf8_bytes_index = 0;
6883 std::size_t utf8_bytes_filled = 0;
6884};
6885
6886template<typename IteratorType, typename Enable = void>
6887struct iterator_input_adapter_factory
6888{
6889 using iterator_type = IteratorType;
6890 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6891 using adapter_type = iterator_input_adapter<iterator_type>;
6892
6893 static adapter_type create(IteratorType first, IteratorType last)
6894 {
6895 return adapter_type(std::move(first), std::move(last));
6896 }
6897};
6898
6899template<typename T>
6900struct is_iterator_of_multibyte
6901{
6902 using value_type = typename std::iterator_traits<T>::value_type;
6903 enum
6904 {
6905 value = sizeof(value_type) > 1
6906 };
6907};
6908
6909template<typename IteratorType>
6910struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
6911{
6912 using iterator_type = IteratorType;
6913 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6914 using base_adapter_type = iterator_input_adapter<iterator_type>;
6915 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
6916
6917 static adapter_type create(IteratorType first, IteratorType last)
6918 {
6919 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6920 }
6921};
6922
6923// General purpose iterator-based input
6924template<typename IteratorType>
6925typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
6926{
6927 using factory_type = iterator_input_adapter_factory<IteratorType>;
6928 return factory_type::create(first, last);
6929}
6930
6931// Convenience shorthand from container to iterator
6932// Enables ADL on begin(container) and end(container)
6933// Encloses the using declarations in namespace for not to leak them to outside scope
6934
6935namespace container_input_adapter_factory_impl
6936{
6937
6938using std::begin;
6939using std::end;
6940
6941template<typename ContainerType, typename Enable = void>
6943
6944template<typename ContainerType>
6946 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6947 {
6948 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6949
6950 static adapter_type create(const ContainerType& container)
6951{
6952 return input_adapter(begin(container), end(container));
6953}
6954 };
6955
6956} // namespace container_input_adapter_factory_impl
6957
6958template<typename ContainerType>
6960{
6962}
6963
6964// specialization for std::string
6965using string_input_adapter_type = decltype(input_adapter(std::declval<std::string>()));
6966
6967#ifndef JSON_NO_IO
6968// Special cases with fast paths
6969inline file_input_adapter input_adapter(std::FILE* file)
6970{
6971 if (file == nullptr)
6972 {
6973 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));
6974 }
6975 return file_input_adapter(file);
6976}
6977
6978inline input_stream_adapter input_adapter(std::istream& stream)
6979{
6980 return input_stream_adapter(stream);
6981}
6982
6983inline input_stream_adapter input_adapter(std::istream&& stream)
6984{
6985 return input_stream_adapter(stream);
6986}
6987#endif // JSON_NO_IO
6988
6989using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6990
6991// Null-delimited strings, and the like.
6992template < typename CharT,
6993 typename std::enable_if <
6994 std::is_pointer<CharT>::value&&
6995 !std::is_array<CharT>::value&&
6996 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6997 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6998 int >::type = 0 >
6999contiguous_bytes_input_adapter input_adapter(CharT b)
7000{
7001 if (b == nullptr)
7002 {
7003 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));
7004 }
7005 auto length = std::strlen(reinterpret_cast<const char*>(b));
7006 const auto* ptr = reinterpret_cast<const char*>(b);
7007 return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck]
7008}
7009
7010template<typename T, std::size_t N>
7011auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
7012{
7013 return input_adapter(array, array + N);
7014}
7015
7016// This class only handles inputs of input_buffer_adapter type.
7017// It's required so that expressions like {ptr, len} can be implicitly cast
7018// to the correct adapter.
7019class span_input_adapter
7020{
7021 public:
7022 template < typename CharT,
7023 typename std::enable_if <
7024 std::is_pointer<CharT>::value&&
7025 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
7026 sizeof(typename std::remove_pointer<CharT>::type) == 1,
7027 int >::type = 0 >
7028 span_input_adapter(CharT b, std::size_t l)
7029 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
7030
7031 template<class IteratorType,
7032 typename std::enable_if<
7033 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
7034 int>::type = 0>
7035 span_input_adapter(IteratorType first, IteratorType last)
7036 : ia(input_adapter(first, last)) {}
7037
7038 contiguous_bytes_input_adapter&& get()
7039 {
7040 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
7041 }
7042
7043 private:
7044 contiguous_bytes_input_adapter ia;
7045};
7046
7047} // namespace detail
7048NLOHMANN_JSON_NAMESPACE_END
7049
7050// #include <nlohmann/detail/input/json_sax.hpp>
7051// __ _____ _____ _____
7052// __| | __| | | | JSON for Modern C++
7053// | | |__ | | | | | | version 3.12.0
7054// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7055//
7056// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7057// SPDX-License-Identifier: MIT
7058
7059
7060
7061#include <cstddef>
7062#include <string> // string
7063#include <type_traits> // enable_if_t
7064#include <utility> // move
7065#include <vector> // vector
7066
7067// #include <nlohmann/detail/exceptions.hpp>
7068
7069// #include <nlohmann/detail/input/lexer.hpp>
7070// __ _____ _____ _____
7071// __| | __| | | | JSON for Modern C++
7072// | | |__ | | | | | | version 3.12.0
7073// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7074//
7075// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7076// SPDX-License-Identifier: MIT
7077
7078
7079
7080#include <array> // array
7081#include <clocale> // localeconv
7082#include <cstddef> // size_t
7083#include <cstdio> // snprintf
7084#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7085#include <initializer_list> // initializer_list
7086#include <string> // char_traits, string
7087#include <utility> // move
7088#include <vector> // vector
7089
7090// #include <nlohmann/detail/input/input_adapters.hpp>
7091
7092// #include <nlohmann/detail/input/position_t.hpp>
7093
7094// #include <nlohmann/detail/macro_scope.hpp>
7095
7096// #include <nlohmann/detail/meta/type_traits.hpp>
7097
7098
7099NLOHMANN_JSON_NAMESPACE_BEGIN
7100namespace detail
7101{
7102
7104// lexer //
7106
7107template<typename BasicJsonType>
7108class lexer_base
7109{
7110 public:
7112 enum class token_type
7113 {
7114 uninitialized,
7115 literal_true,
7116 literal_false,
7117 literal_null,
7118 value_string,
7119 value_unsigned,
7120 value_integer,
7121 value_float,
7122 begin_array,
7123 begin_object,
7124 end_array,
7125 end_object,
7126 name_separator,
7127 value_separator,
7128 parse_error,
7129 end_of_input,
7130 literal_or_value
7131 };
7132
7134 JSON_HEDLEY_RETURNS_NON_NULL
7135 JSON_HEDLEY_CONST
7136 static const char* token_type_name(const token_type t) noexcept
7137 {
7138 switch (t)
7139 {
7140 case token_type::uninitialized:
7141 return "<uninitialized>";
7142 case token_type::literal_true:
7143 return "true literal";
7144 case token_type::literal_false:
7145 return "false literal";
7146 case token_type::literal_null:
7147 return "null literal";
7148 case token_type::value_string:
7149 return "string literal";
7150 case token_type::value_unsigned:
7151 case token_type::value_integer:
7152 case token_type::value_float:
7153 return "number literal";
7154 case token_type::begin_array:
7155 return "'['";
7156 case token_type::begin_object:
7157 return "'{'";
7158 case token_type::end_array:
7159 return "']'";
7160 case token_type::end_object:
7161 return "'}'";
7162 case token_type::name_separator:
7163 return "':'";
7164 case token_type::value_separator:
7165 return "','";
7166 case token_type::parse_error:
7167 return "<parse error>";
7168 case token_type::end_of_input:
7169 return "end of input";
7170 case token_type::literal_or_value:
7171 return "'[', '{', or a literal";
7172 // LCOV_EXCL_START
7173 default: // catch non-enum values
7174 return "unknown token";
7175 // LCOV_EXCL_STOP
7176 }
7177 }
7178};
7184template<typename BasicJsonType, typename InputAdapterType>
7185class lexer : public lexer_base<BasicJsonType>
7186{
7187 using number_integer_t = typename BasicJsonType::number_integer_t;
7188 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7189 using number_float_t = typename BasicJsonType::number_float_t;
7190 using string_t = typename BasicJsonType::string_t;
7191 using char_type = typename InputAdapterType::char_type;
7192 using char_int_type = typename char_traits<char_type>::int_type;
7193
7194 public:
7195 using token_type = typename lexer_base<BasicJsonType>::token_type;
7196
7197 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7198 : ia(std::move(adapter))
7199 , ignore_comments(ignore_comments_)
7200 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7201 {}
7202
7203 // deleted because of pointer members
7204 lexer(const lexer&) = delete;
7205 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7206 lexer& operator=(lexer&) = delete;
7207 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7208 ~lexer() = default;
7209
7210 private:
7212 // locales
7214
7216 JSON_HEDLEY_PURE
7217 static char get_decimal_point() noexcept
7218 {
7219 const auto* loc = localeconv();
7220 JSON_ASSERT(loc != nullptr);
7221 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7222 }
7223
7225 // scan functions
7227
7243 int get_codepoint()
7244 {
7245 // this function only makes sense after reading `\u`
7246 JSON_ASSERT(current == 'u');
7247 int codepoint = 0;
7248
7249 const auto factors = { 12u, 8u, 4u, 0u };
7250 for (const auto factor : factors)
7251 {
7252 get();
7253
7254 if (current >= '0' && current <= '9')
7255 {
7256 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7257 }
7258 else if (current >= 'A' && current <= 'F')
7259 {
7260 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7261 }
7262 else if (current >= 'a' && current <= 'f')
7263 {
7264 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7265 }
7266 else
7267 {
7268 return -1;
7269 }
7270 }
7271
7272 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7273 return codepoint;
7274 }
7275
7291 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7292 {
7293 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7294 add(current);
7295
7296 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7297 {
7298 get();
7299 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7300 {
7301 add(current);
7302 }
7303 else
7304 {
7305 error_message = "invalid string: ill-formed UTF-8 byte";
7306 return false;
7307 }
7308 }
7309
7310 return true;
7311 }
7312
7328 token_type scan_string()
7329 {
7330 // reset token_buffer (ignore opening quote)
7331 reset();
7332
7333 // we entered the function by reading an open quote
7334 JSON_ASSERT(current == '\"');
7335
7336 while (true)
7337 {
7338 // get the next character
7339 switch (get())
7340 {
7341 // end of file while parsing the string
7342 case char_traits<char_type>::eof():
7343 {
7344 error_message = "invalid string: missing closing quote";
7345 return token_type::parse_error;
7346 }
7347
7348 // closing quote
7349 case '\"':
7350 {
7351 return token_type::value_string;
7352 }
7353
7354 // escapes
7355 case '\\':
7356 {
7357 switch (get())
7358 {
7359 // quotation mark
7360 case '\"':
7361 add('\"');
7362 break;
7363 // reverse solidus
7364 case '\\':
7365 add('\\');
7366 break;
7367 // solidus
7368 case '/':
7369 add('/');
7370 break;
7371 // backspace
7372 case 'b':
7373 add('\b');
7374 break;
7375 // form feed
7376 case 'f':
7377 add('\f');
7378 break;
7379 // line feed
7380 case 'n':
7381 add('\n');
7382 break;
7383 // carriage return
7384 case 'r':
7385 add('\r');
7386 break;
7387 // tab
7388 case 't':
7389 add('\t');
7390 break;
7391
7392 // unicode escapes
7393 case 'u':
7394 {
7395 const int codepoint1 = get_codepoint();
7396 int codepoint = codepoint1; // start with codepoint1
7397
7398 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7399 {
7400 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7401 return token_type::parse_error;
7402 }
7403
7404 // check if code point is a high surrogate
7405 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7406 {
7407 // expect next \uxxxx entry
7408 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7409 {
7410 const int codepoint2 = get_codepoint();
7411
7412 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7413 {
7414 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7415 return token_type::parse_error;
7416 }
7417
7418 // check if codepoint2 is a low surrogate
7419 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7420 {
7421 // overwrite codepoint
7422 codepoint = static_cast<int>(
7423 // high surrogate occupies the most significant 22 bits
7424 (static_cast<unsigned int>(codepoint1) << 10u)
7425 // low surrogate occupies the least significant 15 bits
7426 + static_cast<unsigned int>(codepoint2)
7427 // there is still the 0xD800, 0xDC00, and 0x10000 noise
7428 // in the result, so we have to subtract with:
7429 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7430 - 0x35FDC00u);
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 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7441 return token_type::parse_error;
7442 }
7443 }
7444 else
7445 {
7446 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7447 {
7448 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7449 return token_type::parse_error;
7450 }
7451 }
7452
7453 // the result of the above calculation yields a proper codepoint
7454 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7455
7456 // translate codepoint into bytes
7457 if (codepoint < 0x80)
7458 {
7459 // 1-byte characters: 0xxxxxxx (ASCII)
7460 add(static_cast<char_int_type>(codepoint));
7461 }
7462 else if (codepoint <= 0x7FF)
7463 {
7464 // 2-byte characters: 110xxxxx 10xxxxxx
7465 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7466 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7467 }
7468 else if (codepoint <= 0xFFFF)
7469 {
7470 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7471 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7472 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7473 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7474 }
7475 else
7476 {
7477 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7478 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7479 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7480 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7481 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7482 }
7483
7484 break;
7485 }
7486
7487 // other characters after escape
7488 default:
7489 error_message = "invalid string: forbidden character after backslash";
7490 return token_type::parse_error;
7491 }
7492
7493 break;
7494 }
7495
7496 // invalid control characters
7497 case 0x00:
7498 {
7499 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7500 return token_type::parse_error;
7501 }
7502
7503 case 0x01:
7504 {
7505 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7506 return token_type::parse_error;
7507 }
7508
7509 case 0x02:
7510 {
7511 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7512 return token_type::parse_error;
7513 }
7514
7515 case 0x03:
7516 {
7517 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7518 return token_type::parse_error;
7519 }
7520
7521 case 0x04:
7522 {
7523 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7524 return token_type::parse_error;
7525 }
7526
7527 case 0x05:
7528 {
7529 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7530 return token_type::parse_error;
7531 }
7532
7533 case 0x06:
7534 {
7535 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7536 return token_type::parse_error;
7537 }
7538
7539 case 0x07:
7540 {
7541 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7542 return token_type::parse_error;
7543 }
7544
7545 case 0x08:
7546 {
7547 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7548 return token_type::parse_error;
7549 }
7550
7551 case 0x09:
7552 {
7553 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7554 return token_type::parse_error;
7555 }
7556
7557 case 0x0A:
7558 {
7559 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7560 return token_type::parse_error;
7561 }
7562
7563 case 0x0B:
7564 {
7565 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7566 return token_type::parse_error;
7567 }
7568
7569 case 0x0C:
7570 {
7571 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7572 return token_type::parse_error;
7573 }
7574
7575 case 0x0D:
7576 {
7577 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7578 return token_type::parse_error;
7579 }
7580
7581 case 0x0E:
7582 {
7583 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7584 return token_type::parse_error;
7585 }
7586
7587 case 0x0F:
7588 {
7589 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7590 return token_type::parse_error;
7591 }
7592
7593 case 0x10:
7594 {
7595 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7596 return token_type::parse_error;
7597 }
7598
7599 case 0x11:
7600 {
7601 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7602 return token_type::parse_error;
7603 }
7604
7605 case 0x12:
7606 {
7607 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7608 return token_type::parse_error;
7609 }
7610
7611 case 0x13:
7612 {
7613 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7614 return token_type::parse_error;
7615 }
7616
7617 case 0x14:
7618 {
7619 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7620 return token_type::parse_error;
7621 }
7622
7623 case 0x15:
7624 {
7625 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7626 return token_type::parse_error;
7627 }
7628
7629 case 0x16:
7630 {
7631 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7632 return token_type::parse_error;
7633 }
7634
7635 case 0x17:
7636 {
7637 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7638 return token_type::parse_error;
7639 }
7640
7641 case 0x18:
7642 {
7643 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7644 return token_type::parse_error;
7645 }
7646
7647 case 0x19:
7648 {
7649 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7650 return token_type::parse_error;
7651 }
7652
7653 case 0x1A:
7654 {
7655 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7656 return token_type::parse_error;
7657 }
7658
7659 case 0x1B:
7660 {
7661 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7662 return token_type::parse_error;
7663 }
7664
7665 case 0x1C:
7666 {
7667 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7668 return token_type::parse_error;
7669 }
7670
7671 case 0x1D:
7672 {
7673 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7674 return token_type::parse_error;
7675 }
7676
7677 case 0x1E:
7678 {
7679 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7680 return token_type::parse_error;
7681 }
7682
7683 case 0x1F:
7684 {
7685 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7686 return token_type::parse_error;
7687 }
7688
7689 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7690 case 0x20:
7691 case 0x21:
7692 case 0x23:
7693 case 0x24:
7694 case 0x25:
7695 case 0x26:
7696 case 0x27:
7697 case 0x28:
7698 case 0x29:
7699 case 0x2A:
7700 case 0x2B:
7701 case 0x2C:
7702 case 0x2D:
7703 case 0x2E:
7704 case 0x2F:
7705 case 0x30:
7706 case 0x31:
7707 case 0x32:
7708 case 0x33:
7709 case 0x34:
7710 case 0x35:
7711 case 0x36:
7712 case 0x37:
7713 case 0x38:
7714 case 0x39:
7715 case 0x3A:
7716 case 0x3B:
7717 case 0x3C:
7718 case 0x3D:
7719 case 0x3E:
7720 case 0x3F:
7721 case 0x40:
7722 case 0x41:
7723 case 0x42:
7724 case 0x43:
7725 case 0x44:
7726 case 0x45:
7727 case 0x46:
7728 case 0x47:
7729 case 0x48:
7730 case 0x49:
7731 case 0x4A:
7732 case 0x4B:
7733 case 0x4C:
7734 case 0x4D:
7735 case 0x4E:
7736 case 0x4F:
7737 case 0x50:
7738 case 0x51:
7739 case 0x52:
7740 case 0x53:
7741 case 0x54:
7742 case 0x55:
7743 case 0x56:
7744 case 0x57:
7745 case 0x58:
7746 case 0x59:
7747 case 0x5A:
7748 case 0x5B:
7749 case 0x5D:
7750 case 0x5E:
7751 case 0x5F:
7752 case 0x60:
7753 case 0x61:
7754 case 0x62:
7755 case 0x63:
7756 case 0x64:
7757 case 0x65:
7758 case 0x66:
7759 case 0x67:
7760 case 0x68:
7761 case 0x69:
7762 case 0x6A:
7763 case 0x6B:
7764 case 0x6C:
7765 case 0x6D:
7766 case 0x6E:
7767 case 0x6F:
7768 case 0x70:
7769 case 0x71:
7770 case 0x72:
7771 case 0x73:
7772 case 0x74:
7773 case 0x75:
7774 case 0x76:
7775 case 0x77:
7776 case 0x78:
7777 case 0x79:
7778 case 0x7A:
7779 case 0x7B:
7780 case 0x7C:
7781 case 0x7D:
7782 case 0x7E:
7783 case 0x7F:
7784 {
7785 add(current);
7786 break;
7787 }
7788
7789 // U+0080..U+07FF: bytes C2..DF 80..BF
7790 case 0xC2:
7791 case 0xC3:
7792 case 0xC4:
7793 case 0xC5:
7794 case 0xC6:
7795 case 0xC7:
7796 case 0xC8:
7797 case 0xC9:
7798 case 0xCA:
7799 case 0xCB:
7800 case 0xCC:
7801 case 0xCD:
7802 case 0xCE:
7803 case 0xCF:
7804 case 0xD0:
7805 case 0xD1:
7806 case 0xD2:
7807 case 0xD3:
7808 case 0xD4:
7809 case 0xD5:
7810 case 0xD6:
7811 case 0xD7:
7812 case 0xD8:
7813 case 0xD9:
7814 case 0xDA:
7815 case 0xDB:
7816 case 0xDC:
7817 case 0xDD:
7818 case 0xDE:
7819 case 0xDF:
7820 {
7821 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7822 {
7823 return token_type::parse_error;
7824 }
7825 break;
7826 }
7827
7828 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7829 case 0xE0:
7830 {
7831 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7832 {
7833 return token_type::parse_error;
7834 }
7835 break;
7836 }
7837
7838 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7839 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7840 case 0xE1:
7841 case 0xE2:
7842 case 0xE3:
7843 case 0xE4:
7844 case 0xE5:
7845 case 0xE6:
7846 case 0xE7:
7847 case 0xE8:
7848 case 0xE9:
7849 case 0xEA:
7850 case 0xEB:
7851 case 0xEC:
7852 case 0xEE:
7853 case 0xEF:
7854 {
7855 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7856 {
7857 return token_type::parse_error;
7858 }
7859 break;
7860 }
7861
7862 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7863 case 0xED:
7864 {
7865 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7866 {
7867 return token_type::parse_error;
7868 }
7869 break;
7870 }
7871
7872 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7873 case 0xF0:
7874 {
7875 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7876 {
7877 return token_type::parse_error;
7878 }
7879 break;
7880 }
7881
7882 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7883 case 0xF1:
7884 case 0xF2:
7885 case 0xF3:
7886 {
7887 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7888 {
7889 return token_type::parse_error;
7890 }
7891 break;
7892 }
7893
7894 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7895 case 0xF4:
7896 {
7897 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7898 {
7899 return token_type::parse_error;
7900 }
7901 break;
7902 }
7903
7904 // the remaining bytes (80..C1 and F5..FF) are ill-formed
7905 default:
7906 {
7907 error_message = "invalid string: ill-formed UTF-8 byte";
7908 return token_type::parse_error;
7909 }
7910 }
7911 }
7912 }
7913
7918 bool scan_comment()
7919 {
7920 switch (get())
7921 {
7922 // single-line comments skip input until a newline or EOF is read
7923 case '/':
7924 {
7925 while (true)
7926 {
7927 switch (get())
7928 {
7929 case '\n':
7930 case '\r':
7931 case char_traits<char_type>::eof():
7932 case '\0':
7933 return true;
7934
7935 default:
7936 break;
7937 }
7938 }
7939 }
7940
7941 // multi-line comments skip input until */ is read
7942 case '*':
7943 {
7944 while (true)
7945 {
7946 switch (get())
7947 {
7948 case char_traits<char_type>::eof():
7949 case '\0':
7950 {
7951 error_message = "invalid comment; missing closing '*/'";
7952 return false;
7953 }
7954
7955 case '*':
7956 {
7957 switch (get())
7958 {
7959 case '/':
7960 return true;
7961
7962 default:
7963 {
7964 unget();
7965 continue;
7966 }
7967 }
7968 }
7969
7970 default:
7971 continue;
7972 }
7973 }
7974 }
7975
7976 // unexpected character after reading '/'
7977 default:
7978 {
7979 error_message = "invalid comment; expecting '/' or '*' after '/'";
7980 return false;
7981 }
7982 }
7983 }
7984
7985 JSON_HEDLEY_NON_NULL(2)
7986 static void strtof(float& f, const char* str, char** endptr) noexcept
7987 {
7988 f = std::strtof(str, endptr);
7989 }
7990
7991 JSON_HEDLEY_NON_NULL(2)
7992 static void strtof(double& f, const char* str, char** endptr) noexcept
7993 {
7994 f = std::strtod(str, endptr);
7995 }
7996
7997 JSON_HEDLEY_NON_NULL(2)
7998 static void strtof(long double& f, const char* str, char** endptr) noexcept
7999 {
8000 f = std::strtold(str, endptr);
8001 }
8002
8043 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.
8044 {
8045 // reset token_buffer to store the number's bytes
8046 reset();
8047
8048 // the type of the parsed number; initially set to unsigned; will be
8049 // changed if minus sign, decimal point, or exponent is read
8050 token_type number_type = token_type::value_unsigned;
8051
8052 // state (init): we just found out we need to scan a number
8053 switch (current)
8054 {
8055 case '-':
8056 {
8057 add(current);
8058 goto scan_number_minus;
8059 }
8060
8061 case '0':
8062 {
8063 add(current);
8064 goto scan_number_zero;
8065 }
8066
8067 case '1':
8068 case '2':
8069 case '3':
8070 case '4':
8071 case '5':
8072 case '6':
8073 case '7':
8074 case '8':
8075 case '9':
8076 {
8077 add(current);
8078 goto scan_number_any1;
8079 }
8080
8081 // all other characters are rejected outside scan_number()
8082 default: // LCOV_EXCL_LINE
8083 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8084 }
8085
8086scan_number_minus:
8087 // state: we just parsed a leading minus sign
8088 number_type = token_type::value_integer;
8089 switch (get())
8090 {
8091 case '0':
8092 {
8093 add(current);
8094 goto scan_number_zero;
8095 }
8096
8097 case '1':
8098 case '2':
8099 case '3':
8100 case '4':
8101 case '5':
8102 case '6':
8103 case '7':
8104 case '8':
8105 case '9':
8106 {
8107 add(current);
8108 goto scan_number_any1;
8109 }
8110
8111 default:
8112 {
8113 error_message = "invalid number; expected digit after '-'";
8114 return token_type::parse_error;
8115 }
8116 }
8117
8118scan_number_zero:
8119 // state: we just parse a zero (maybe with a leading minus sign)
8120 switch (get())
8121 {
8122 case '.':
8123 {
8124 add(decimal_point_char);
8125 decimal_point_position = token_buffer.size() - 1;
8126 goto scan_number_decimal1;
8127 }
8128
8129 case 'e':
8130 case 'E':
8131 {
8132 add(current);
8133 goto scan_number_exponent;
8134 }
8135
8136 default:
8137 goto scan_number_done;
8138 }
8139
8140scan_number_any1:
8141 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8142 switch (get())
8143 {
8144 case '0':
8145 case '1':
8146 case '2':
8147 case '3':
8148 case '4':
8149 case '5':
8150 case '6':
8151 case '7':
8152 case '8':
8153 case '9':
8154 {
8155 add(current);
8156 goto scan_number_any1;
8157 }
8158
8159 case '.':
8160 {
8161 add(decimal_point_char);
8162 decimal_point_position = token_buffer.size() - 1;
8163 goto scan_number_decimal1;
8164 }
8165
8166 case 'e':
8167 case 'E':
8168 {
8169 add(current);
8170 goto scan_number_exponent;
8171 }
8172
8173 default:
8174 goto scan_number_done;
8175 }
8176
8177scan_number_decimal1:
8178 // state: we just parsed a decimal point
8179 number_type = token_type::value_float;
8180 switch (get())
8181 {
8182 case '0':
8183 case '1':
8184 case '2':
8185 case '3':
8186 case '4':
8187 case '5':
8188 case '6':
8189 case '7':
8190 case '8':
8191 case '9':
8192 {
8193 add(current);
8194 goto scan_number_decimal2;
8195 }
8196
8197 default:
8198 {
8199 error_message = "invalid number; expected digit after '.'";
8200 return token_type::parse_error;
8201 }
8202 }
8203
8204scan_number_decimal2:
8205 // we just parsed at least one number after a decimal point
8206 switch (get())
8207 {
8208 case '0':
8209 case '1':
8210 case '2':
8211 case '3':
8212 case '4':
8213 case '5':
8214 case '6':
8215 case '7':
8216 case '8':
8217 case '9':
8218 {
8219 add(current);
8220 goto scan_number_decimal2;
8221 }
8222
8223 case 'e':
8224 case 'E':
8225 {
8226 add(current);
8227 goto scan_number_exponent;
8228 }
8229
8230 default:
8231 goto scan_number_done;
8232 }
8233
8234scan_number_exponent:
8235 // we just parsed an exponent
8236 number_type = token_type::value_float;
8237 switch (get())
8238 {
8239 case '+':
8240 case '-':
8241 {
8242 add(current);
8243 goto scan_number_sign;
8244 }
8245
8246 case '0':
8247 case '1':
8248 case '2':
8249 case '3':
8250 case '4':
8251 case '5':
8252 case '6':
8253 case '7':
8254 case '8':
8255 case '9':
8256 {
8257 add(current);
8258 goto scan_number_any2;
8259 }
8260
8261 default:
8262 {
8263 error_message =
8264 "invalid number; expected '+', '-', or digit after exponent";
8265 return token_type::parse_error;
8266 }
8267 }
8268
8269scan_number_sign:
8270 // we just parsed an exponent sign
8271 switch (get())
8272 {
8273 case '0':
8274 case '1':
8275 case '2':
8276 case '3':
8277 case '4':
8278 case '5':
8279 case '6':
8280 case '7':
8281 case '8':
8282 case '9':
8283 {
8284 add(current);
8285 goto scan_number_any2;
8286 }
8287
8288 default:
8289 {
8290 error_message = "invalid number; expected digit after exponent sign";
8291 return token_type::parse_error;
8292 }
8293 }
8294
8295scan_number_any2:
8296 // we just parsed a number after the exponent or exponent sign
8297 switch (get())
8298 {
8299 case '0':
8300 case '1':
8301 case '2':
8302 case '3':
8303 case '4':
8304 case '5':
8305 case '6':
8306 case '7':
8307 case '8':
8308 case '9':
8309 {
8310 add(current);
8311 goto scan_number_any2;
8312 }
8313
8314 default:
8315 goto scan_number_done;
8316 }
8317
8318scan_number_done:
8319 // unget the character after the number (we only read it to know that
8320 // we are done scanning a number)
8321 unget();
8322
8323 char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8324 errno = 0;
8325
8326 // try to parse integers first and fall back to floats
8327 if (number_type == token_type::value_unsigned)
8328 {
8329 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8330
8331 // we checked the number format before
8332 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8333
8334 if (errno != ERANGE)
8335 {
8336 value_unsigned = static_cast<number_unsigned_t>(x);
8337 if (value_unsigned == x)
8338 {
8339 return token_type::value_unsigned;
8340 }
8341 }
8342 }
8343 else if (number_type == token_type::value_integer)
8344 {
8345 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8346
8347 // we checked the number format before
8348 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8349
8350 if (errno != ERANGE)
8351 {
8352 value_integer = static_cast<number_integer_t>(x);
8353 if (value_integer == x)
8354 {
8355 return token_type::value_integer;
8356 }
8357 }
8358 }
8359
8360 // this code is reached if we parse a floating-point number or if an
8361 // integer conversion above failed
8362 strtof(value_float, token_buffer.data(), &endptr);
8363
8364 // we checked the number format before
8365 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8366
8367 return token_type::value_float;
8368 }
8369
8375 JSON_HEDLEY_NON_NULL(2)
8376 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8377 token_type return_type)
8378 {
8379 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8380 for (std::size_t i = 1; i < length; ++i)
8381 {
8382 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8383 {
8384 error_message = "invalid literal";
8385 return token_type::parse_error;
8386 }
8387 }
8388 return return_type;
8389 }
8390
8392 // input management
8394
8396 void reset() noexcept
8397 {
8398 token_buffer.clear();
8399 token_string.clear();
8400 decimal_point_position = std::string::npos;
8401 token_string.push_back(char_traits<char_type>::to_char_type(current));
8402 }
8403
8404 /*
8405 @brief get next character from the input
8406
8407 This function provides the interface to the used input adapter. It does
8408 not throw in case the input reached EOF, but returns a
8409 `char_traits<char>::eof()` in that case. Stores the scanned characters
8410 for use in error messages.
8411
8412 @return character read from the input
8413 */
8414 char_int_type get()
8415 {
8416 ++position.chars_read_total;
8417 ++position.chars_read_current_line;
8418
8419 if (next_unget)
8420 {
8421 // only reset the next_unget variable and work with current
8422 next_unget = false;
8423 }
8424 else
8425 {
8426 current = ia.get_character();
8427 }
8428
8429 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8430 {
8431 token_string.push_back(char_traits<char_type>::to_char_type(current));
8432 }
8433
8434 if (current == '\n')
8435 {
8436 ++position.lines_read;
8437 position.chars_read_current_line = 0;
8438 }
8439
8440 return current;
8441 }
8442
8451 void unget()
8452 {
8453 next_unget = true;
8454
8455 --position.chars_read_total;
8456
8457 // in case we "unget" a newline, we have to also decrement the lines_read
8458 if (position.chars_read_current_line == 0)
8459 {
8460 if (position.lines_read > 0)
8461 {
8462 --position.lines_read;
8463 }
8464 }
8465 else
8466 {
8467 --position.chars_read_current_line;
8468 }
8469
8470 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8471 {
8472 JSON_ASSERT(!token_string.empty());
8473 token_string.pop_back();
8474 }
8475 }
8476
8478 void add(char_int_type c)
8479 {
8480 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8481 }
8482
8483 public:
8485 // value getters
8487
8489 constexpr number_integer_t get_number_integer() const noexcept
8490 {
8491 return value_integer;
8492 }
8493
8495 constexpr number_unsigned_t get_number_unsigned() const noexcept
8496 {
8497 return value_unsigned;
8498 }
8499
8501 constexpr number_float_t get_number_float() const noexcept
8502 {
8503 return value_float;
8504 }
8505
8507 string_t& get_string()
8508 {
8509 // translate decimal points from locale back to '.' (#4084)
8510 if (decimal_point_char != '.' && decimal_point_position != std::string::npos)
8511 {
8512 token_buffer[decimal_point_position] = '.';
8513 }
8514 return token_buffer;
8515 }
8516
8518 // diagnostics
8520
8522 constexpr position_t get_position() const noexcept
8523 {
8524 return position;
8525 }
8526
8530 std::string get_token_string() const
8531 {
8532 // escape control characters
8533 std::string result;
8534 for (const auto c : token_string)
8535 {
8536 if (static_cast<unsigned char>(c) <= '\x1F')
8537 {
8538 // escape control characters
8539 std::array<char, 9> cs{{}};
8540 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8541 result += cs.data();
8542 }
8543 else
8544 {
8545 // add character as is
8546 result.push_back(static_cast<std::string::value_type>(c));
8547 }
8548 }
8549
8550 return result;
8551 }
8552
8554 JSON_HEDLEY_RETURNS_NON_NULL
8555 constexpr const char* get_error_message() const noexcept
8556 {
8557 return error_message;
8558 }
8559
8561 // actual scanner
8563
8568 bool skip_bom()
8569 {
8570 if (get() == 0xEF)
8571 {
8572 // check if we completely parse the BOM
8573 return get() == 0xBB && get() == 0xBF;
8574 }
8575
8576 // the first character is not the beginning of the BOM; unget it to
8577 // process is later
8578 unget();
8579 return true;
8580 }
8581
8582 void skip_whitespace()
8583 {
8584 do
8585 {
8586 get();
8587 }
8588 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8589 }
8590
8591 token_type scan()
8592 {
8593 // initially, skip the BOM
8594 if (position.chars_read_total == 0 && !skip_bom())
8595 {
8596 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8597 return token_type::parse_error;
8598 }
8599
8600 // read the next character and ignore whitespace
8601 skip_whitespace();
8602
8603 // ignore comments
8604 while (ignore_comments && current == '/')
8605 {
8606 if (!scan_comment())
8607 {
8608 return token_type::parse_error;
8609 }
8610
8611 // skip following whitespace
8612 skip_whitespace();
8613 }
8614
8615 switch (current)
8616 {
8617 // structural characters
8618 case '[':
8619 return token_type::begin_array;
8620 case ']':
8621 return token_type::end_array;
8622 case '{':
8623 return token_type::begin_object;
8624 case '}':
8625 return token_type::end_object;
8626 case ':':
8627 return token_type::name_separator;
8628 case ',':
8629 return token_type::value_separator;
8630
8631 // literals
8632 case 't':
8633 {
8634 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')}};
8635 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8636 }
8637 case 'f':
8638 {
8639 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')}};
8640 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8641 }
8642 case 'n':
8643 {
8644 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')}};
8645 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8646 }
8647
8648 // string
8649 case '\"':
8650 return scan_string();
8651
8652 // number
8653 case '-':
8654 case '0':
8655 case '1':
8656 case '2':
8657 case '3':
8658 case '4':
8659 case '5':
8660 case '6':
8661 case '7':
8662 case '8':
8663 case '9':
8664 return scan_number();
8665
8666 // end of input (the null byte is needed when parsing from
8667 // string literals)
8668 case '\0':
8669 case char_traits<char_type>::eof():
8670 return token_type::end_of_input;
8671
8672 // error
8673 default:
8674 error_message = "invalid literal";
8675 return token_type::parse_error;
8676 }
8677 }
8678
8679 private:
8681 InputAdapterType ia;
8682
8684 const bool ignore_comments = false;
8685
8687 char_int_type current = char_traits<char_type>::eof();
8688
8690 bool next_unget = false;
8691
8693 position_t position {};
8694
8696 std::vector<char_type> token_string {};
8697
8699 string_t token_buffer {};
8700
8702 const char* error_message = "";
8703
8704 // number values
8705 number_integer_t value_integer = 0;
8706 number_unsigned_t value_unsigned = 0;
8707 number_float_t value_float = 0;
8708
8710 const char_int_type decimal_point_char = '.';
8712 std::size_t decimal_point_position = std::string::npos;
8713};
8714
8715} // namespace detail
8716NLOHMANN_JSON_NAMESPACE_END
8717
8718// #include <nlohmann/detail/macro_scope.hpp>
8719
8720// #include <nlohmann/detail/string_concat.hpp>
8721
8722NLOHMANN_JSON_NAMESPACE_BEGIN
8723
8732template<typename BasicJsonType>
8734{
8735 using number_integer_t = typename BasicJsonType::number_integer_t;
8736 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8737 using number_float_t = typename BasicJsonType::number_float_t;
8738 using string_t = typename BasicJsonType::string_t;
8739 using binary_t = typename BasicJsonType::binary_t;
8740
8745 virtual bool null() = 0;
8746
8752 virtual bool boolean(bool val) = 0;
8753
8759 virtual bool number_integer(number_integer_t val) = 0;
8760
8766 virtual bool number_unsigned(number_unsigned_t val) = 0;
8767
8774 virtual bool number_float(number_float_t val, const string_t& s) = 0;
8775
8782 virtual bool string(string_t& val) = 0;
8783
8790 virtual bool binary(binary_t& val) = 0;
8791
8798 virtual bool start_object(std::size_t elements) = 0;
8799
8806 virtual bool key(string_t& val) = 0;
8807
8812 virtual bool end_object() = 0;
8813
8820 virtual bool start_array(std::size_t elements) = 0;
8821
8826 virtual bool end_array() = 0;
8827
8835 virtual bool parse_error(std::size_t position,
8836 const std::string& last_token,
8837 const detail::exception& ex) = 0;
8838
8839 json_sax() = default;
8840 json_sax(const json_sax&) = default;
8841 json_sax(json_sax&&) noexcept = default;
8842 json_sax& operator=(const json_sax&) = default;
8843 json_sax& operator=(json_sax&&) noexcept = default;
8844 virtual ~json_sax() = default;
8845};
8846
8847namespace detail
8848{
8849constexpr std::size_t unknown_size()
8850{
8851 return (std::numeric_limits<std::size_t>::max)();
8852}
8853
8867template<typename BasicJsonType, typename InputAdapterType>
8869{
8870 public:
8871 using number_integer_t = typename BasicJsonType::number_integer_t;
8872 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8873 using number_float_t = typename BasicJsonType::number_float_t;
8874 using string_t = typename BasicJsonType::string_t;
8875 using binary_t = typename BasicJsonType::binary_t;
8876 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
8877
8883 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr)
8884 : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
8885 {}
8886
8887 // make class move-only
8889 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8890 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
8891 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8892 ~json_sax_dom_parser() = default;
8893
8894 bool null()
8895 {
8896 handle_value(nullptr);
8897 return true;
8898 }
8899
8900 bool boolean(bool val)
8901 {
8902 handle_value(val);
8903 return true;
8904 }
8905
8906 bool number_integer(number_integer_t val)
8907 {
8908 handle_value(val);
8909 return true;
8910 }
8911
8912 bool number_unsigned(number_unsigned_t val)
8913 {
8914 handle_value(val);
8915 return true;
8916 }
8917
8918 bool number_float(number_float_t val, const string_t& /*unused*/)
8919 {
8920 handle_value(val);
8921 return true;
8922 }
8923
8924 bool string(string_t& val)
8925 {
8926 handle_value(val);
8927 return true;
8928 }
8929
8930 bool binary(binary_t& val)
8931 {
8932 handle_value(std::move(val));
8933 return true;
8934 }
8935
8936 bool start_object(std::size_t len)
8937 {
8938 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
8939
8940#if JSON_DIAGNOSTIC_POSITIONS
8941 // Manually set the start position of the object here.
8942 // Ensure this is after the call to handle_value to ensure correct start position.
8943 if (m_lexer_ref)
8944 {
8945 // Lexer has read the first character of the object, so
8946 // subtract 1 from the position to get the correct start position.
8947 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8948 }
8949#endif
8950
8951 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
8952 {
8953 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
8954 }
8955
8956 return true;
8957 }
8958
8959 bool key(string_t& val)
8960 {
8961 JSON_ASSERT(!ref_stack.empty());
8962 JSON_ASSERT(ref_stack.back()->is_object());
8963
8964 // add null at the given key and store the reference for later
8965 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
8966 return true;
8967 }
8968
8969 bool end_object()
8970 {
8971 JSON_ASSERT(!ref_stack.empty());
8972 JSON_ASSERT(ref_stack.back()->is_object());
8973
8974#if JSON_DIAGNOSTIC_POSITIONS
8975 if (m_lexer_ref)
8976 {
8977 // Lexer's position is past the closing brace, so set that as the end position.
8978 ref_stack.back()->end_position = m_lexer_ref->get_position();
8979 }
8980#endif
8981
8982 ref_stack.back()->set_parents();
8983 ref_stack.pop_back();
8984 return true;
8985 }
8986
8987 bool start_array(std::size_t len)
8988 {
8989 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
8990
8991#if JSON_DIAGNOSTIC_POSITIONS
8992 // Manually set the start position of the array here.
8993 // Ensure this is after the call to handle_value to ensure correct start position.
8994 if (m_lexer_ref)
8995 {
8996 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8997 }
8998#endif
8999
9000 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9001 {
9002 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
9003 }
9004
9005 return true;
9006 }
9007
9008 bool end_array()
9009 {
9010 JSON_ASSERT(!ref_stack.empty());
9011 JSON_ASSERT(ref_stack.back()->is_array());
9012
9013#if JSON_DIAGNOSTIC_POSITIONS
9014 if (m_lexer_ref)
9015 {
9016 // Lexer's position is past the closing bracket, so set that as the end position.
9017 ref_stack.back()->end_position = m_lexer_ref->get_position();
9018 }
9019#endif
9020
9021 ref_stack.back()->set_parents();
9022 ref_stack.pop_back();
9023 return true;
9024 }
9025
9026 template<class Exception>
9027 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9028 const Exception& ex)
9029 {
9030 errored = true;
9031 static_cast<void>(ex);
9032 if (allow_exceptions)
9033 {
9034 JSON_THROW(ex);
9035 }
9036 return false;
9037 }
9038
9039 constexpr bool is_errored() const
9040 {
9041 return errored;
9042 }
9043
9044 private:
9045
9046#if JSON_DIAGNOSTIC_POSITIONS
9047 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9048 {
9049 if (m_lexer_ref)
9050 {
9051 // Lexer has read past the current field value, so set the end position to the current position.
9052 // The start position will be set below based on the length of the string representation
9053 // of the value.
9054 v.end_position = m_lexer_ref->get_position();
9055
9056 switch (v.type())
9057 {
9058 case value_t::boolean:
9059 {
9060 // 4 and 5 are the string length of "true" and "false"
9061 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9062 break;
9063 }
9064
9065 case value_t::null:
9066 {
9067 // 4 is the string length of "null"
9068 v.start_position = v.end_position - 4;
9069 break;
9070 }
9071
9072 case value_t::string:
9073 {
9074 // include the length of the quotes, which is 2
9075 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9076 break;
9077 }
9078
9079 // As we handle the start and end positions for values created during parsing,
9080 // we do not expect the following value type to be called. Regardless, set the positions
9081 // in case this is created manually or through a different constructor. Exclude from lcov
9082 // since the exact condition of this switch is esoteric.
9083 // LCOV_EXCL_START
9084 case value_t::discarded:
9085 {
9086 v.end_position = std::string::npos;
9087 v.start_position = v.end_position;
9088 break;
9089 }
9090 // LCOV_EXCL_STOP
9091 case value_t::binary:
9092 case value_t::number_integer:
9093 case value_t::number_unsigned:
9094 case value_t::number_float:
9095 {
9096 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9097 break;
9098 }
9099 case value_t::object:
9100 case value_t::array:
9101 {
9102 // object and array are handled in start_object() and start_array() handlers
9103 // skip setting the values here.
9104 break;
9105 }
9106 default: // LCOV_EXCL_LINE
9107 // Handle all possible types discretely, default handler should never be reached.
9108 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9109 }
9110 }
9111 }
9112#endif
9113
9120 template<typename Value>
9121 JSON_HEDLEY_RETURNS_NON_NULL
9122 BasicJsonType* handle_value(Value&& v)
9123 {
9124 if (ref_stack.empty())
9125 {
9126 root = BasicJsonType(std::forward<Value>(v));
9127
9128#if JSON_DIAGNOSTIC_POSITIONS
9129 handle_diagnostic_positions_for_json_value(root);
9130#endif
9131
9132 return &root;
9133 }
9134
9135 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9136
9137 if (ref_stack.back()->is_array())
9138 {
9139 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
9140
9141#if JSON_DIAGNOSTIC_POSITIONS
9142 handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back());
9143#endif
9144
9145 return &(ref_stack.back()->m_data.m_value.array->back());
9146 }
9147
9148 JSON_ASSERT(ref_stack.back()->is_object());
9149 JSON_ASSERT(object_element);
9150 *object_element = BasicJsonType(std::forward<Value>(v));
9151
9152#if JSON_DIAGNOSTIC_POSITIONS
9153 handle_diagnostic_positions_for_json_value(*object_element);
9154#endif
9155
9156 return object_element;
9157 }
9158
9160 BasicJsonType& root;
9162 std::vector<BasicJsonType*> ref_stack {};
9164 BasicJsonType* object_element = nullptr;
9166 bool errored = false;
9168 const bool allow_exceptions = true;
9170 lexer_t* m_lexer_ref = nullptr;
9171};
9172
9173template<typename BasicJsonType, typename InputAdapterType>
9175{
9176 public:
9177 using number_integer_t = typename BasicJsonType::number_integer_t;
9178 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9179 using number_float_t = typename BasicJsonType::number_float_t;
9180 using string_t = typename BasicJsonType::string_t;
9181 using binary_t = typename BasicJsonType::binary_t;
9182 using parser_callback_t = typename BasicJsonType::parser_callback_t;
9183 using parse_event_t = typename BasicJsonType::parse_event_t;
9184 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
9185
9186 json_sax_dom_callback_parser(BasicJsonType& r,
9187 parser_callback_t cb,
9188 const bool allow_exceptions_ = true,
9189 lexer_t* lexer_ = nullptr)
9190 : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
9191 {
9192 keep_stack.push_back(true);
9193 }
9194
9195 // make class move-only
9197 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9199 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9201
9202 bool null()
9203 {
9204 handle_value(nullptr);
9205 return true;
9206 }
9207
9208 bool boolean(bool val)
9209 {
9210 handle_value(val);
9211 return true;
9212 }
9213
9214 bool number_integer(number_integer_t val)
9215 {
9216 handle_value(val);
9217 return true;
9218 }
9219
9220 bool number_unsigned(number_unsigned_t val)
9221 {
9222 handle_value(val);
9223 return true;
9224 }
9225
9226 bool number_float(number_float_t val, const string_t& /*unused*/)
9227 {
9228 handle_value(val);
9229 return true;
9230 }
9231
9232 bool string(string_t& val)
9233 {
9234 handle_value(val);
9235 return true;
9236 }
9237
9238 bool binary(binary_t& val)
9239 {
9240 handle_value(std::move(val));
9241 return true;
9242 }
9243
9244 bool start_object(std::size_t len)
9245 {
9246 // check callback for object start
9247 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
9248 keep_stack.push_back(keep);
9249
9250 auto val = handle_value(BasicJsonType::value_t::object, true);
9251 ref_stack.push_back(val.second);
9252
9253 if (ref_stack.back())
9254 {
9255
9256#if JSON_DIAGNOSTIC_POSITIONS
9257 // Manually set the start position of the object here.
9258 // Ensure this is after the call to handle_value to ensure correct start position.
9259 if (m_lexer_ref)
9260 {
9261 // Lexer has read the first character of the object, so
9262 // subtract 1 from the position to get the correct start position.
9263 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9264 }
9265#endif
9266
9267 // check object limit
9268 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9269 {
9270 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
9271 }
9272 }
9273 return true;
9274 }
9275
9276 bool key(string_t& val)
9277 {
9278 BasicJsonType k = BasicJsonType(val);
9279
9280 // check callback for the key
9281 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
9282 key_keep_stack.push_back(keep);
9283
9284 // add discarded value at the given key and store the reference for later
9285 if (keep && ref_stack.back())
9286 {
9287 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
9288 }
9289
9290 return true;
9291 }
9292
9293 bool end_object()
9294 {
9295 if (ref_stack.back())
9296 {
9297 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
9298 {
9299 // discard object
9300 *ref_stack.back() = discarded;
9301
9302#if JSON_DIAGNOSTIC_POSITIONS
9303 // Set start/end positions for discarded object.
9304 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9305#endif
9306 }
9307 else
9308 {
9309
9310#if JSON_DIAGNOSTIC_POSITIONS
9311 if (m_lexer_ref)
9312 {
9313 // Lexer's position is past the closing brace, so set that as the end position.
9314 ref_stack.back()->end_position = m_lexer_ref->get_position();
9315 }
9316#endif
9317
9318 ref_stack.back()->set_parents();
9319 }
9320 }
9321
9322 JSON_ASSERT(!ref_stack.empty());
9323 JSON_ASSERT(!keep_stack.empty());
9324 ref_stack.pop_back();
9325 keep_stack.pop_back();
9326
9327 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
9328 {
9329 // remove discarded value
9330 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
9331 {
9332 if (it->is_discarded())
9333 {
9334 ref_stack.back()->erase(it);
9335 break;
9336 }
9337 }
9338 }
9339
9340 return true;
9341 }
9342
9343 bool start_array(std::size_t len)
9344 {
9345 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
9346 keep_stack.push_back(keep);
9347
9348 auto val = handle_value(BasicJsonType::value_t::array, true);
9349 ref_stack.push_back(val.second);
9350
9351 if (ref_stack.back())
9352 {
9353
9354#if JSON_DIAGNOSTIC_POSITIONS
9355 // Manually set the start position of the array here.
9356 // Ensure this is after the call to handle_value to ensure correct start position.
9357 if (m_lexer_ref)
9358 {
9359 // Lexer has read the first character of the array, so
9360 // subtract 1 from the position to get the correct start position.
9361 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9362 }
9363#endif
9364
9365 // check array limit
9366 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9367 {
9368 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
9369 }
9370 }
9371
9372 return true;
9373 }
9374
9375 bool end_array()
9376 {
9377 bool keep = true;
9378
9379 if (ref_stack.back())
9380 {
9381 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
9382 if (keep)
9383 {
9384
9385#if JSON_DIAGNOSTIC_POSITIONS
9386 if (m_lexer_ref)
9387 {
9388 // Lexer's position is past the closing bracket, so set that as the end position.
9389 ref_stack.back()->end_position = m_lexer_ref->get_position();
9390 }
9391#endif
9392
9393 ref_stack.back()->set_parents();
9394 }
9395 else
9396 {
9397 // discard array
9398 *ref_stack.back() = discarded;
9399
9400#if JSON_DIAGNOSTIC_POSITIONS
9401 // Set start/end positions for discarded array.
9402 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9403#endif
9404 }
9405 }
9406
9407 JSON_ASSERT(!ref_stack.empty());
9408 JSON_ASSERT(!keep_stack.empty());
9409 ref_stack.pop_back();
9410 keep_stack.pop_back();
9411
9412 // remove discarded value
9413 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
9414 {
9415 ref_stack.back()->m_data.m_value.array->pop_back();
9416 }
9417
9418 return true;
9419 }
9420
9421 template<class Exception>
9422 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9423 const Exception& ex)
9424 {
9425 errored = true;
9426 static_cast<void>(ex);
9427 if (allow_exceptions)
9428 {
9429 JSON_THROW(ex);
9430 }
9431 return false;
9432 }
9433
9434 constexpr bool is_errored() const
9435 {
9436 return errored;
9437 }
9438
9439 private:
9440
9441#if JSON_DIAGNOSTIC_POSITIONS
9442 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9443 {
9444 if (m_lexer_ref)
9445 {
9446 // Lexer has read past the current field value, so set the end position to the current position.
9447 // The start position will be set below based on the length of the string representation
9448 // of the value.
9449 v.end_position = m_lexer_ref->get_position();
9450
9451 switch (v.type())
9452 {
9453 case value_t::boolean:
9454 {
9455 // 4 and 5 are the string length of "true" and "false"
9456 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9457 break;
9458 }
9459
9460 case value_t::null:
9461 {
9462 // 4 is the string length of "null"
9463 v.start_position = v.end_position - 4;
9464 break;
9465 }
9466
9467 case value_t::string:
9468 {
9469 // include the length of the quotes, which is 2
9470 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9471 break;
9472 }
9473
9474 case value_t::discarded:
9475 {
9476 v.end_position = std::string::npos;
9477 v.start_position = v.end_position;
9478 break;
9479 }
9480
9481 case value_t::binary:
9482 case value_t::number_integer:
9483 case value_t::number_unsigned:
9484 case value_t::number_float:
9485 {
9486 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9487 break;
9488 }
9489
9490 case value_t::object:
9491 case value_t::array:
9492 {
9493 // object and array are handled in start_object() and start_array() handlers
9494 // skip setting the values here.
9495 break;
9496 }
9497 default: // LCOV_EXCL_LINE
9498 // Handle all possible types discretely, default handler should never be reached.
9499 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9500 }
9501 }
9502 }
9503#endif
9504
9520 template<typename Value>
9521 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
9522 {
9523 JSON_ASSERT(!keep_stack.empty());
9524
9525 // do not handle this value if we know it would be added to a discarded
9526 // container
9527 if (!keep_stack.back())
9528 {
9529 return {false, nullptr};
9530 }
9531
9532 // create value
9533 auto value = BasicJsonType(std::forward<Value>(v));
9534
9535#if JSON_DIAGNOSTIC_POSITIONS
9536 handle_diagnostic_positions_for_json_value(value);
9537#endif
9538
9539 // check callback
9540 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
9541
9542 // do not handle this value if we just learnt it shall be discarded
9543 if (!keep)
9544 {
9545 return {false, nullptr};
9546 }
9547
9548 if (ref_stack.empty())
9549 {
9550 root = std::move(value);
9551 return {true, & root};
9552 }
9553
9554 // skip this value if we already decided to skip the parent
9555 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
9556 if (!ref_stack.back())
9557 {
9558 return {false, nullptr};
9559 }
9560
9561 // we now only expect arrays and objects
9562 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9563
9564 // array
9565 if (ref_stack.back()->is_array())
9566 {
9567 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
9568 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
9569 }
9570
9571 // object
9572 JSON_ASSERT(ref_stack.back()->is_object());
9573 // check if we should store an element for the current key
9574 JSON_ASSERT(!key_keep_stack.empty());
9575 const bool store_element = key_keep_stack.back();
9576 key_keep_stack.pop_back();
9577
9578 if (!store_element)
9579 {
9580 return {false, nullptr};
9581 }
9582
9583 JSON_ASSERT(object_element);
9584 *object_element = std::move(value);
9585 return {true, object_element};
9586 }
9587
9589 BasicJsonType& root;
9591 std::vector<BasicJsonType*> ref_stack {};
9593 std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
9595 std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
9597 BasicJsonType* object_element = nullptr;
9599 bool errored = false;
9601 const parser_callback_t callback = nullptr;
9603 const bool allow_exceptions = true;
9605 BasicJsonType discarded = BasicJsonType::value_t::discarded;
9607 lexer_t* m_lexer_ref = nullptr;
9608};
9609
9610template<typename BasicJsonType>
9612{
9613 public:
9614 using number_integer_t = typename BasicJsonType::number_integer_t;
9615 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9616 using number_float_t = typename BasicJsonType::number_float_t;
9617 using string_t = typename BasicJsonType::string_t;
9618 using binary_t = typename BasicJsonType::binary_t;
9619
9620 bool null()
9621 {
9622 return true;
9623 }
9624
9625 bool boolean(bool /*unused*/)
9626 {
9627 return true;
9628 }
9629
9630 bool number_integer(number_integer_t /*unused*/)
9631 {
9632 return true;
9633 }
9634
9635 bool number_unsigned(number_unsigned_t /*unused*/)
9636 {
9637 return true;
9638 }
9639
9640 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
9641 {
9642 return true;
9643 }
9644
9645 bool string(string_t& /*unused*/)
9646 {
9647 return true;
9648 }
9649
9650 bool binary(binary_t& /*unused*/)
9651 {
9652 return true;
9653 }
9654
9655 bool start_object(std::size_t /*unused*/ = detail::unknown_size())
9656 {
9657 return true;
9658 }
9659
9660 bool key(string_t& /*unused*/)
9661 {
9662 return true;
9663 }
9664
9665 bool end_object()
9666 {
9667 return true;
9668 }
9669
9670 bool start_array(std::size_t /*unused*/ = detail::unknown_size())
9671 {
9672 return true;
9673 }
9674
9675 bool end_array()
9676 {
9677 return true;
9678 }
9679
9680 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
9681 {
9682 return false;
9683 }
9684};
9685
9686} // namespace detail
9687NLOHMANN_JSON_NAMESPACE_END
9688
9689// #include <nlohmann/detail/input/lexer.hpp>
9690
9691// #include <nlohmann/detail/macro_scope.hpp>
9692
9693// #include <nlohmann/detail/meta/is_sax.hpp>
9694// __ _____ _____ _____
9695// __| | __| | | | JSON for Modern C++
9696// | | |__ | | | | | | version 3.12.0
9697// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9698//
9699// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
9700// SPDX-License-Identifier: MIT
9701
9702
9703
9704#include <cstdint> // size_t
9705#include <utility> // declval
9706#include <string> // string
9707
9708// #include <nlohmann/detail/abi_macros.hpp>
9709
9710// #include <nlohmann/detail/meta/detected.hpp>
9711
9712// #include <nlohmann/detail/meta/type_traits.hpp>
9713
9714
9715NLOHMANN_JSON_NAMESPACE_BEGIN
9716namespace detail
9717{
9718
9719template<typename T>
9720using null_function_t = decltype(std::declval<T&>().null());
9721
9722template<typename T>
9723using boolean_function_t =
9724 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9725
9726template<typename T, typename Integer>
9727using number_integer_function_t =
9728 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9729
9730template<typename T, typename Unsigned>
9731using number_unsigned_function_t =
9732 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9733
9734template<typename T, typename Float, typename String>
9735using number_float_function_t = decltype(std::declval<T&>().number_float(
9736 std::declval<Float>(), std::declval<const String&>()));
9737
9738template<typename T, typename String>
9739using string_function_t =
9740 decltype(std::declval<T&>().string(std::declval<String&>()));
9741
9742template<typename T, typename Binary>
9743using binary_function_t =
9744 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9745
9746template<typename T>
9747using start_object_function_t =
9748 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9749
9750template<typename T, typename String>
9751using key_function_t =
9752 decltype(std::declval<T&>().key(std::declval<String&>()));
9753
9754template<typename T>
9755using end_object_function_t = decltype(std::declval<T&>().end_object());
9756
9757template<typename T>
9758using start_array_function_t =
9759 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9760
9761template<typename T>
9762using end_array_function_t = decltype(std::declval<T&>().end_array());
9763
9764template<typename T, typename Exception>
9765using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9766 std::declval<std::size_t>(), std::declval<const std::string&>(),
9767 std::declval<const Exception&>()));
9768
9769template<typename SAX, typename BasicJsonType>
9771{
9772 private:
9774 "BasicJsonType must be of type basic_json<...>");
9775
9776 using number_integer_t = typename BasicJsonType::number_integer_t;
9777 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9778 using number_float_t = typename BasicJsonType::number_float_t;
9779 using string_t = typename BasicJsonType::string_t;
9780 using binary_t = typename BasicJsonType::binary_t;
9781 using exception_t = typename BasicJsonType::exception;
9782
9783 public:
9784 static constexpr bool value =
9785 is_detected_exact<bool, null_function_t, SAX>::value &&
9786 is_detected_exact<bool, boolean_function_t, SAX>::value &&
9787 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
9788 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
9789 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
9790 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
9791 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
9792 is_detected_exact<bool, start_object_function_t, SAX>::value &&
9793 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
9794 is_detected_exact<bool, end_object_function_t, SAX>::value &&
9795 is_detected_exact<bool, start_array_function_t, SAX>::value &&
9796 is_detected_exact<bool, end_array_function_t, SAX>::value &&
9797 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
9798};
9799
9800template<typename SAX, typename BasicJsonType>
9802{
9803 private:
9805 "BasicJsonType must be of type basic_json<...>");
9806
9807 using number_integer_t = typename BasicJsonType::number_integer_t;
9808 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9809 using number_float_t = typename BasicJsonType::number_float_t;
9810 using string_t = typename BasicJsonType::string_t;
9811 using binary_t = typename BasicJsonType::binary_t;
9812 using exception_t = typename BasicJsonType::exception;
9813
9814 public:
9815 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
9816 "Missing/invalid function: bool null()");
9817 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9818 "Missing/invalid function: bool boolean(bool)");
9819 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9820 "Missing/invalid function: bool boolean(bool)");
9821 static_assert(
9822 is_detected_exact<bool, number_integer_function_t, SAX,
9823 number_integer_t>::value,
9824 "Missing/invalid function: bool number_integer(number_integer_t)");
9825 static_assert(
9826 is_detected_exact<bool, number_unsigned_function_t, SAX,
9827 number_unsigned_t>::value,
9828 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9829 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9830 number_float_t, string_t>::value,
9831 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9832 static_assert(
9833 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
9834 "Missing/invalid function: bool string(string_t&)");
9835 static_assert(
9836 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
9837 "Missing/invalid function: bool binary(binary_t&)");
9838 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
9839 "Missing/invalid function: bool start_object(std::size_t)");
9840 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
9841 "Missing/invalid function: bool key(string_t&)");
9842 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
9843 "Missing/invalid function: bool end_object()");
9844 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
9845 "Missing/invalid function: bool start_array(std::size_t)");
9846 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
9847 "Missing/invalid function: bool end_array()");
9848 static_assert(
9849 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
9850 "Missing/invalid function: bool parse_error(std::size_t, const "
9851 "std::string&, const exception&)");
9852};
9853
9854} // namespace detail
9855NLOHMANN_JSON_NAMESPACE_END
9856
9857// #include <nlohmann/detail/meta/type_traits.hpp>
9858
9859// #include <nlohmann/detail/string_concat.hpp>
9860
9861// #include <nlohmann/detail/value_t.hpp>
9862
9863
9864NLOHMANN_JSON_NAMESPACE_BEGIN
9865namespace detail
9866{
9867
9870{
9871 error,
9872 ignore,
9873 store
9874};
9875
9883inline bool little_endianness(int num = 1) noexcept
9884{
9885 return *reinterpret_cast<char*>(&num) == 1;
9886}
9887
9889// binary reader //
9891
9895template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType, InputAdapterType>>
9897{
9898 using number_integer_t = typename BasicJsonType::number_integer_t;
9899 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9900 using number_float_t = typename BasicJsonType::number_float_t;
9901 using string_t = typename BasicJsonType::string_t;
9902 using binary_t = typename BasicJsonType::binary_t;
9903 using json_sax_t = SAX;
9904 using char_type = typename InputAdapterType::char_type;
9905 using char_int_type = typename char_traits<char_type>::int_type;
9906
9907 public:
9913 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9914 {
9916 }
9917
9918 // make class move-only
9919 binary_reader(const binary_reader&) = delete;
9920 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9921 binary_reader& operator=(const binary_reader&) = delete;
9922 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9923 ~binary_reader() = default;
9924
9933 JSON_HEDLEY_NON_NULL(3)
9934 bool sax_parse(const input_format_t format,
9935 json_sax_t* sax_,
9936 const bool strict = true,
9937 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9938 {
9939 sax = sax_;
9940 bool result = false;
9941
9942 switch (format)
9943 {
9944 case input_format_t::bson:
9945 result = parse_bson_internal();
9946 break;
9947
9948 case input_format_t::cbor:
9949 result = parse_cbor_internal(true, tag_handler);
9950 break;
9951
9952 case input_format_t::msgpack:
9953 result = parse_msgpack_internal();
9954 break;
9955
9956 case input_format_t::ubjson:
9957 case input_format_t::bjdata:
9958 result = parse_ubjson_internal();
9959 break;
9960
9961 case input_format_t::json: // LCOV_EXCL_LINE
9962 default: // LCOV_EXCL_LINE
9963 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9964 }
9965
9966 // strict mode: next byte must be EOF
9967 if (result && strict)
9968 {
9969 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9970 {
9971 get_ignore_noop();
9972 }
9973 else
9974 {
9975 get();
9976 }
9977
9978 if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
9979 {
9980 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9981 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9982 }
9983 }
9984
9985 return result;
9986 }
9987
9988 private:
9990 // BSON //
9992
9997 bool parse_bson_internal()
9998 {
9999 std::int32_t document_size{};
10000 get_number<std::int32_t, true>(input_format_t::bson, document_size);
10001
10002 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
10003 {
10004 return false;
10005 }
10006
10007 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
10008 {
10009 return false;
10010 }
10011
10012 return sax->end_object();
10013 }
10014
10022 bool get_bson_cstr(string_t& result)
10023 {
10024 auto out = std::back_inserter(result);
10025 while (true)
10026 {
10027 get();
10028 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
10029 {
10030 return false;
10031 }
10032 if (current == 0x00)
10033 {
10034 return true;
10035 }
10036 *out++ = static_cast<typename string_t::value_type>(current);
10037 }
10038 }
10039
10051 template<typename NumberType>
10052 bool get_bson_string(const NumberType len, string_t& result)
10053 {
10054 if (JSON_HEDLEY_UNLIKELY(len < 1))
10055 {
10056 auto last_token = get_token_string();
10057 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10058 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
10059 }
10060
10061 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
10062 }
10063
10073 template<typename NumberType>
10074 bool get_bson_binary(const NumberType len, binary_t& result)
10075 {
10076 if (JSON_HEDLEY_UNLIKELY(len < 0))
10077 {
10078 auto last_token = get_token_string();
10079 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10080 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
10081 }
10082
10083 // All BSON binary values have a subtype
10084 std::uint8_t subtype{};
10085 get_number<std::uint8_t>(input_format_t::bson, subtype);
10086 result.set_subtype(subtype);
10087
10088 return get_binary(input_format_t::bson, len, result);
10089 }
10090
10101 bool parse_bson_element_internal(const char_int_type element_type,
10102 const std::size_t element_type_parse_position)
10103 {
10104 switch (element_type)
10105 {
10106 case 0x01: // double
10107 {
10108 double number{};
10109 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10110 }
10111
10112 case 0x02: // string
10113 {
10114 std::int32_t len{};
10115 string_t value;
10116 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
10117 }
10118
10119 case 0x03: // object
10120 {
10121 return parse_bson_internal();
10122 }
10123
10124 case 0x04: // array
10125 {
10126 return parse_bson_array();
10127 }
10128
10129 case 0x05: // binary
10130 {
10131 std::int32_t len{};
10132 binary_t value;
10133 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
10134 }
10135
10136 case 0x08: // boolean
10137 {
10138 return sax->boolean(get() != 0);
10139 }
10140
10141 case 0x0A: // null
10142 {
10143 return sax->null();
10144 }
10145
10146 case 0x10: // int32
10147 {
10148 std::int32_t value{};
10149 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10150 }
10151
10152 case 0x12: // int64
10153 {
10154 std::int64_t value{};
10155 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10156 }
10157
10158 case 0x11: // uint64
10159 {
10160 std::uint64_t value{};
10161 return get_number<std::uint64_t, true>(input_format_t::bson, value) && sax->number_unsigned(value);
10162 }
10163
10164 default: // anything else is not supported (yet)
10165 {
10166 std::array<char, 3> cr{{}};
10167 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10168 const std::string cr_str{cr.data()};
10169 return sax->parse_error(element_type_parse_position, cr_str,
10170 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
10171 }
10172 }
10173 }
10174
10187 bool parse_bson_element_list(const bool is_array)
10188 {
10189 string_t key;
10190
10191 while (auto element_type = get())
10192 {
10193 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
10194 {
10195 return false;
10196 }
10197
10198 const std::size_t element_type_parse_position = chars_read;
10199 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
10200 {
10201 return false;
10202 }
10203
10204 if (!is_array && !sax->key(key))
10205 {
10206 return false;
10207 }
10208
10209 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
10210 {
10211 return false;
10212 }
10213
10214 // get_bson_cstr only appends
10215 key.clear();
10216 }
10217
10218 return true;
10219 }
10220
10225 bool parse_bson_array()
10226 {
10227 std::int32_t document_size{};
10228 get_number<std::int32_t, true>(input_format_t::bson, document_size);
10229
10230 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
10231 {
10232 return false;
10233 }
10234
10235 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
10236 {
10237 return false;
10238 }
10239
10240 return sax->end_array();
10241 }
10242
10244 // CBOR //
10246
10255 bool parse_cbor_internal(const bool get_char,
10256 const cbor_tag_handler_t tag_handler)
10257 {
10258 switch (get_char ? get() : current)
10259 {
10260 // EOF
10261 case char_traits<char_type>::eof():
10262 return unexpect_eof(input_format_t::cbor, "value");
10263
10264 // Integer 0x00..0x17 (0..23)
10265 case 0x00:
10266 case 0x01:
10267 case 0x02:
10268 case 0x03:
10269 case 0x04:
10270 case 0x05:
10271 case 0x06:
10272 case 0x07:
10273 case 0x08:
10274 case 0x09:
10275 case 0x0A:
10276 case 0x0B:
10277 case 0x0C:
10278 case 0x0D:
10279 case 0x0E:
10280 case 0x0F:
10281 case 0x10:
10282 case 0x11:
10283 case 0x12:
10284 case 0x13:
10285 case 0x14:
10286 case 0x15:
10287 case 0x16:
10288 case 0x17:
10289 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10290
10291 case 0x18: // Unsigned integer (one-byte uint8_t follows)
10292 {
10293 std::uint8_t number{};
10294 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10295 }
10296
10297 case 0x19: // Unsigned integer (two-byte uint16_t follows)
10298 {
10299 std::uint16_t number{};
10300 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10301 }
10302
10303 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
10304 {
10305 std::uint32_t number{};
10306 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10307 }
10308
10309 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
10310 {
10311 std::uint64_t number{};
10312 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10313 }
10314
10315 // Negative integer -1-0x00..-1-0x17 (-1..-24)
10316 case 0x20:
10317 case 0x21:
10318 case 0x22:
10319 case 0x23:
10320 case 0x24:
10321 case 0x25:
10322 case 0x26:
10323 case 0x27:
10324 case 0x28:
10325 case 0x29:
10326 case 0x2A:
10327 case 0x2B:
10328 case 0x2C:
10329 case 0x2D:
10330 case 0x2E:
10331 case 0x2F:
10332 case 0x30:
10333 case 0x31:
10334 case 0x32:
10335 case 0x33:
10336 case 0x34:
10337 case 0x35:
10338 case 0x36:
10339 case 0x37:
10340 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
10341
10342 case 0x38: // Negative integer (one-byte uint8_t follows)
10343 {
10344 std::uint8_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 0x39: // Negative integer -1-n (two-byte uint16_t follows)
10349 {
10350 std::uint16_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 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
10355 {
10356 std::uint32_t number{};
10357 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10358 }
10359
10360 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
10361 {
10362 std::uint64_t number{};
10363 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
10364 - static_cast<number_integer_t>(number));
10365 }
10366
10367 // Binary data (0x00..0x17 bytes follow)
10368 case 0x40:
10369 case 0x41:
10370 case 0x42:
10371 case 0x43:
10372 case 0x44:
10373 case 0x45:
10374 case 0x46:
10375 case 0x47:
10376 case 0x48:
10377 case 0x49:
10378 case 0x4A:
10379 case 0x4B:
10380 case 0x4C:
10381 case 0x4D:
10382 case 0x4E:
10383 case 0x4F:
10384 case 0x50:
10385 case 0x51:
10386 case 0x52:
10387 case 0x53:
10388 case 0x54:
10389 case 0x55:
10390 case 0x56:
10391 case 0x57:
10392 case 0x58: // Binary data (one-byte uint8_t for n follows)
10393 case 0x59: // Binary data (two-byte uint16_t for n follow)
10394 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10395 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10396 case 0x5F: // Binary data (indefinite length)
10397 {
10398 binary_t b;
10399 return get_cbor_binary(b) && sax->binary(b);
10400 }
10401
10402 // UTF-8 string (0x00..0x17 bytes follow)
10403 case 0x60:
10404 case 0x61:
10405 case 0x62:
10406 case 0x63:
10407 case 0x64:
10408 case 0x65:
10409 case 0x66:
10410 case 0x67:
10411 case 0x68:
10412 case 0x69:
10413 case 0x6A:
10414 case 0x6B:
10415 case 0x6C:
10416 case 0x6D:
10417 case 0x6E:
10418 case 0x6F:
10419 case 0x70:
10420 case 0x71:
10421 case 0x72:
10422 case 0x73:
10423 case 0x74:
10424 case 0x75:
10425 case 0x76:
10426 case 0x77:
10427 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10428 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10429 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10430 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10431 case 0x7F: // UTF-8 string (indefinite length)
10432 {
10433 string_t s;
10434 return get_cbor_string(s) && sax->string(s);
10435 }
10436
10437 // array (0x00..0x17 data items follow)
10438 case 0x80:
10439 case 0x81:
10440 case 0x82:
10441 case 0x83:
10442 case 0x84:
10443 case 0x85:
10444 case 0x86:
10445 case 0x87:
10446 case 0x88:
10447 case 0x89:
10448 case 0x8A:
10449 case 0x8B:
10450 case 0x8C:
10451 case 0x8D:
10452 case 0x8E:
10453 case 0x8F:
10454 case 0x90:
10455 case 0x91:
10456 case 0x92:
10457 case 0x93:
10458 case 0x94:
10459 case 0x95:
10460 case 0x96:
10461 case 0x97:
10462 return get_cbor_array(
10463 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10464
10465 case 0x98: // array (one-byte uint8_t for n follows)
10466 {
10467 std::uint8_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 0x99: // array (two-byte uint16_t for n follow)
10472 {
10473 std::uint16_t len{};
10474 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10475 }
10476
10477 case 0x9A: // array (four-byte uint32_t for n follow)
10478 {
10479 std::uint32_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 0x9B: // array (eight-byte uint64_t for n follow)
10484 {
10485 std::uint64_t len{};
10486 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10487 }
10488
10489 case 0x9F: // array (indefinite length)
10490 return get_cbor_array(detail::unknown_size(), tag_handler);
10491
10492 // map (0x00..0x17 pairs of data items follow)
10493 case 0xA0:
10494 case 0xA1:
10495 case 0xA2:
10496 case 0xA3:
10497 case 0xA4:
10498 case 0xA5:
10499 case 0xA6:
10500 case 0xA7:
10501 case 0xA8:
10502 case 0xA9:
10503 case 0xAA:
10504 case 0xAB:
10505 case 0xAC:
10506 case 0xAD:
10507 case 0xAE:
10508 case 0xAF:
10509 case 0xB0:
10510 case 0xB1:
10511 case 0xB2:
10512 case 0xB3:
10513 case 0xB4:
10514 case 0xB5:
10515 case 0xB6:
10516 case 0xB7:
10517 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10518
10519 case 0xB8: // map (one-byte uint8_t for n follows)
10520 {
10521 std::uint8_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 0xB9: // map (two-byte uint16_t for n follow)
10526 {
10527 std::uint16_t len{};
10528 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10529 }
10530
10531 case 0xBA: // map (four-byte uint32_t for n follow)
10532 {
10533 std::uint32_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 0xBB: // map (eight-byte uint64_t for n follow)
10538 {
10539 std::uint64_t len{};
10540 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10541 }
10542
10543 case 0xBF: // map (indefinite length)
10544 return get_cbor_object(detail::unknown_size(), tag_handler);
10545
10546 case 0xC6: // tagged item
10547 case 0xC7:
10548 case 0xC8:
10549 case 0xC9:
10550 case 0xCA:
10551 case 0xCB:
10552 case 0xCC:
10553 case 0xCD:
10554 case 0xCE:
10555 case 0xCF:
10556 case 0xD0:
10557 case 0xD1:
10558 case 0xD2:
10559 case 0xD3:
10560 case 0xD4:
10561 case 0xD8: // tagged item (1 byte follows)
10562 case 0xD9: // tagged item (2 bytes follow)
10563 case 0xDA: // tagged item (4 bytes follow)
10564 case 0xDB: // tagged item (8 bytes follow)
10565 {
10566 switch (tag_handler)
10567 {
10568 case cbor_tag_handler_t::error:
10569 {
10570 auto last_token = get_token_string();
10571 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10572 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10573 }
10574
10575 case cbor_tag_handler_t::ignore:
10576 {
10577 // ignore binary subtype
10578 switch (current)
10579 {
10580 case 0xD8:
10581 {
10582 std::uint8_t subtype_to_ignore{};
10583 get_number(input_format_t::cbor, subtype_to_ignore);
10584 break;
10585 }
10586 case 0xD9:
10587 {
10588 std::uint16_t subtype_to_ignore{};
10589 get_number(input_format_t::cbor, subtype_to_ignore);
10590 break;
10591 }
10592 case 0xDA:
10593 {
10594 std::uint32_t subtype_to_ignore{};
10595 get_number(input_format_t::cbor, subtype_to_ignore);
10596 break;
10597 }
10598 case 0xDB:
10599 {
10600 std::uint64_t subtype_to_ignore{};
10601 get_number(input_format_t::cbor, subtype_to_ignore);
10602 break;
10603 }
10604 default:
10605 break;
10606 }
10607 return parse_cbor_internal(true, tag_handler);
10608 }
10609
10610 case cbor_tag_handler_t::store:
10611 {
10612 binary_t b;
10613 // use binary subtype and store in a binary container
10614 switch (current)
10615 {
10616 case 0xD8:
10617 {
10618 std::uint8_t subtype{};
10619 get_number(input_format_t::cbor, subtype);
10620 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10621 break;
10622 }
10623 case 0xD9:
10624 {
10625 std::uint16_t subtype{};
10626 get_number(input_format_t::cbor, subtype);
10627 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10628 break;
10629 }
10630 case 0xDA:
10631 {
10632 std::uint32_t subtype{};
10633 get_number(input_format_t::cbor, subtype);
10634 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10635 break;
10636 }
10637 case 0xDB:
10638 {
10639 std::uint64_t subtype{};
10640 get_number(input_format_t::cbor, subtype);
10641 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10642 break;
10643 }
10644 default:
10645 return parse_cbor_internal(true, tag_handler);
10646 }
10647 get();
10648 return get_cbor_binary(b) && sax->binary(b);
10649 }
10650
10651 default: // LCOV_EXCL_LINE
10652 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10653 return false; // LCOV_EXCL_LINE
10654 }
10655 }
10656
10657 case 0xF4: // false
10658 return sax->boolean(false);
10659
10660 case 0xF5: // true
10661 return sax->boolean(true);
10662
10663 case 0xF6: // null
10664 return sax->null();
10665
10666 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10667 {
10668 const auto byte1_raw = get();
10669 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10670 {
10671 return false;
10672 }
10673 const auto byte2_raw = get();
10674 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10675 {
10676 return false;
10677 }
10678
10679 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10680 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10681
10682 // Code from RFC 7049, Appendix D, Figure 3:
10683 // As half-precision floating-point numbers were only added
10684 // to IEEE 754 in 2008, today's programming platforms often
10685 // still only have limited support for them. It is very
10686 // easy to include at least decoding support for them even
10687 // without such support. An example of a small decoder for
10688 // half-precision floating-point numbers in the C language
10689 // is shown in Fig. 3.
10690 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10691 const double val = [&half]
10692 {
10693 const int exp = (half >> 10u) & 0x1Fu;
10694 const unsigned int mant = half & 0x3FFu;
10695 JSON_ASSERT(0 <= exp&& exp <= 32);
10696 JSON_ASSERT(mant <= 1024);
10697 switch (exp)
10698 {
10699 case 0:
10700 return std::ldexp(mant, -24);
10701 case 31:
10702 return (mant == 0)
10703 ? std::numeric_limits<double>::infinity()
10704 : std::numeric_limits<double>::quiet_NaN();
10705 default:
10706 return std::ldexp(mant + 1024, exp - 25);
10707 }
10708 }();
10709 return sax->number_float((half & 0x8000u) != 0
10710 ? static_cast<number_float_t>(-val)
10711 : static_cast<number_float_t>(val), "");
10712 }
10713
10714 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10715 {
10716 float number{};
10717 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10718 }
10719
10720 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10721 {
10722 double number{};
10723 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10724 }
10725
10726 default: // anything else (0xFF is handled inside the other types)
10727 {
10728 auto last_token = get_token_string();
10729 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10730 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10731 }
10732 }
10733 }
10734
10746 bool get_cbor_string(string_t& result)
10747 {
10748 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10749 {
10750 return false;
10751 }
10752
10753 switch (current)
10754 {
10755 // UTF-8 string (0x00..0x17 bytes follow)
10756 case 0x60:
10757 case 0x61:
10758 case 0x62:
10759 case 0x63:
10760 case 0x64:
10761 case 0x65:
10762 case 0x66:
10763 case 0x67:
10764 case 0x68:
10765 case 0x69:
10766 case 0x6A:
10767 case 0x6B:
10768 case 0x6C:
10769 case 0x6D:
10770 case 0x6E:
10771 case 0x6F:
10772 case 0x70:
10773 case 0x71:
10774 case 0x72:
10775 case 0x73:
10776 case 0x74:
10777 case 0x75:
10778 case 0x76:
10779 case 0x77:
10780 {
10781 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10782 }
10783
10784 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10785 {
10786 std::uint8_t len{};
10787 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10788 }
10789
10790 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10791 {
10792 std::uint16_t len{};
10793 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10794 }
10795
10796 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10797 {
10798 std::uint32_t len{};
10799 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10800 }
10801
10802 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10803 {
10804 std::uint64_t len{};
10805 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10806 }
10807
10808 case 0x7F: // UTF-8 string (indefinite length)
10809 {
10810 while (get() != 0xFF)
10811 {
10812 string_t chunk;
10813 if (!get_cbor_string(chunk))
10814 {
10815 return false;
10816 }
10817 result.append(chunk);
10818 }
10819 return true;
10820 }
10821
10822 default:
10823 {
10824 auto last_token = get_token_string();
10825 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10826 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10827 }
10828 }
10829 }
10830
10842 bool get_cbor_binary(binary_t& result)
10843 {
10844 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10845 {
10846 return false;
10847 }
10848
10849 switch (current)
10850 {
10851 // Binary data (0x00..0x17 bytes follow)
10852 case 0x40:
10853 case 0x41:
10854 case 0x42:
10855 case 0x43:
10856 case 0x44:
10857 case 0x45:
10858 case 0x46:
10859 case 0x47:
10860 case 0x48:
10861 case 0x49:
10862 case 0x4A:
10863 case 0x4B:
10864 case 0x4C:
10865 case 0x4D:
10866 case 0x4E:
10867 case 0x4F:
10868 case 0x50:
10869 case 0x51:
10870 case 0x52:
10871 case 0x53:
10872 case 0x54:
10873 case 0x55:
10874 case 0x56:
10875 case 0x57:
10876 {
10877 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10878 }
10879
10880 case 0x58: // Binary data (one-byte uint8_t for n follows)
10881 {
10882 std::uint8_t len{};
10883 return get_number(input_format_t::cbor, len) &&
10884 get_binary(input_format_t::cbor, len, result);
10885 }
10886
10887 case 0x59: // Binary data (two-byte uint16_t for n follow)
10888 {
10889 std::uint16_t len{};
10890 return get_number(input_format_t::cbor, len) &&
10891 get_binary(input_format_t::cbor, len, result);
10892 }
10893
10894 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10895 {
10896 std::uint32_t len{};
10897 return get_number(input_format_t::cbor, len) &&
10898 get_binary(input_format_t::cbor, len, result);
10899 }
10900
10901 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10902 {
10903 std::uint64_t len{};
10904 return get_number(input_format_t::cbor, len) &&
10905 get_binary(input_format_t::cbor, len, result);
10906 }
10907
10908 case 0x5F: // Binary data (indefinite length)
10909 {
10910 while (get() != 0xFF)
10911 {
10912 binary_t chunk;
10913 if (!get_cbor_binary(chunk))
10914 {
10915 return false;
10916 }
10917 result.insert(result.end(), chunk.begin(), chunk.end());
10918 }
10919 return true;
10920 }
10921
10922 default:
10923 {
10924 auto last_token = get_token_string();
10925 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10926 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));
10927 }
10928 }
10929 }
10930
10937 bool get_cbor_array(const std::size_t len,
10938 const cbor_tag_handler_t tag_handler)
10939 {
10940 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10941 {
10942 return false;
10943 }
10944
10945 if (len != detail::unknown_size())
10946 {
10947 for (std::size_t i = 0; i < len; ++i)
10948 {
10949 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10950 {
10951 return false;
10952 }
10953 }
10954 }
10955 else
10956 {
10957 while (get() != 0xFF)
10958 {
10959 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10960 {
10961 return false;
10962 }
10963 }
10964 }
10965
10966 return sax->end_array();
10967 }
10968
10975 bool get_cbor_object(const std::size_t len,
10976 const cbor_tag_handler_t tag_handler)
10977 {
10978 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10979 {
10980 return false;
10981 }
10982
10983 if (len != 0)
10984 {
10985 string_t key;
10986 if (len != detail::unknown_size())
10987 {
10988 for (std::size_t i = 0; i < len; ++i)
10989 {
10990 get();
10991 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10992 {
10993 return false;
10994 }
10995
10996 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10997 {
10998 return false;
10999 }
11000 key.clear();
11001 }
11002 }
11003 else
11004 {
11005 while (get() != 0xFF)
11006 {
11007 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
11008 {
11009 return false;
11010 }
11011
11012 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
11013 {
11014 return false;
11015 }
11016 key.clear();
11017 }
11018 }
11019 }
11020
11021 return sax->end_object();
11022 }
11023
11025 // MsgPack //
11027
11031 bool parse_msgpack_internal()
11032 {
11033 switch (get())
11034 {
11035 // EOF
11036 case char_traits<char_type>::eof():
11037 return unexpect_eof(input_format_t::msgpack, "value");
11038
11039 // positive fixint
11040 case 0x00:
11041 case 0x01:
11042 case 0x02:
11043 case 0x03:
11044 case 0x04:
11045 case 0x05:
11046 case 0x06:
11047 case 0x07:
11048 case 0x08:
11049 case 0x09:
11050 case 0x0A:
11051 case 0x0B:
11052 case 0x0C:
11053 case 0x0D:
11054 case 0x0E:
11055 case 0x0F:
11056 case 0x10:
11057 case 0x11:
11058 case 0x12:
11059 case 0x13:
11060 case 0x14:
11061 case 0x15:
11062 case 0x16:
11063 case 0x17:
11064 case 0x18:
11065 case 0x19:
11066 case 0x1A:
11067 case 0x1B:
11068 case 0x1C:
11069 case 0x1D:
11070 case 0x1E:
11071 case 0x1F:
11072 case 0x20:
11073 case 0x21:
11074 case 0x22:
11075 case 0x23:
11076 case 0x24:
11077 case 0x25:
11078 case 0x26:
11079 case 0x27:
11080 case 0x28:
11081 case 0x29:
11082 case 0x2A:
11083 case 0x2B:
11084 case 0x2C:
11085 case 0x2D:
11086 case 0x2E:
11087 case 0x2F:
11088 case 0x30:
11089 case 0x31:
11090 case 0x32:
11091 case 0x33:
11092 case 0x34:
11093 case 0x35:
11094 case 0x36:
11095 case 0x37:
11096 case 0x38:
11097 case 0x39:
11098 case 0x3A:
11099 case 0x3B:
11100 case 0x3C:
11101 case 0x3D:
11102 case 0x3E:
11103 case 0x3F:
11104 case 0x40:
11105 case 0x41:
11106 case 0x42:
11107 case 0x43:
11108 case 0x44:
11109 case 0x45:
11110 case 0x46:
11111 case 0x47:
11112 case 0x48:
11113 case 0x49:
11114 case 0x4A:
11115 case 0x4B:
11116 case 0x4C:
11117 case 0x4D:
11118 case 0x4E:
11119 case 0x4F:
11120 case 0x50:
11121 case 0x51:
11122 case 0x52:
11123 case 0x53:
11124 case 0x54:
11125 case 0x55:
11126 case 0x56:
11127 case 0x57:
11128 case 0x58:
11129 case 0x59:
11130 case 0x5A:
11131 case 0x5B:
11132 case 0x5C:
11133 case 0x5D:
11134 case 0x5E:
11135 case 0x5F:
11136 case 0x60:
11137 case 0x61:
11138 case 0x62:
11139 case 0x63:
11140 case 0x64:
11141 case 0x65:
11142 case 0x66:
11143 case 0x67:
11144 case 0x68:
11145 case 0x69:
11146 case 0x6A:
11147 case 0x6B:
11148 case 0x6C:
11149 case 0x6D:
11150 case 0x6E:
11151 case 0x6F:
11152 case 0x70:
11153 case 0x71:
11154 case 0x72:
11155 case 0x73:
11156 case 0x74:
11157 case 0x75:
11158 case 0x76:
11159 case 0x77:
11160 case 0x78:
11161 case 0x79:
11162 case 0x7A:
11163 case 0x7B:
11164 case 0x7C:
11165 case 0x7D:
11166 case 0x7E:
11167 case 0x7F:
11168 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
11169
11170 // fixmap
11171 case 0x80:
11172 case 0x81:
11173 case 0x82:
11174 case 0x83:
11175 case 0x84:
11176 case 0x85:
11177 case 0x86:
11178 case 0x87:
11179 case 0x88:
11180 case 0x89:
11181 case 0x8A:
11182 case 0x8B:
11183 case 0x8C:
11184 case 0x8D:
11185 case 0x8E:
11186 case 0x8F:
11187 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11188
11189 // fixarray
11190 case 0x90:
11191 case 0x91:
11192 case 0x92:
11193 case 0x93:
11194 case 0x94:
11195 case 0x95:
11196 case 0x96:
11197 case 0x97:
11198 case 0x98:
11199 case 0x99:
11200 case 0x9A:
11201 case 0x9B:
11202 case 0x9C:
11203 case 0x9D:
11204 case 0x9E:
11205 case 0x9F:
11206 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11207
11208 // fixstr
11209 case 0xA0:
11210 case 0xA1:
11211 case 0xA2:
11212 case 0xA3:
11213 case 0xA4:
11214 case 0xA5:
11215 case 0xA6:
11216 case 0xA7:
11217 case 0xA8:
11218 case 0xA9:
11219 case 0xAA:
11220 case 0xAB:
11221 case 0xAC:
11222 case 0xAD:
11223 case 0xAE:
11224 case 0xAF:
11225 case 0xB0:
11226 case 0xB1:
11227 case 0xB2:
11228 case 0xB3:
11229 case 0xB4:
11230 case 0xB5:
11231 case 0xB6:
11232 case 0xB7:
11233 case 0xB8:
11234 case 0xB9:
11235 case 0xBA:
11236 case 0xBB:
11237 case 0xBC:
11238 case 0xBD:
11239 case 0xBE:
11240 case 0xBF:
11241 case 0xD9: // str 8
11242 case 0xDA: // str 16
11243 case 0xDB: // str 32
11244 {
11245 string_t s;
11246 return get_msgpack_string(s) && sax->string(s);
11247 }
11248
11249 case 0xC0: // nil
11250 return sax->null();
11251
11252 case 0xC2: // false
11253 return sax->boolean(false);
11254
11255 case 0xC3: // true
11256 return sax->boolean(true);
11257
11258 case 0xC4: // bin 8
11259 case 0xC5: // bin 16
11260 case 0xC6: // bin 32
11261 case 0xC7: // ext 8
11262 case 0xC8: // ext 16
11263 case 0xC9: // ext 32
11264 case 0xD4: // fixext 1
11265 case 0xD5: // fixext 2
11266 case 0xD6: // fixext 4
11267 case 0xD7: // fixext 8
11268 case 0xD8: // fixext 16
11269 {
11270 binary_t b;
11271 return get_msgpack_binary(b) && sax->binary(b);
11272 }
11273
11274 case 0xCA: // float 32
11275 {
11276 float number{};
11277 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11278 }
11279
11280 case 0xCB: // float 64
11281 {
11282 double number{};
11283 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11284 }
11285
11286 case 0xCC: // uint 8
11287 {
11288 std::uint8_t number{};
11289 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11290 }
11291
11292 case 0xCD: // uint 16
11293 {
11294 std::uint16_t number{};
11295 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11296 }
11297
11298 case 0xCE: // uint 32
11299 {
11300 std::uint32_t number{};
11301 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11302 }
11303
11304 case 0xCF: // uint 64
11305 {
11306 std::uint64_t number{};
11307 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11308 }
11309
11310 case 0xD0: // int 8
11311 {
11312 std::int8_t number{};
11313 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11314 }
11315
11316 case 0xD1: // int 16
11317 {
11318 std::int16_t number{};
11319 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11320 }
11321
11322 case 0xD2: // int 32
11323 {
11324 std::int32_t number{};
11325 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11326 }
11327
11328 case 0xD3: // int 64
11329 {
11330 std::int64_t number{};
11331 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11332 }
11333
11334 case 0xDC: // array 16
11335 {
11336 std::uint16_t len{};
11337 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
11338 }
11339
11340 case 0xDD: // array 32
11341 {
11342 std::uint32_t len{};
11343 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
11344 }
11345
11346 case 0xDE: // map 16
11347 {
11348 std::uint16_t len{};
11349 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
11350 }
11351
11352 case 0xDF: // map 32
11353 {
11354 std::uint32_t len{};
11355 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
11356 }
11357
11358 // negative fixint
11359 case 0xE0:
11360 case 0xE1:
11361 case 0xE2:
11362 case 0xE3:
11363 case 0xE4:
11364 case 0xE5:
11365 case 0xE6:
11366 case 0xE7:
11367 case 0xE8:
11368 case 0xE9:
11369 case 0xEA:
11370 case 0xEB:
11371 case 0xEC:
11372 case 0xED:
11373 case 0xEE:
11374 case 0xEF:
11375 case 0xF0:
11376 case 0xF1:
11377 case 0xF2:
11378 case 0xF3:
11379 case 0xF4:
11380 case 0xF5:
11381 case 0xF6:
11382 case 0xF7:
11383 case 0xF8:
11384 case 0xF9:
11385 case 0xFA:
11386 case 0xFB:
11387 case 0xFC:
11388 case 0xFD:
11389 case 0xFE:
11390 case 0xFF:
11391 return sax->number_integer(static_cast<std::int8_t>(current));
11392
11393 default: // anything else
11394 {
11395 auto last_token = get_token_string();
11396 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11397 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
11398 }
11399 }
11400 }
11401
11412 bool get_msgpack_string(string_t& result)
11413 {
11414 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
11415 {
11416 return false;
11417 }
11418
11419 switch (current)
11420 {
11421 // fixstr
11422 case 0xA0:
11423 case 0xA1:
11424 case 0xA2:
11425 case 0xA3:
11426 case 0xA4:
11427 case 0xA5:
11428 case 0xA6:
11429 case 0xA7:
11430 case 0xA8:
11431 case 0xA9:
11432 case 0xAA:
11433 case 0xAB:
11434 case 0xAC:
11435 case 0xAD:
11436 case 0xAE:
11437 case 0xAF:
11438 case 0xB0:
11439 case 0xB1:
11440 case 0xB2:
11441 case 0xB3:
11442 case 0xB4:
11443 case 0xB5:
11444 case 0xB6:
11445 case 0xB7:
11446 case 0xB8:
11447 case 0xB9:
11448 case 0xBA:
11449 case 0xBB:
11450 case 0xBC:
11451 case 0xBD:
11452 case 0xBE:
11453 case 0xBF:
11454 {
11455 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
11456 }
11457
11458 case 0xD9: // str 8
11459 {
11460 std::uint8_t len{};
11461 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11462 }
11463
11464 case 0xDA: // str 16
11465 {
11466 std::uint16_t len{};
11467 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11468 }
11469
11470 case 0xDB: // str 32
11471 {
11472 std::uint32_t len{};
11473 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11474 }
11475
11476 default:
11477 {
11478 auto last_token = get_token_string();
11479 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11480 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
11481 }
11482 }
11483 }
11484
11495 bool get_msgpack_binary(binary_t& result)
11496 {
11497 // helper function to set the subtype
11498 auto assign_and_return_true = [&result](std::int8_t subtype)
11499 {
11500 result.set_subtype(static_cast<std::uint8_t>(subtype));
11501 return true;
11502 };
11503
11504 switch (current)
11505 {
11506 case 0xC4: // bin 8
11507 {
11508 std::uint8_t len{};
11509 return get_number(input_format_t::msgpack, len) &&
11510 get_binary(input_format_t::msgpack, len, result);
11511 }
11512
11513 case 0xC5: // bin 16
11514 {
11515 std::uint16_t len{};
11516 return get_number(input_format_t::msgpack, len) &&
11517 get_binary(input_format_t::msgpack, len, result);
11518 }
11519
11520 case 0xC6: // bin 32
11521 {
11522 std::uint32_t len{};
11523 return get_number(input_format_t::msgpack, len) &&
11524 get_binary(input_format_t::msgpack, len, result);
11525 }
11526
11527 case 0xC7: // ext 8
11528 {
11529 std::uint8_t len{};
11530 std::int8_t subtype{};
11531 return get_number(input_format_t::msgpack, len) &&
11532 get_number(input_format_t::msgpack, subtype) &&
11533 get_binary(input_format_t::msgpack, len, result) &&
11534 assign_and_return_true(subtype);
11535 }
11536
11537 case 0xC8: // ext 16
11538 {
11539 std::uint16_t len{};
11540 std::int8_t subtype{};
11541 return get_number(input_format_t::msgpack, len) &&
11542 get_number(input_format_t::msgpack, subtype) &&
11543 get_binary(input_format_t::msgpack, len, result) &&
11544 assign_and_return_true(subtype);
11545 }
11546
11547 case 0xC9: // ext 32
11548 {
11549 std::uint32_t len{};
11550 std::int8_t subtype{};
11551 return get_number(input_format_t::msgpack, len) &&
11552 get_number(input_format_t::msgpack, subtype) &&
11553 get_binary(input_format_t::msgpack, len, result) &&
11554 assign_and_return_true(subtype);
11555 }
11556
11557 case 0xD4: // fixext 1
11558 {
11559 std::int8_t subtype{};
11560 return get_number(input_format_t::msgpack, subtype) &&
11561 get_binary(input_format_t::msgpack, 1, result) &&
11562 assign_and_return_true(subtype);
11563 }
11564
11565 case 0xD5: // fixext 2
11566 {
11567 std::int8_t subtype{};
11568 return get_number(input_format_t::msgpack, subtype) &&
11569 get_binary(input_format_t::msgpack, 2, result) &&
11570 assign_and_return_true(subtype);
11571 }
11572
11573 case 0xD6: // fixext 4
11574 {
11575 std::int8_t subtype{};
11576 return get_number(input_format_t::msgpack, subtype) &&
11577 get_binary(input_format_t::msgpack, 4, result) &&
11578 assign_and_return_true(subtype);
11579 }
11580
11581 case 0xD7: // fixext 8
11582 {
11583 std::int8_t subtype{};
11584 return get_number(input_format_t::msgpack, subtype) &&
11585 get_binary(input_format_t::msgpack, 8, result) &&
11586 assign_and_return_true(subtype);
11587 }
11588
11589 case 0xD8: // fixext 16
11590 {
11591 std::int8_t subtype{};
11592 return get_number(input_format_t::msgpack, subtype) &&
11593 get_binary(input_format_t::msgpack, 16, result) &&
11594 assign_and_return_true(subtype);
11595 }
11596
11597 default: // LCOV_EXCL_LINE
11598 return false; // LCOV_EXCL_LINE
11599 }
11600 }
11601
11606 bool get_msgpack_array(const std::size_t len)
11607 {
11608 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
11609 {
11610 return false;
11611 }
11612
11613 for (std::size_t i = 0; i < len; ++i)
11614 {
11615 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11616 {
11617 return false;
11618 }
11619 }
11620
11621 return sax->end_array();
11622 }
11623
11628 bool get_msgpack_object(const std::size_t len)
11629 {
11630 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
11631 {
11632 return false;
11633 }
11634
11635 string_t key;
11636 for (std::size_t i = 0; i < len; ++i)
11637 {
11638 get();
11639 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
11640 {
11641 return false;
11642 }
11643
11644 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11645 {
11646 return false;
11647 }
11648 key.clear();
11649 }
11650
11651 return sax->end_object();
11652 }
11653
11655 // UBJSON //
11657
11665 bool parse_ubjson_internal(const bool get_char = true)
11666 {
11667 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11668 }
11669
11684 bool get_ubjson_string(string_t& result, const bool get_char = true)
11685 {
11686 if (get_char)
11687 {
11688 get(); // TODO(niels): may we ignore N here?
11689 }
11690
11691 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11692 {
11693 return false;
11694 }
11695
11696 switch (current)
11697 {
11698 case 'U':
11699 {
11700 std::uint8_t len{};
11701 return get_number(input_format, len) && get_string(input_format, len, result);
11702 }
11703
11704 case 'i':
11705 {
11706 std::int8_t len{};
11707 return get_number(input_format, len) && get_string(input_format, len, result);
11708 }
11709
11710 case 'I':
11711 {
11712 std::int16_t len{};
11713 return get_number(input_format, len) && get_string(input_format, len, result);
11714 }
11715
11716 case 'l':
11717 {
11718 std::int32_t len{};
11719 return get_number(input_format, len) && get_string(input_format, len, result);
11720 }
11721
11722 case 'L':
11723 {
11724 std::int64_t len{};
11725 return get_number(input_format, len) && get_string(input_format, len, result);
11726 }
11727
11728 case 'u':
11729 {
11730 if (input_format != input_format_t::bjdata)
11731 {
11732 break;
11733 }
11734 std::uint16_t len{};
11735 return get_number(input_format, len) && get_string(input_format, len, result);
11736 }
11737
11738 case 'm':
11739 {
11740 if (input_format != input_format_t::bjdata)
11741 {
11742 break;
11743 }
11744 std::uint32_t len{};
11745 return get_number(input_format, len) && get_string(input_format, len, result);
11746 }
11747
11748 case 'M':
11749 {
11750 if (input_format != input_format_t::bjdata)
11751 {
11752 break;
11753 }
11754 std::uint64_t len{};
11755 return get_number(input_format, len) && get_string(input_format, len, result);
11756 }
11757
11758 default:
11759 break;
11760 }
11761 auto last_token = get_token_string();
11762 std::string message;
11763
11764 if (input_format != input_format_t::bjdata)
11765 {
11766 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11767 }
11768 else
11769 {
11770 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11771 }
11772 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11773 }
11774
11779 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11780 {
11781 std::pair<std::size_t, char_int_type> size_and_type;
11782 size_t dimlen = 0;
11783 bool no_ndarray = true;
11784
11785 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11786 {
11787 return false;
11788 }
11789
11790 if (size_and_type.first != npos)
11791 {
11792 if (size_and_type.second != 0)
11793 {
11794 if (size_and_type.second != 'N')
11795 {
11796 for (std::size_t i = 0; i < size_and_type.first; ++i)
11797 {
11798 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11799 {
11800 return false;
11801 }
11802 dim.push_back(dimlen);
11803 }
11804 }
11805 }
11806 else
11807 {
11808 for (std::size_t i = 0; i < size_and_type.first; ++i)
11809 {
11810 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11811 {
11812 return false;
11813 }
11814 dim.push_back(dimlen);
11815 }
11816 }
11817 }
11818 else
11819 {
11820 while (current != ']')
11821 {
11822 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11823 {
11824 return false;
11825 }
11826 dim.push_back(dimlen);
11827 get_ignore_noop();
11828 }
11829 }
11830 return true;
11831 }
11832
11844 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11845 {
11846 if (prefix == 0)
11847 {
11848 prefix = get_ignore_noop();
11849 }
11850
11851 switch (prefix)
11852 {
11853 case 'U':
11854 {
11855 std::uint8_t number{};
11856 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11857 {
11858 return false;
11859 }
11860 result = static_cast<std::size_t>(number);
11861 return true;
11862 }
11863
11864 case 'i':
11865 {
11866 std::int8_t number{};
11867 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11868 {
11869 return false;
11870 }
11871 if (number < 0)
11872 {
11873 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11874 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11875 }
11876 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11877 return true;
11878 }
11879
11880 case 'I':
11881 {
11882 std::int16_t number{};
11883 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11884 {
11885 return false;
11886 }
11887 if (number < 0)
11888 {
11889 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11890 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11891 }
11892 result = static_cast<std::size_t>(number);
11893 return true;
11894 }
11895
11896 case 'l':
11897 {
11898 std::int32_t number{};
11899 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11900 {
11901 return false;
11902 }
11903 if (number < 0)
11904 {
11905 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11906 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11907 }
11908 result = static_cast<std::size_t>(number);
11909 return true;
11910 }
11911
11912 case 'L':
11913 {
11914 std::int64_t number{};
11915 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11916 {
11917 return false;
11918 }
11919 if (number < 0)
11920 {
11921 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11922 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11923 }
11924 if (!value_in_range_of<std::size_t>(number))
11925 {
11926 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11927 exception_message(input_format, "integer value overflow", "size"), nullptr));
11928 }
11929 result = static_cast<std::size_t>(number);
11930 return true;
11931 }
11932
11933 case 'u':
11934 {
11935 if (input_format != input_format_t::bjdata)
11936 {
11937 break;
11938 }
11939 std::uint16_t number{};
11940 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11941 {
11942 return false;
11943 }
11944 result = static_cast<std::size_t>(number);
11945 return true;
11946 }
11947
11948 case 'm':
11949 {
11950 if (input_format != input_format_t::bjdata)
11951 {
11952 break;
11953 }
11954 std::uint32_t number{};
11955 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11956 {
11957 return false;
11958 }
11959 result = conditional_static_cast<std::size_t>(number);
11960 return true;
11961 }
11962
11963 case 'M':
11964 {
11965 if (input_format != input_format_t::bjdata)
11966 {
11967 break;
11968 }
11969 std::uint64_t number{};
11970 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11971 {
11972 return false;
11973 }
11974 if (!value_in_range_of<std::size_t>(number))
11975 {
11976 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11977 exception_message(input_format, "integer value overflow", "size"), nullptr));
11978 }
11979 result = detail::conditional_static_cast<std::size_t>(number);
11980 return true;
11981 }
11982
11983 case '[':
11984 {
11985 if (input_format != input_format_t::bjdata)
11986 {
11987 break;
11988 }
11989 if (is_ndarray) // ndarray dimensional vector can only contain integers and cannot embed another array
11990 {
11991 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));
11992 }
11993 std::vector<size_t> dim;
11994 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11995 {
11996 return false;
11997 }
11998 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11999 {
12000 result = dim.at(dim.size() - 1);
12001 return true;
12002 }
12003 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
12004 {
12005 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
12006 {
12007 if ( i == 0 )
12008 {
12009 result = 0;
12010 return true;
12011 }
12012 }
12013
12014 string_t key = "_ArraySize_";
12015 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
12016 {
12017 return false;
12018 }
12019 result = 1;
12020 for (auto i : dim)
12021 {
12022 // Pre-multiplication overflow check: if i > 0 and result > SIZE_MAX/i, then result*i would overflow.
12023 // This check must happen before multiplication since overflow detection after the fact is unreliable
12024 // as modular arithmetic can produce any value, not just 0 or SIZE_MAX.
12025 if (JSON_HEDLEY_UNLIKELY(i > 0 && result > (std::numeric_limits<std::size_t>::max)() / i))
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 result *= i;
12030 // Additional post-multiplication check to catch any edge cases the pre-check might miss
12031 if (result == 0 || result == npos)
12032 {
12033 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));
12034 }
12035 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
12036 {
12037 return false;
12038 }
12039 }
12040 is_ndarray = true;
12041 return sax->end_array();
12042 }
12043 result = 0;
12044 return true;
12045 }
12046
12047 default:
12048 break;
12049 }
12050 auto last_token = get_token_string();
12051 std::string message;
12052
12053 if (input_format != input_format_t::bjdata)
12054 {
12055 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
12056 }
12057 else
12058 {
12059 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
12060 }
12061 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
12062 }
12063
12075 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
12076 {
12077 result.first = npos; // size
12078 result.second = 0; // type
12079 bool is_ndarray = false;
12080
12081 get_ignore_noop();
12082
12083 if (current == '$')
12084 {
12085 result.second = get(); // must not ignore 'N', because 'N' maybe the type
12086 if (input_format == input_format_t::bjdata
12087 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
12088 {
12089 auto last_token = get_token_string();
12090 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12091 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
12092 }
12093
12094 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
12095 {
12096 return false;
12097 }
12098
12099 get_ignore_noop();
12100 if (JSON_HEDLEY_UNLIKELY(current != '#'))
12101 {
12102 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
12103 {
12104 return false;
12105 }
12106 auto last_token = get_token_string();
12107 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12108 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
12109 }
12110
12111 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12112 if (input_format == input_format_t::bjdata && is_ndarray)
12113 {
12114 if (inside_ndarray)
12115 {
12116 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12117 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
12118 }
12119 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
12120 }
12121 return is_error;
12122 }
12123
12124 if (current == '#')
12125 {
12126 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12127 if (input_format == input_format_t::bjdata && is_ndarray)
12128 {
12129 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12130 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
12131 }
12132 return is_error;
12133 }
12134
12135 return true;
12136 }
12137
12142 bool get_ubjson_value(const char_int_type prefix)
12143 {
12144 switch (prefix)
12145 {
12146 case char_traits<char_type>::eof(): // EOF
12147 return unexpect_eof(input_format, "value");
12148
12149 case 'T': // true
12150 return sax->boolean(true);
12151 case 'F': // false
12152 return sax->boolean(false);
12153
12154 case 'Z': // null
12155 return sax->null();
12156
12157 case 'B': // byte
12158 {
12159 if (input_format != input_format_t::bjdata)
12160 {
12161 break;
12162 }
12163 std::uint8_t number{};
12164 return get_number(input_format, number) && sax->number_unsigned(number);
12165 }
12166
12167 case 'U':
12168 {
12169 std::uint8_t number{};
12170 return get_number(input_format, number) && sax->number_unsigned(number);
12171 }
12172
12173 case 'i':
12174 {
12175 std::int8_t number{};
12176 return get_number(input_format, number) && sax->number_integer(number);
12177 }
12178
12179 case 'I':
12180 {
12181 std::int16_t number{};
12182 return get_number(input_format, number) && sax->number_integer(number);
12183 }
12184
12185 case 'l':
12186 {
12187 std::int32_t number{};
12188 return get_number(input_format, number) && sax->number_integer(number);
12189 }
12190
12191 case 'L':
12192 {
12193 std::int64_t number{};
12194 return get_number(input_format, number) && sax->number_integer(number);
12195 }
12196
12197 case 'u':
12198 {
12199 if (input_format != input_format_t::bjdata)
12200 {
12201 break;
12202 }
12203 std::uint16_t number{};
12204 return get_number(input_format, number) && sax->number_unsigned(number);
12205 }
12206
12207 case 'm':
12208 {
12209 if (input_format != input_format_t::bjdata)
12210 {
12211 break;
12212 }
12213 std::uint32_t number{};
12214 return get_number(input_format, number) && sax->number_unsigned(number);
12215 }
12216
12217 case 'M':
12218 {
12219 if (input_format != input_format_t::bjdata)
12220 {
12221 break;
12222 }
12223 std::uint64_t number{};
12224 return get_number(input_format, number) && sax->number_unsigned(number);
12225 }
12226
12227 case 'h':
12228 {
12229 if (input_format != input_format_t::bjdata)
12230 {
12231 break;
12232 }
12233 const auto byte1_raw = get();
12234 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12235 {
12236 return false;
12237 }
12238 const auto byte2_raw = get();
12239 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12240 {
12241 return false;
12242 }
12243
12244 const auto byte1 = static_cast<unsigned char>(byte1_raw);
12245 const auto byte2 = static_cast<unsigned char>(byte2_raw);
12246
12247 // Code from RFC 7049, Appendix D, Figure 3:
12248 // As half-precision floating-point numbers were only added
12249 // to IEEE 754 in 2008, today's programming platforms often
12250 // still only have limited support for them. It is very
12251 // easy to include at least decoding support for them even
12252 // without such support. An example of a small decoder for
12253 // half-precision floating-point numbers in the C language
12254 // is shown in Fig. 3.
12255 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
12256 const double val = [&half]
12257 {
12258 const int exp = (half >> 10u) & 0x1Fu;
12259 const unsigned int mant = half & 0x3FFu;
12260 JSON_ASSERT(0 <= exp&& exp <= 32);
12261 JSON_ASSERT(mant <= 1024);
12262 switch (exp)
12263 {
12264 case 0:
12265 return std::ldexp(mant, -24);
12266 case 31:
12267 return (mant == 0)
12268 ? std::numeric_limits<double>::infinity()
12269 : std::numeric_limits<double>::quiet_NaN();
12270 default:
12271 return std::ldexp(mant + 1024, exp - 25);
12272 }
12273 }();
12274 return sax->number_float((half & 0x8000u) != 0
12275 ? static_cast<number_float_t>(-val)
12276 : static_cast<number_float_t>(val), "");
12277 }
12278
12279 case 'd':
12280 {
12281 float number{};
12282 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12283 }
12284
12285 case 'D':
12286 {
12287 double number{};
12288 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12289 }
12290
12291 case 'H':
12292 {
12293 return get_ubjson_high_precision_number();
12294 }
12295
12296 case 'C': // char
12297 {
12298 get();
12299 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
12300 {
12301 return false;
12302 }
12303 if (JSON_HEDLEY_UNLIKELY(current > 127))
12304 {
12305 auto last_token = get_token_string();
12306 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
12307 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
12308 }
12309 string_t s(1, static_cast<typename string_t::value_type>(current));
12310 return sax->string(s);
12311 }
12312
12313 case 'S': // string
12314 {
12315 string_t s;
12316 return get_ubjson_string(s) && sax->string(s);
12317 }
12318
12319 case '[': // array
12320 return get_ubjson_array();
12321
12322 case '{': // object
12323 return get_ubjson_object();
12324
12325 default: // anything else
12326 break;
12327 }
12328 auto last_token = get_token_string();
12329 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));
12330 }
12331
12335 bool get_ubjson_array()
12336 {
12337 std::pair<std::size_t, char_int_type> size_and_type;
12338 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12339 {
12340 return false;
12341 }
12342
12343 // 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):
12344 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
12345
12346 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12347 {
12348 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
12349 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)
12350 {
12351 return p.first < t;
12352 });
12353 string_t key = "_ArrayType_";
12354 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
12355 {
12356 auto last_token = get_token_string();
12357 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12358 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
12359 }
12360
12361 string_t type = it->second; // sax->string() takes a reference
12362 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
12363 {
12364 return false;
12365 }
12366
12367 if (size_and_type.second == 'C' || size_and_type.second == 'B')
12368 {
12369 size_and_type.second = 'U';
12370 }
12371
12372 key = "_ArrayData_";
12373 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
12374 {
12375 return false;
12376 }
12377
12378 for (std::size_t i = 0; i < size_and_type.first; ++i)
12379 {
12380 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12381 {
12382 return false;
12383 }
12384 }
12385
12386 return (sax->end_array() && sax->end_object());
12387 }
12388
12389 // If BJData type marker is 'B' decode as binary
12390 if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second == 'B')
12391 {
12392 binary_t result;
12393 return get_binary(input_format, size_and_type.first, result) && sax->binary(result);
12394 }
12395
12396 if (size_and_type.first != npos)
12397 {
12398 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
12399 {
12400 return false;
12401 }
12402
12403 if (size_and_type.second != 0)
12404 {
12405 if (size_and_type.second != 'N')
12406 {
12407 for (std::size_t i = 0; i < size_and_type.first; ++i)
12408 {
12409 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12410 {
12411 return false;
12412 }
12413 }
12414 }
12415 }
12416 else
12417 {
12418 for (std::size_t i = 0; i < size_and_type.first; ++i)
12419 {
12420 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12421 {
12422 return false;
12423 }
12424 }
12425 }
12426 }
12427 else
12428 {
12429 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
12430 {
12431 return false;
12432 }
12433
12434 while (current != ']')
12435 {
12436 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
12437 {
12438 return false;
12439 }
12440 get_ignore_noop();
12441 }
12442 }
12443
12444 return sax->end_array();
12445 }
12446
12450 bool get_ubjson_object()
12451 {
12452 std::pair<std::size_t, char_int_type> size_and_type;
12453 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12454 {
12455 return false;
12456 }
12457
12458 // do not accept ND-array size in objects in BJData
12459 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12460 {
12461 auto last_token = get_token_string();
12462 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12463 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
12464 }
12465
12466 string_t key;
12467 if (size_and_type.first != npos)
12468 {
12469 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
12470 {
12471 return false;
12472 }
12473
12474 if (size_and_type.second != 0)
12475 {
12476 for (std::size_t i = 0; i < size_and_type.first; ++i)
12477 {
12478 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12479 {
12480 return false;
12481 }
12482 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12483 {
12484 return false;
12485 }
12486 key.clear();
12487 }
12488 }
12489 else
12490 {
12491 for (std::size_t i = 0; i < size_and_type.first; ++i)
12492 {
12493 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12494 {
12495 return false;
12496 }
12497 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12498 {
12499 return false;
12500 }
12501 key.clear();
12502 }
12503 }
12504 }
12505 else
12506 {
12507 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
12508 {
12509 return false;
12510 }
12511
12512 while (current != '}')
12513 {
12514 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
12515 {
12516 return false;
12517 }
12518 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12519 {
12520 return false;
12521 }
12522 get_ignore_noop();
12523 key.clear();
12524 }
12525 }
12526
12527 return sax->end_object();
12528 }
12529
12530 // Note, no reader for UBJSON binary types is implemented because they do
12531 // not exist
12532
12533 bool get_ubjson_high_precision_number()
12534 {
12535 // get the size of the following number string
12536 std::size_t size{};
12537 bool no_ndarray = true;
12538 auto res = get_ubjson_size_value(size, no_ndarray);
12539 if (JSON_HEDLEY_UNLIKELY(!res))
12540 {
12541 return res;
12542 }
12543
12544 // get number string
12545 std::vector<char> number_vector;
12546 for (std::size_t i = 0; i < size; ++i)
12547 {
12548 get();
12549 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12550 {
12551 return false;
12552 }
12553 number_vector.push_back(static_cast<char>(current));
12554 }
12555
12556 // parse number string
12557 using ia_type = decltype(detail::input_adapter(number_vector));
12558 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
12559 const auto result_number = number_lexer.scan();
12560 const auto number_string = number_lexer.get_token_string();
12561 const auto result_remainder = number_lexer.scan();
12562
12563 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
12564
12565 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
12566 {
12567 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12568 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12569 }
12570
12571 switch (result_number)
12572 {
12573 case token_type::value_integer:
12574 return sax->number_integer(number_lexer.get_number_integer());
12575 case token_type::value_unsigned:
12576 return sax->number_unsigned(number_lexer.get_number_unsigned());
12577 case token_type::value_float:
12578 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
12579 case token_type::uninitialized:
12580 case token_type::literal_true:
12581 case token_type::literal_false:
12582 case token_type::literal_null:
12583 case token_type::value_string:
12584 case token_type::begin_array:
12585 case token_type::begin_object:
12586 case token_type::end_array:
12587 case token_type::end_object:
12588 case token_type::name_separator:
12589 case token_type::value_separator:
12590 case token_type::parse_error:
12591 case token_type::end_of_input:
12592 case token_type::literal_or_value:
12593 default:
12594 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12595 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12596 }
12597 }
12598
12600 // Utility functions //
12602
12612 char_int_type get()
12613 {
12614 ++chars_read;
12615 return current = ia.get_character();
12616 }
12617
12626 template<class T>
12627 bool get_to(T& dest, const input_format_t format, const char* context)
12628 {
12629 auto new_chars_read = ia.get_elements(&dest);
12630 chars_read += new_chars_read;
12631 if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T)))
12632 {
12633 // in case of failure, advance position by 1 to report the failing location
12634 ++chars_read;
12635 sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12636 return false;
12637 }
12638 return true;
12639 }
12640
12644 char_int_type get_ignore_noop()
12645 {
12646 do
12647 {
12648 get();
12649 }
12650 while (current == 'N');
12651
12652 return current;
12653 }
12654
12655 template<class NumberType>
12656 static void byte_swap(NumberType& number)
12657 {
12658 constexpr std::size_t sz = sizeof(number);
12659#ifdef __cpp_lib_byteswap
12660 if constexpr (sz == 1)
12661 {
12662 return;
12663 }
12664 else if constexpr(std::is_integral_v<NumberType>)
12665 {
12666 number = std::byteswap(number);
12667 return;
12668 }
12669 else
12670 {
12671#endif
12672 auto* ptr = reinterpret_cast<std::uint8_t*>(&number);
12673 for (std::size_t i = 0; i < sz / 2; ++i)
12674 {
12675 std::swap(ptr[i], ptr[sz - i - 1]);
12676 }
12677#ifdef __cpp_lib_byteswap
12678 }
12679#endif
12680 }
12681
12682 /*
12683 @brief read a number from the input
12684
12685 @tparam NumberType the type of the number
12686 @param[in] format the current format (for diagnostics)
12687 @param[out] result number of type @a NumberType
12688
12689 @return whether conversion completed
12690
12691 @note This function needs to respect the system's endianness, because
12692 bytes in CBOR, MessagePack, and UBJSON are stored in network order
12693 (big endian) and therefore need reordering on little endian systems.
12694 On the other hand, BSON and BJData use little endian and should reorder
12695 on big endian systems.
12696 */
12697 template<typename NumberType, bool InputIsLittleEndian = false>
12698 bool get_number(const input_format_t format, NumberType& result)
12699 {
12700 // read in the original format
12701
12702 if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number")))
12703 {
12704 return false;
12705 }
12706 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
12707 {
12708 byte_swap(result);
12709 }
12710 return true;
12711 }
12712
12727 template<typename NumberType>
12728 bool get_string(const input_format_t format,
12729 const NumberType len,
12730 string_t& result)
12731 {
12732 bool success = true;
12733 for (NumberType i = 0; i < len; i++)
12734 {
12735 get();
12736 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
12737 {
12738 success = false;
12739 break;
12740 }
12741 result.push_back(static_cast<typename string_t::value_type>(current));
12742 }
12743 return success;
12744 }
12745
12760 template<typename NumberType>
12761 bool get_binary(const input_format_t format,
12762 const NumberType len,
12763 binary_t& result)
12764 {
12765 bool success = true;
12766 for (NumberType i = 0; i < len; i++)
12767 {
12768 get();
12769 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12770 {
12771 success = false;
12772 break;
12773 }
12774 result.push_back(static_cast<typename binary_t::value_type>(current));
12775 }
12776 return success;
12777 }
12778
12784 JSON_HEDLEY_NON_NULL(3)
12785 bool unexpect_eof(const input_format_t format, const char* context) const
12786 {
12787 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12788 {
12789 return sax->parse_error(chars_read, "<end of file>",
12790 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12791 }
12792 return true;
12793 }
12794
12798 std::string get_token_string() const
12799 {
12800 std::array<char, 3> cr{{}};
12801 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12802 return std::string{cr.data()};
12803 }
12804
12811 std::string exception_message(const input_format_t format,
12812 const std::string& detail,
12813 const std::string& context) const
12814 {
12815 std::string error_msg = "syntax error while parsing ";
12816
12817 switch (format)
12818 {
12819 case input_format_t::cbor:
12820 error_msg += "CBOR";
12821 break;
12822
12823 case input_format_t::msgpack:
12824 error_msg += "MessagePack";
12825 break;
12826
12827 case input_format_t::ubjson:
12828 error_msg += "UBJSON";
12829 break;
12830
12831 case input_format_t::bson:
12832 error_msg += "BSON";
12833 break;
12834
12835 case input_format_t::bjdata:
12836 error_msg += "BJData";
12837 break;
12838
12839 case input_format_t::json: // LCOV_EXCL_LINE
12840 default: // LCOV_EXCL_LINE
12841 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12842 }
12843
12844 return concat(error_msg, ' ', context, ": ", detail);
12845 }
12846
12847 private:
12848 static JSON_INLINE_VARIABLE constexpr std::size_t npos = detail::unknown_size();
12849
12851 InputAdapterType ia;
12852
12854 char_int_type current = char_traits<char_type>::eof();
12855
12857 std::size_t chars_read = 0;
12858
12860 const bool is_little_endian = little_endianness();
12861
12863 const input_format_t input_format = input_format_t::json;
12864
12866 json_sax_t* sax = nullptr;
12867
12868 // excluded markers in bjdata optimized type
12869#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12870 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12871
12872#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12873 make_array<bjd_type>( \
12874 bjd_type{'B', "byte"}, \
12875 bjd_type{'C', "char"}, \
12876 bjd_type{'D', "double"}, \
12877 bjd_type{'I', "int16"}, \
12878 bjd_type{'L', "int64"}, \
12879 bjd_type{'M', "uint64"}, \
12880 bjd_type{'U', "uint8"}, \
12881 bjd_type{'d', "single"}, \
12882 bjd_type{'i', "int8"}, \
12883 bjd_type{'l', "int32"}, \
12884 bjd_type{'m', "uint32"}, \
12885 bjd_type{'u', "uint16"})
12886
12887 JSON_PRIVATE_UNLESS_TESTED:
12888 // lookup tables
12889 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12890 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12891 JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
12892
12893 using bjd_type = std::pair<char_int_type, string_t>;
12894 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12895 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12896 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
12897
12898#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12899#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12900};
12901
12902#ifndef JSON_HAS_CPP_17
12903 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12904 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12905#endif
12906
12907} // namespace detail
12908NLOHMANN_JSON_NAMESPACE_END
12909
12910// #include <nlohmann/detail/input/input_adapters.hpp>
12911
12912// #include <nlohmann/detail/input/lexer.hpp>
12913
12914// #include <nlohmann/detail/input/parser.hpp>
12915// __ _____ _____ _____
12916// __| | __| | | | JSON for Modern C++
12917// | | |__ | | | | | | version 3.12.0
12918// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12919//
12920// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
12921// SPDX-License-Identifier: MIT
12922
12923
12924
12925#include <cmath> // isfinite
12926#include <cstdint> // uint8_t
12927#include <functional> // function
12928#include <string> // string
12929#include <utility> // move
12930#include <vector> // vector
12931
12932// #include <nlohmann/detail/exceptions.hpp>
12933
12934// #include <nlohmann/detail/input/input_adapters.hpp>
12935
12936// #include <nlohmann/detail/input/json_sax.hpp>
12937
12938// #include <nlohmann/detail/input/lexer.hpp>
12939
12940// #include <nlohmann/detail/macro_scope.hpp>
12941
12942// #include <nlohmann/detail/meta/is_sax.hpp>
12943
12944// #include <nlohmann/detail/string_concat.hpp>
12945
12946// #include <nlohmann/detail/value_t.hpp>
12947
12948
12949NLOHMANN_JSON_NAMESPACE_BEGIN
12950namespace detail
12951{
12953// parser //
12955
12956enum class parse_event_t : std::uint8_t
12957{
12959 object_start,
12961 object_end,
12963 array_start,
12965 array_end,
12967 key,
12969 value
12970};
12971
12972template<typename BasicJsonType>
12973using parser_callback_t =
12974 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12975
12981template<typename BasicJsonType, typename InputAdapterType>
12982class parser
12983{
12984 using number_integer_t = typename BasicJsonType::number_integer_t;
12985 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12986 using number_float_t = typename BasicJsonType::number_float_t;
12987 using string_t = typename BasicJsonType::string_t;
12988 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
12989 using token_type = typename lexer_t::token_type;
12990
12991 public:
12993 explicit parser(InputAdapterType&& adapter,
12994 parser_callback_t<BasicJsonType> cb = nullptr,
12995 const bool allow_exceptions_ = true,
12996 const bool ignore_comments = false,
12997 const bool ignore_trailing_commas_ = false)
12998 : callback(std::move(cb))
12999 , m_lexer(std::move(adapter), ignore_comments)
13000 , allow_exceptions(allow_exceptions_)
13001 , ignore_trailing_commas(ignore_trailing_commas_)
13002 {
13003 // read first token
13004 get_token();
13005 }
13006
13017 void parse(const bool strict, BasicJsonType& result)
13018 {
13019 if (callback)
13020 {
13021 json_sax_dom_callback_parser<BasicJsonType, InputAdapterType> sdp(result, callback, allow_exceptions, &m_lexer);
13022 sax_parse_internal(&sdp);
13023
13024 // in strict mode, input must be completely read
13025 if (strict && (get_token() != token_type::end_of_input))
13026 {
13027 sdp.parse_error(m_lexer.get_position(),
13028 m_lexer.get_token_string(),
13029 parse_error::create(101, m_lexer.get_position(),
13030 exception_message(token_type::end_of_input, "value"), nullptr));
13031 }
13032
13033 // in case of an error, return a discarded value
13034 if (sdp.is_errored())
13035 {
13036 result = value_t::discarded;
13037 return;
13038 }
13039
13040 // set top-level value to null if it was discarded by the callback
13041 // function
13042 if (result.is_discarded())
13043 {
13044 result = nullptr;
13045 }
13046 }
13047 else
13048 {
13049 json_sax_dom_parser<BasicJsonType, InputAdapterType> sdp(result, allow_exceptions, &m_lexer);
13050 sax_parse_internal(&sdp);
13051
13052 // in strict mode, input must be completely read
13053 if (strict && (get_token() != token_type::end_of_input))
13054 {
13055 sdp.parse_error(m_lexer.get_position(),
13056 m_lexer.get_token_string(),
13057 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13058 }
13059
13060 // in case of an error, return a discarded value
13061 if (sdp.is_errored())
13062 {
13063 result = value_t::discarded;
13064 return;
13065 }
13066 }
13067
13068 result.assert_invariant();
13069 }
13070
13077 bool accept(const bool strict = true)
13078 {
13079 json_sax_acceptor<BasicJsonType> sax_acceptor;
13080 return sax_parse(&sax_acceptor, strict);
13081 }
13082
13083 template<typename SAX>
13084 JSON_HEDLEY_NON_NULL(2)
13085 bool sax_parse(SAX* sax, const bool strict = true)
13086 {
13088 const bool result = sax_parse_internal(sax);
13089
13090 // strict mode: next byte must be EOF
13091 if (result && strict && (get_token() != token_type::end_of_input))
13092 {
13093 return sax->parse_error(m_lexer.get_position(),
13094 m_lexer.get_token_string(),
13095 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13096 }
13097
13098 return result;
13099 }
13100
13101 private:
13102 template<typename SAX>
13103 JSON_HEDLEY_NON_NULL(2)
13104 bool sax_parse_internal(SAX* sax)
13105 {
13106 // stack to remember the hierarchy of structured values we are parsing
13107 // true = array; false = object
13108 std::vector<bool> states;
13109 // value to avoid a goto (see comment where set to true)
13110 bool skip_to_state_evaluation = false;
13111
13112 while (true)
13113 {
13114 if (!skip_to_state_evaluation)
13115 {
13116 // invariant: get_token() was called before each iteration
13117 switch (last_token)
13118 {
13119 case token_type::begin_object:
13120 {
13121 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
13122 {
13123 return false;
13124 }
13125
13126 // closing } -> we are done
13127 if (get_token() == token_type::end_object)
13128 {
13129 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13130 {
13131 return false;
13132 }
13133 break;
13134 }
13135
13136 // parse key
13137 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13138 {
13139 return sax->parse_error(m_lexer.get_position(),
13140 m_lexer.get_token_string(),
13141 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13142 }
13143 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13144 {
13145 return false;
13146 }
13147
13148 // parse separator (:)
13149 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13150 {
13151 return sax->parse_error(m_lexer.get_position(),
13152 m_lexer.get_token_string(),
13153 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13154 }
13155
13156 // remember we are now inside an object
13157 states.push_back(false);
13158
13159 // parse values
13160 get_token();
13161 continue;
13162 }
13163
13164 case token_type::begin_array:
13165 {
13166 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
13167 {
13168 return false;
13169 }
13170
13171 // closing ] -> we are done
13172 if (get_token() == token_type::end_array)
13173 {
13174 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13175 {
13176 return false;
13177 }
13178 break;
13179 }
13180
13181 // remember we are now inside an array
13182 states.push_back(true);
13183
13184 // parse values (no need to call get_token)
13185 continue;
13186 }
13187
13188 case token_type::value_float:
13189 {
13190 const auto res = m_lexer.get_number_float();
13191
13192 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
13193 {
13194 return sax->parse_error(m_lexer.get_position(),
13195 m_lexer.get_token_string(),
13196 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
13197 }
13198
13199 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
13200 {
13201 return false;
13202 }
13203
13204 break;
13205 }
13206
13207 case token_type::literal_false:
13208 {
13209 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
13210 {
13211 return false;
13212 }
13213 break;
13214 }
13215
13216 case token_type::literal_null:
13217 {
13218 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
13219 {
13220 return false;
13221 }
13222 break;
13223 }
13224
13225 case token_type::literal_true:
13226 {
13227 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
13228 {
13229 return false;
13230 }
13231 break;
13232 }
13233
13234 case token_type::value_integer:
13235 {
13236 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
13237 {
13238 return false;
13239 }
13240 break;
13241 }
13242
13243 case token_type::value_string:
13244 {
13245 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
13246 {
13247 return false;
13248 }
13249 break;
13250 }
13251
13252 case token_type::value_unsigned:
13253 {
13254 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
13255 {
13256 return false;
13257 }
13258 break;
13259 }
13260
13261 case token_type::parse_error:
13262 {
13263 // using "uninitialized" to avoid an "expected" message
13264 return sax->parse_error(m_lexer.get_position(),
13265 m_lexer.get_token_string(),
13266 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
13267 }
13268 case token_type::end_of_input:
13269 {
13270 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
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(),
13275 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
13276 }
13277
13278 return sax->parse_error(m_lexer.get_position(),
13279 m_lexer.get_token_string(),
13280 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13281 }
13282 case token_type::uninitialized:
13283 case token_type::end_array:
13284 case token_type::end_object:
13285 case token_type::name_separator:
13286 case token_type::value_separator:
13287 case token_type::literal_or_value:
13288 default: // the last token was unexpected
13289 {
13290 return sax->parse_error(m_lexer.get_position(),
13291 m_lexer.get_token_string(),
13292 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13293 }
13294 }
13295 }
13296 else
13297 {
13298 skip_to_state_evaluation = false;
13299 }
13300
13301 // we reached this line after we successfully parsed a value
13302 if (states.empty())
13303 {
13304 // empty stack: we reached the end of the hierarchy: done
13305 return true;
13306 }
13307
13308 if (states.back()) // array
13309 {
13310 // comma -> next value
13311 // or end of array (ignore_trailing_commas = true)
13312 if (get_token() == token_type::value_separator)
13313 {
13314 // parse a new value
13315 get_token();
13316
13317 // if ignore_trailing_commas and last_token is ], we can continue to "closing ]"
13318 if (!(ignore_trailing_commas && last_token == token_type::end_array))
13319 {
13320 continue;
13321 }
13322 }
13323
13324 // closing ]
13325 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
13326 {
13327 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13328 {
13329 return false;
13330 }
13331
13332 // We are done with this array. Before we can parse a
13333 // new value, we need to evaluate the new state first.
13334 // By setting skip_to_state_evaluation to false, we
13335 // are effectively jumping to the beginning of this if.
13336 JSON_ASSERT(!states.empty());
13337 states.pop_back();
13338 skip_to_state_evaluation = true;
13339 continue;
13340 }
13341
13342 return sax->parse_error(m_lexer.get_position(),
13343 m_lexer.get_token_string(),
13344 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
13345 }
13346
13347 // states.back() is false -> object
13348
13349 // comma -> next value
13350 // or end of object (ignore_trailing_commas = true)
13351 if (get_token() == token_type::value_separator)
13352 {
13353 get_token();
13354
13355 // if ignore_trailing_commas and last_token is }, we can continue to "closing }"
13356 if (!(ignore_trailing_commas && last_token == token_type::end_object))
13357 {
13358 // parse key
13359 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13360 {
13361 return sax->parse_error(m_lexer.get_position(),
13362 m_lexer.get_token_string(),
13363 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13364 }
13365
13366 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13367 {
13368 return false;
13369 }
13370
13371 // parse separator (:)
13372 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13373 {
13374 return sax->parse_error(m_lexer.get_position(),
13375 m_lexer.get_token_string(),
13376 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13377 }
13378
13379 // parse values
13380 get_token();
13381 continue;
13382 }
13383 }
13384
13385 // closing }
13386 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
13387 {
13388 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13389 {
13390 return false;
13391 }
13392
13393 // We are done with this object. Before we can parse a
13394 // new value, we need to evaluate the new state first.
13395 // By setting skip_to_state_evaluation to false, we
13396 // are effectively jumping to the beginning of this if.
13397 JSON_ASSERT(!states.empty());
13398 states.pop_back();
13399 skip_to_state_evaluation = true;
13400 continue;
13401 }
13402
13403 return sax->parse_error(m_lexer.get_position(),
13404 m_lexer.get_token_string(),
13405 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
13406 }
13407 }
13408
13410 token_type get_token()
13411 {
13412 return last_token = m_lexer.scan();
13413 }
13414
13415 std::string exception_message(const token_type expected, const std::string& context)
13416 {
13417 std::string error_msg = "syntax error ";
13418
13419 if (!context.empty())
13420 {
13421 error_msg += concat("while parsing ", context, ' ');
13422 }
13423
13424 error_msg += "- ";
13425
13426 if (last_token == token_type::parse_error)
13427 {
13428 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
13429 m_lexer.get_token_string(), '\'');
13430 }
13431 else
13432 {
13433 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
13434 }
13435
13436 if (expected != token_type::uninitialized)
13437 {
13438 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
13439 }
13440
13441 return error_msg;
13442 }
13443
13444 private:
13446 const parser_callback_t<BasicJsonType> callback = nullptr;
13448 token_type last_token = token_type::uninitialized;
13450 lexer_t m_lexer;
13452 const bool allow_exceptions = true;
13454 const bool ignore_trailing_commas = false;
13455};
13456
13457} // namespace detail
13458NLOHMANN_JSON_NAMESPACE_END
13459
13460// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13461// __ _____ _____ _____
13462// __| | __| | | | JSON for Modern C++
13463// | | |__ | | | | | | version 3.12.0
13464// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13465//
13466// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13467// SPDX-License-Identifier: MIT
13468
13469
13470
13471// #include <nlohmann/detail/abi_macros.hpp>
13472
13473// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13474// __ _____ _____ _____
13475// __| | __| | | | JSON for Modern C++
13476// | | |__ | | | | | | version 3.12.0
13477// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13478//
13479// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13480// SPDX-License-Identifier: MIT
13481
13482
13483
13484#include <cstddef> // ptrdiff_t
13485#include <limits> // numeric_limits
13486
13487// #include <nlohmann/detail/macro_scope.hpp>
13488
13489
13490NLOHMANN_JSON_NAMESPACE_BEGIN
13491namespace detail
13492{
13493
13494/*
13495@brief an iterator for primitive JSON types
13496
13497This class models an iterator for primitive JSON types (boolean, number,
13498string). Its only purpose is to allow the iterator/const_iterator classes
13499to "iterate" over primitive values. Internally, the iterator is modeled by
13500a `difference_type` variable. Value begin_value (`0`) models the begin and
13501end_value (`1`) models past the end.
13502*/
13503class primitive_iterator_t
13504{
13505 private:
13506 using difference_type = std::ptrdiff_t;
13507 static constexpr difference_type begin_value = 0;
13508 static constexpr difference_type end_value = begin_value + 1;
13509
13510 JSON_PRIVATE_UNLESS_TESTED:
13512 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
13513
13514 public:
13515 constexpr difference_type get_value() const noexcept
13516 {
13517 return m_it;
13518 }
13519
13521 void set_begin() noexcept
13522 {
13523 m_it = begin_value;
13524 }
13525
13527 void set_end() noexcept
13528 {
13529 m_it = end_value;
13530 }
13531
13533 constexpr bool is_begin() const noexcept
13534 {
13535 return m_it == begin_value;
13536 }
13537
13539 constexpr bool is_end() const noexcept
13540 {
13541 return m_it == end_value;
13542 }
13543
13544 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13545 {
13546 return lhs.m_it == rhs.m_it;
13547 }
13548
13549 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13550 {
13551 return lhs.m_it < rhs.m_it;
13552 }
13553
13554 primitive_iterator_t operator+(difference_type n) noexcept
13555 {
13556 auto result = *this;
13557 result += n;
13558 return result;
13559 }
13560
13561 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13562 {
13563 return lhs.m_it - rhs.m_it;
13564 }
13565
13566 primitive_iterator_t& operator++() noexcept
13567 {
13568 ++m_it;
13569 return *this;
13570 }
13571
13572 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
13573 {
13574 auto result = *this;
13575 ++m_it;
13576 return result;
13577 }
13578
13579 primitive_iterator_t& operator--() noexcept
13580 {
13581 --m_it;
13582 return *this;
13583 }
13584
13585 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
13586 {
13587 auto result = *this;
13588 --m_it;
13589 return result;
13590 }
13591
13592 primitive_iterator_t& operator+=(difference_type n) noexcept
13593 {
13594 m_it += n;
13595 return *this;
13596 }
13597
13598 primitive_iterator_t& operator-=(difference_type n) noexcept
13599 {
13600 m_it -= n;
13601 return *this;
13602 }
13603};
13604
13605} // namespace detail
13606NLOHMANN_JSON_NAMESPACE_END
13607
13608
13609NLOHMANN_JSON_NAMESPACE_BEGIN
13610namespace detail
13611{
13612
13619template<typename BasicJsonType> struct internal_iterator
13620{
13622 typename BasicJsonType::object_t::iterator object_iterator {};
13624 typename BasicJsonType::array_t::iterator array_iterator {};
13626 primitive_iterator_t primitive_iterator {};
13627};
13628
13629} // namespace detail
13630NLOHMANN_JSON_NAMESPACE_END
13631
13632// #include <nlohmann/detail/iterators/iter_impl.hpp>
13633// __ _____ _____ _____
13634// __| | __| | | | JSON for Modern C++
13635// | | |__ | | | | | | version 3.12.0
13636// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13637//
13638// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13639// SPDX-License-Identifier: MIT
13640
13641
13642
13643#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
13644#include <type_traits> // conditional, is_const, remove_const
13645
13646// #include <nlohmann/detail/exceptions.hpp>
13647
13648// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13649
13650// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13651
13652// #include <nlohmann/detail/macro_scope.hpp>
13653
13654// #include <nlohmann/detail/meta/cpp_future.hpp>
13655
13656// #include <nlohmann/detail/meta/type_traits.hpp>
13657
13658// #include <nlohmann/detail/value_t.hpp>
13659
13660
13661NLOHMANN_JSON_NAMESPACE_BEGIN
13662namespace detail
13663{
13664
13665// forward declare to be able to friend it later on
13666template<typename IteratorType> class iteration_proxy;
13667template<typename IteratorType> class iteration_proxy_value;
13668
13685template<typename BasicJsonType>
13686class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
13687{
13689 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
13691 friend other_iter_impl;
13692 friend BasicJsonType;
13695
13696 using object_t = typename BasicJsonType::object_t;
13697 using array_t = typename BasicJsonType::array_t;
13698 // make sure BasicJsonType is basic_json or const basic_json
13700 "iter_impl only accepts (const) basic_json");
13701 // superficial check for the LegacyBidirectionalIterator named requirement
13702 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
13703 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
13704 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
13705
13706 public:
13712 using iterator_category = std::bidirectional_iterator_tag;
13713
13715 using value_type = typename BasicJsonType::value_type;
13717 using difference_type = typename BasicJsonType::difference_type;
13719 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
13720 typename BasicJsonType::const_pointer,
13721 typename BasicJsonType::pointer>::type;
13724 typename std::conditional<std::is_const<BasicJsonType>::value,
13725 typename BasicJsonType::const_reference,
13726 typename BasicJsonType::reference>::type;
13727
13728 iter_impl() = default;
13729 ~iter_impl() = default;
13730 iter_impl(iter_impl&&) noexcept = default;
13731 iter_impl& operator=(iter_impl&&) noexcept = default;
13732
13739 explicit iter_impl(pointer object) noexcept : m_object(object)
13740 {
13741 JSON_ASSERT(m_object != nullptr);
13742
13743 switch (m_object->m_data.m_type)
13744 {
13745 case value_t::object:
13746 {
13747 m_it.object_iterator = typename object_t::iterator();
13748 break;
13749 }
13750
13751 case value_t::array:
13752 {
13753 m_it.array_iterator = typename array_t::iterator();
13754 break;
13755 }
13756
13757 case value_t::null:
13758 case value_t::string:
13759 case value_t::boolean:
13760 case value_t::number_integer:
13761 case value_t::number_unsigned:
13762 case value_t::number_float:
13763 case value_t::binary:
13764 case value_t::discarded:
13765 default:
13766 {
13767 m_it.primitive_iterator = primitive_iterator_t();
13768 break;
13769 }
13770 }
13771 }
13772
13790 : m_object(other.m_object), m_it(other.m_it)
13791 {}
13792
13800 {
13801 if (&other != this)
13802 {
13803 m_object = other.m_object;
13804 m_it = other.m_it;
13805 }
13806 return *this;
13807 }
13808
13814 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13815 : m_object(other.m_object), m_it(other.m_it)
13816 {}
13817
13824 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13825 {
13826 m_object = other.m_object;
13827 m_it = other.m_it;
13828 return *this;
13829 }
13830
13831 JSON_PRIVATE_UNLESS_TESTED:
13836 void set_begin() noexcept
13837 {
13838 JSON_ASSERT(m_object != nullptr);
13839
13840 switch (m_object->m_data.m_type)
13841 {
13842 case value_t::object:
13843 {
13844 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13845 break;
13846 }
13847
13848 case value_t::array:
13849 {
13850 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13851 break;
13852 }
13853
13854 case value_t::null:
13855 {
13856 // set to end so begin()==end() is true: null is empty
13857 m_it.primitive_iterator.set_end();
13858 break;
13859 }
13860
13861 case value_t::string:
13862 case value_t::boolean:
13863 case value_t::number_integer:
13864 case value_t::number_unsigned:
13865 case value_t::number_float:
13866 case value_t::binary:
13867 case value_t::discarded:
13868 default:
13869 {
13870 m_it.primitive_iterator.set_begin();
13871 break;
13872 }
13873 }
13874 }
13875
13880 void set_end() noexcept
13881 {
13882 JSON_ASSERT(m_object != nullptr);
13883
13884 switch (m_object->m_data.m_type)
13885 {
13886 case value_t::object:
13887 {
13888 m_it.object_iterator = m_object->m_data.m_value.object->end();
13889 break;
13890 }
13891
13892 case value_t::array:
13893 {
13894 m_it.array_iterator = m_object->m_data.m_value.array->end();
13895 break;
13896 }
13897
13898 case value_t::null:
13899 case value_t::string:
13900 case value_t::boolean:
13901 case value_t::number_integer:
13902 case value_t::number_unsigned:
13903 case value_t::number_float:
13904 case value_t::binary:
13905 case value_t::discarded:
13906 default:
13907 {
13908 m_it.primitive_iterator.set_end();
13909 break;
13910 }
13911 }
13912 }
13913
13914 public:
13920 {
13921 JSON_ASSERT(m_object != nullptr);
13922
13923 switch (m_object->m_data.m_type)
13924 {
13925 case value_t::object:
13926 {
13927 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13928 return m_it.object_iterator->second;
13929 }
13930
13931 case value_t::array:
13932 {
13933 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13934 return *m_it.array_iterator;
13935 }
13936
13937 case value_t::null:
13938 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13939
13940 case value_t::string:
13941 case value_t::boolean:
13942 case value_t::number_integer:
13943 case value_t::number_unsigned:
13944 case value_t::number_float:
13945 case value_t::binary:
13946 case value_t::discarded:
13947 default:
13948 {
13949 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13950 {
13951 return *m_object;
13952 }
13953
13954 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13955 }
13956 }
13957 }
13958
13964 {
13965 JSON_ASSERT(m_object != nullptr);
13966
13967 switch (m_object->m_data.m_type)
13968 {
13969 case value_t::object:
13970 {
13971 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13972 return &(m_it.object_iterator->second);
13973 }
13974
13975 case value_t::array:
13976 {
13977 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13978 return &*m_it.array_iterator;
13979 }
13980
13981 case value_t::null:
13982 case value_t::string:
13983 case value_t::boolean:
13984 case value_t::number_integer:
13985 case value_t::number_unsigned:
13986 case value_t::number_float:
13987 case value_t::binary:
13988 case value_t::discarded:
13989 default:
13990 {
13991 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13992 {
13993 return m_object;
13994 }
13995
13996 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13997 }
13998 }
13999 }
14000
14005 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
14006 {
14007 auto result = *this;
14008 ++(*this);
14009 return result;
14010 }
14011
14017 {
14018 JSON_ASSERT(m_object != nullptr);
14019
14020 switch (m_object->m_data.m_type)
14021 {
14022 case value_t::object:
14023 {
14024 std::advance(m_it.object_iterator, 1);
14025 break;
14026 }
14027
14028 case value_t::array:
14029 {
14030 std::advance(m_it.array_iterator, 1);
14031 break;
14032 }
14033
14034 case value_t::null:
14035 case value_t::string:
14036 case value_t::boolean:
14037 case value_t::number_integer:
14038 case value_t::number_unsigned:
14039 case value_t::number_float:
14040 case value_t::binary:
14041 case value_t::discarded:
14042 default:
14043 {
14044 ++m_it.primitive_iterator;
14045 break;
14046 }
14047 }
14048
14049 return *this;
14050 }
14051
14056 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
14057 {
14058 auto result = *this;
14059 --(*this);
14060 return result;
14061 }
14062
14068 {
14069 JSON_ASSERT(m_object != nullptr);
14070
14071 switch (m_object->m_data.m_type)
14072 {
14073 case value_t::object:
14074 {
14075 std::advance(m_it.object_iterator, -1);
14076 break;
14077 }
14078
14079 case value_t::array:
14080 {
14081 std::advance(m_it.array_iterator, -1);
14082 break;
14083 }
14084
14085 case value_t::null:
14086 case value_t::string:
14087 case value_t::boolean:
14088 case value_t::number_integer:
14089 case value_t::number_unsigned:
14090 case value_t::number_float:
14091 case value_t::binary:
14092 case value_t::discarded:
14093 default:
14094 {
14095 --m_it.primitive_iterator;
14096 break;
14097 }
14098 }
14099
14100 return *this;
14101 }
14102
14107 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 >
14108 bool operator==(const IterImpl& other) const
14109 {
14110 // if objects are not the same, the comparison is undefined
14111 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14112 {
14113 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14114 }
14115
14116 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14117 if (m_object == nullptr)
14118 {
14119 return true;
14120 }
14121
14122 switch (m_object->m_data.m_type)
14123 {
14124 case value_t::object:
14125 return (m_it.object_iterator == other.m_it.object_iterator);
14126
14127 case value_t::array:
14128 return (m_it.array_iterator == other.m_it.array_iterator);
14129
14130 case value_t::null:
14131 case value_t::string:
14132 case value_t::boolean:
14133 case value_t::number_integer:
14134 case value_t::number_unsigned:
14135 case value_t::number_float:
14136 case value_t::binary:
14137 case value_t::discarded:
14138 default:
14139 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
14140 }
14141 }
14142
14147 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 >
14148 bool operator!=(const IterImpl& other) const
14149 {
14150 return !operator==(other);
14151 }
14152
14157 bool operator<(const iter_impl& other) const
14158 {
14159 // if objects are not the same, the comparison is undefined
14160 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14161 {
14162 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14163 }
14164
14165 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14166 if (m_object == nullptr)
14167 {
14168 // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false
14169 return false;
14170 }
14171
14172 switch (m_object->m_data.m_type)
14173 {
14174 case value_t::object:
14175 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
14176
14177 case value_t::array:
14178 return (m_it.array_iterator < other.m_it.array_iterator);
14179
14180 case value_t::null:
14181 case value_t::string:
14182 case value_t::boolean:
14183 case value_t::number_integer:
14184 case value_t::number_unsigned:
14185 case value_t::number_float:
14186 case value_t::binary:
14187 case value_t::discarded:
14188 default:
14189 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
14190 }
14191 }
14192
14197 bool operator<=(const iter_impl& other) const
14198 {
14199 return !other.operator < (*this);
14200 }
14201
14206 bool operator>(const iter_impl& other) const
14207 {
14208 return !operator<=(other);
14209 }
14210
14215 bool operator>=(const iter_impl& other) const
14216 {
14217 return !operator<(other);
14218 }
14219
14225 {
14226 JSON_ASSERT(m_object != nullptr);
14227
14228 switch (m_object->m_data.m_type)
14229 {
14230 case value_t::object:
14231 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14232
14233 case value_t::array:
14234 {
14235 std::advance(m_it.array_iterator, i);
14236 break;
14237 }
14238
14239 case value_t::null:
14240 case value_t::string:
14241 case value_t::boolean:
14242 case value_t::number_integer:
14243 case value_t::number_unsigned:
14244 case value_t::number_float:
14245 case value_t::binary:
14246 case value_t::discarded:
14247 default:
14248 {
14249 m_it.primitive_iterator += i;
14250 break;
14251 }
14252 }
14253
14254 return *this;
14255 }
14256
14262 {
14263 return operator+=(-i);
14264 }
14265
14271 {
14272 auto result = *this;
14273 result += i;
14274 return result;
14275 }
14276
14282 {
14283 auto result = it;
14284 result += i;
14285 return result;
14286 }
14287
14293 {
14294 auto result = *this;
14295 result -= i;
14296 return result;
14297 }
14298
14304 {
14305 JSON_ASSERT(m_object != nullptr);
14306
14307 switch (m_object->m_data.m_type)
14308 {
14309 case value_t::object:
14310 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14311
14312 case value_t::array:
14313 return m_it.array_iterator - other.m_it.array_iterator;
14314
14315 case value_t::null:
14316 case value_t::string:
14317 case value_t::boolean:
14318 case value_t::number_integer:
14319 case value_t::number_unsigned:
14320 case value_t::number_float:
14321 case value_t::binary:
14322 case value_t::discarded:
14323 default:
14324 return m_it.primitive_iterator - other.m_it.primitive_iterator;
14325 }
14326 }
14327
14333 {
14334 JSON_ASSERT(m_object != nullptr);
14335
14336 switch (m_object->m_data.m_type)
14337 {
14338 case value_t::object:
14339 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
14340
14341 case value_t::array:
14342 return *std::next(m_it.array_iterator, n);
14343
14344 case value_t::null:
14345 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14346
14347 case value_t::string:
14348 case value_t::boolean:
14349 case value_t::number_integer:
14350 case value_t::number_unsigned:
14351 case value_t::number_float:
14352 case value_t::binary:
14353 case value_t::discarded:
14354 default:
14355 {
14356 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
14357 {
14358 return *m_object;
14359 }
14360
14361 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14362 }
14363 }
14364 }
14365
14370 const typename object_t::key_type& key() const
14371 {
14372 JSON_ASSERT(m_object != nullptr);
14373
14374 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
14375 {
14376 return m_it.object_iterator->first;
14377 }
14378
14379 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
14380 }
14381
14387 {
14388 return operator*();
14389 }
14390
14391 JSON_PRIVATE_UNLESS_TESTED:
14393 pointer m_object = nullptr;
14396};
14397
14398} // namespace detail
14399NLOHMANN_JSON_NAMESPACE_END
14400
14401// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
14402
14403// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
14404// __ _____ _____ _____
14405// __| | __| | | | JSON for Modern C++
14406// | | |__ | | | | | | version 3.12.0
14407// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14408//
14409// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14410// SPDX-License-Identifier: MIT
14411
14412
14413
14414#include <cstddef> // ptrdiff_t
14415#include <iterator> // reverse_iterator
14416#include <utility> // declval
14417
14418// #include <nlohmann/detail/abi_macros.hpp>
14419
14420
14421NLOHMANN_JSON_NAMESPACE_BEGIN
14422namespace detail
14423{
14424
14426// reverse_iterator //
14428
14447template<typename Base>
14448class json_reverse_iterator : public std::reverse_iterator<Base>
14449{
14450 public:
14451 using difference_type = std::ptrdiff_t;
14453 using base_iterator = std::reverse_iterator<Base>;
14455 using reference = typename Base::reference;
14456
14458 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
14459 : base_iterator(it) {}
14460
14462 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
14463
14465 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
14466 {
14467 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
14468 }
14469
14472 {
14473 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
14474 }
14475
14477 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
14478 {
14479 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
14480 }
14481
14484 {
14485 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
14486 }
14487
14490 {
14491 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
14492 }
14493
14495 json_reverse_iterator operator+(difference_type i) const
14496 {
14497 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
14498 }
14499
14501 json_reverse_iterator operator-(difference_type i) const
14502 {
14503 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
14504 }
14505
14507 difference_type operator-(const json_reverse_iterator& other) const
14508 {
14509 return base_iterator(*this) - base_iterator(other);
14510 }
14511
14513 reference operator[](difference_type n) const
14514 {
14515 return *(this->operator+(n));
14516 }
14517
14519 auto key() const -> decltype(std::declval<Base>().key())
14520 {
14521 auto it = --this->base();
14522 return it.key();
14523 }
14524
14527 {
14528 auto it = --this->base();
14529 return it.operator * ();
14530 }
14531};
14532
14533} // namespace detail
14534NLOHMANN_JSON_NAMESPACE_END
14535
14536// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
14537
14538// #include <nlohmann/detail/json_custom_base_class.hpp>
14539// __ _____ _____ _____
14540// __| | __| | | | JSON for Modern C++
14541// | | |__ | | | | | | version 3.12.0
14542// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14543//
14544// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14545// SPDX-License-Identifier: MIT
14546
14547
14548
14549#include <type_traits> // conditional, is_same
14550
14551// #include <nlohmann/detail/abi_macros.hpp>
14552
14553
14554NLOHMANN_JSON_NAMESPACE_BEGIN
14555namespace detail
14556{
14557
14569
14570template<class T>
14571using json_base_class = typename std::conditional <
14572 std::is_same<T, void>::value,
14574 T
14575 >::type;
14576
14577} // namespace detail
14578NLOHMANN_JSON_NAMESPACE_END
14579
14580// #include <nlohmann/detail/json_pointer.hpp>
14581// __ _____ _____ _____
14582// __| | __| | | | JSON for Modern C++
14583// | | |__ | | | | | | version 3.12.0
14584// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14585//
14586// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14587// SPDX-License-Identifier: MIT
14588
14589
14590
14591#include <algorithm> // all_of
14592#include <cctype> // isdigit
14593#include <cerrno> // errno, ERANGE
14594#include <cstdlib> // strtoull
14595#ifndef JSON_NO_IO
14596 #include <iosfwd> // ostream
14597#endif // JSON_NO_IO
14598#include <limits> // max
14599#include <numeric> // accumulate
14600#include <string> // string
14601#include <utility> // move
14602#include <vector> // vector
14603
14604// #include <nlohmann/detail/exceptions.hpp>
14605
14606// #include <nlohmann/detail/macro_scope.hpp>
14607
14608// #include <nlohmann/detail/string_concat.hpp>
14609
14610// #include <nlohmann/detail/string_escape.hpp>
14611
14612// #include <nlohmann/detail/value_t.hpp>
14613
14614
14615NLOHMANN_JSON_NAMESPACE_BEGIN
14616
14619template<typename RefStringType>
14621{
14622 // allow basic_json to access private members
14623 NLOHMANN_BASIC_JSON_TPL_DECLARATION
14624 friend class basic_json;
14625
14626 template<typename>
14627 friend class json_pointer;
14628
14629 template<typename T>
14630 struct string_t_helper
14631 {
14632 using type = T;
14633 };
14634
14635 NLOHMANN_BASIC_JSON_TPL_DECLARATION
14636 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
14637 {
14638 using type = StringType;
14639 };
14640
14641 public:
14642 // for backwards compatibility accept BasicJsonType
14643 using string_t = typename string_t_helper<RefStringType>::type;
14644
14647 explicit json_pointer(const string_t& s = "")
14648 : reference_tokens(split(s))
14649 {}
14650
14653 string_t to_string() const
14654 {
14655 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
14656 string_t{},
14657 [](const string_t& a, const string_t& b)
14658 {
14659 return detail::concat(a, '/', detail::escape(b));
14660 });
14661 }
14662
14665 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
14666 operator string_t() const
14667 {
14668 return to_string();
14669 }
14670
14671#ifndef JSON_NO_IO
14674 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
14675 {
14676 o << ptr.to_string();
14677 return o;
14678 }
14679#endif
14680
14684 {
14685 reference_tokens.insert(reference_tokens.end(),
14686 ptr.reference_tokens.begin(),
14687 ptr.reference_tokens.end());
14688 return *this;
14689 }
14690
14693 json_pointer& operator/=(string_t token)
14694 {
14695 push_back(std::move(token));
14696 return *this;
14697 }
14698
14701 json_pointer& operator/=(std::size_t array_idx)
14702 {
14703 return *this /= std::to_string(array_idx);
14704 }
14705
14709 const json_pointer& rhs)
14710 {
14711 return json_pointer(lhs) /= rhs;
14712 }
14713
14716 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
14717 {
14718 return json_pointer(lhs) /= std::move(token);
14719 }
14720
14723 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
14724 {
14725 return json_pointer(lhs) /= array_idx;
14726 }
14727
14731 {
14732 if (empty())
14733 {
14734 return *this;
14735 }
14736
14737 json_pointer res = *this;
14738 res.pop_back();
14739 return res;
14740 }
14741
14745 {
14746 if (JSON_HEDLEY_UNLIKELY(empty()))
14747 {
14748 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14749 }
14750
14751 reference_tokens.pop_back();
14752 }
14753
14756 const string_t& back() const
14757 {
14758 if (JSON_HEDLEY_UNLIKELY(empty()))
14759 {
14760 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14761 }
14762
14763 return reference_tokens.back();
14764 }
14765
14768 void push_back(const string_t& token)
14769 {
14770 reference_tokens.push_back(token);
14771 }
14772
14775 void push_back(string_t&& token)
14776 {
14777 reference_tokens.push_back(std::move(token));
14778 }
14779
14782 bool empty() const noexcept
14783 {
14784 return reference_tokens.empty();
14785 }
14786
14787 private:
14798 template<typename BasicJsonType>
14799 static typename BasicJsonType::size_type array_index(const string_t& s)
14800 {
14801 using size_type = typename BasicJsonType::size_type;
14802
14803 // error condition (cf. RFC 6901, Sect. 4)
14804 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14805 {
14806 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14807 }
14808
14809 // error condition (cf. RFC 6901, Sect. 4)
14810 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14811 {
14812 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14813 }
14814
14815 const char* p = s.c_str();
14816 char* p_end = nullptr; // NOLINT(misc-const-correctness)
14817 errno = 0; // strtoull doesn't reset errno
14818 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14819 if (p == p_end // invalid input or empty string
14820 || errno == ERANGE // out of range
14821 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14822 {
14823 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14824 }
14825
14826 // only triggered on special platforms (like 32bit), see also
14827 // https://github.com/nlohmann/json/pull/2203
14828 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14829 {
14830 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14831 }
14832
14833 return static_cast<size_type>(res);
14834 }
14835
14836 JSON_PRIVATE_UNLESS_TESTED:
14837 json_pointer top() const
14838 {
14839 if (JSON_HEDLEY_UNLIKELY(empty()))
14840 {
14841 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14842 }
14843
14844 json_pointer result = *this;
14845 result.reference_tokens = {reference_tokens[0]};
14846 return result;
14847 }
14848
14849 private:
14858 template<typename BasicJsonType>
14859 BasicJsonType& get_and_create(BasicJsonType& j) const
14860 {
14861 auto* result = &j;
14862
14863 // in case no reference tokens exist, return a reference to the JSON value
14864 // j which will be overwritten by a primitive value
14865 for (const auto& reference_token : reference_tokens)
14866 {
14867 switch (result->type())
14868 {
14870 {
14871 if (reference_token == "0")
14872 {
14873 // start a new array if the reference token is 0
14874 result = &result->operator[](0);
14875 }
14876 else
14877 {
14878 // start a new object otherwise
14879 result = &result->operator[](reference_token);
14880 }
14881 break;
14882 }
14883
14885 {
14886 // create an entry in the object
14887 result = &result->operator[](reference_token);
14888 break;
14889 }
14890
14892 {
14893 // create an entry in the array
14894 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14895 break;
14896 }
14897
14898 /*
14899 The following code is only reached if there exists a reference
14900 token _and_ the current value is primitive. In this case, we have
14901 an error situation, because primitive values may only occur as
14902 a single value; that is, with an empty list of reference tokens.
14903 */
14911 default:
14912 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14913 }
14914 }
14915
14916 return *result;
14917 }
14918
14938 template<typename BasicJsonType>
14939 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14940 {
14941 for (const auto& reference_token : reference_tokens)
14942 {
14943 // convert null values to arrays or objects before continuing
14944 if (ptr->is_null())
14945 {
14946 // check if the reference token is a number
14947 const bool nums =
14948 std::all_of(reference_token.begin(), reference_token.end(),
14949 [](const unsigned char x)
14950 {
14951 return std::isdigit(x);
14952 });
14953
14954 // change value to an array for numbers or "-" or to object otherwise
14955 *ptr = (nums || reference_token == "-")
14957 : detail::value_t::object;
14958 }
14959
14960 switch (ptr->type())
14961 {
14963 {
14964 // use unchecked object access
14965 ptr = &ptr->operator[](reference_token);
14966 break;
14967 }
14968
14970 {
14971 if (reference_token == "-")
14972 {
14973 // explicitly treat "-" as index beyond the end
14974 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14975 }
14976 else
14977 {
14978 // convert array index to number; unchecked access
14979 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14980 }
14981 break;
14982 }
14983
14992 default:
14993 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14994 }
14995 }
14996
14997 return *ptr;
14998 }
14999
15006 template<typename BasicJsonType>
15007 BasicJsonType& get_checked(BasicJsonType* ptr) const
15008 {
15009 for (const auto& reference_token : reference_tokens)
15010 {
15011 switch (ptr->type())
15012 {
15014 {
15015 // note: at performs range check
15016 ptr = &ptr->at(reference_token);
15017 break;
15018 }
15019
15021 {
15022 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15023 {
15024 // "-" always fails the range check
15025 JSON_THROW(detail::out_of_range::create(402, detail::concat(
15026 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15027 ") is out of range"), ptr));
15028 }
15029
15030 // note: at performs range check
15031 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15032 break;
15033 }
15034
15043 default:
15044 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15045 }
15046 }
15047
15048 return *ptr;
15049 }
15050
15064 template<typename BasicJsonType>
15065 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
15066 {
15067 for (const auto& reference_token : reference_tokens)
15068 {
15069 switch (ptr->type())
15070 {
15072 {
15073 // use unchecked object access
15074 ptr = &ptr->operator[](reference_token);
15075 break;
15076 }
15077
15079 {
15080 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15081 {
15082 // "-" cannot be used for const access
15083 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));
15084 }
15085
15086 // use unchecked array access
15087 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
15088 break;
15089 }
15090
15099 default:
15100 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15101 }
15102 }
15103
15104 return *ptr;
15105 }
15106
15113 template<typename BasicJsonType>
15114 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
15115 {
15116 for (const auto& reference_token : reference_tokens)
15117 {
15118 switch (ptr->type())
15119 {
15121 {
15122 // note: at performs range check
15123 ptr = &ptr->at(reference_token);
15124 break;
15125 }
15126
15128 {
15129 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15130 {
15131 // "-" always fails the range check
15132 JSON_THROW(detail::out_of_range::create(402, detail::concat(
15133 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15134 ") is out of range"), ptr));
15135 }
15136
15137 // note: at performs range check
15138 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15139 break;
15140 }
15141
15150 default:
15151 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15152 }
15153 }
15154
15155 return *ptr;
15156 }
15157
15162 template<typename BasicJsonType>
15163 bool contains(const BasicJsonType* ptr) const
15164 {
15165 for (const auto& reference_token : reference_tokens)
15166 {
15167 switch (ptr->type())
15168 {
15170 {
15171 if (!ptr->contains(reference_token))
15172 {
15173 // we did not find the key in the object
15174 return false;
15175 }
15176
15177 ptr = &ptr->operator[](reference_token);
15178 break;
15179 }
15180
15182 {
15183 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15184 {
15185 // "-" always fails the range check
15186 return false;
15187 }
15188 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
15189 {
15190 // invalid char
15191 return false;
15192 }
15193 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
15194 {
15195 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
15196 {
15197 // the first char should be between '1' and '9'
15198 return false;
15199 }
15200 for (std::size_t i = 1; i < reference_token.size(); i++)
15201 {
15202 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
15203 {
15204 // other char should be between '0' and '9'
15205 return false;
15206 }
15207 }
15208 }
15209
15210 const auto idx = array_index<BasicJsonType>(reference_token);
15211 if (idx >= ptr->size())
15212 {
15213 // index out of range
15214 return false;
15215 }
15216
15217 ptr = &ptr->operator[](idx);
15218 break;
15219 }
15220
15229 default:
15230 {
15231 // we do not expect primitive values if there is still a
15232 // reference token to process
15233 return false;
15234 }
15235 }
15236 }
15237
15238 // no reference token left means we found a primitive value
15239 return true;
15240 }
15241
15251 static std::vector<string_t> split(const string_t& reference_string)
15252 {
15253 std::vector<string_t> result;
15254
15255 // special case: empty reference string -> no reference tokens
15256 if (reference_string.empty())
15257 {
15258 return result;
15259 }
15260
15261 // check if a nonempty reference string begins with slash
15262 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
15263 {
15264 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
15265 }
15266
15267 // extract the reference tokens:
15268 // - slash: position of the last read slash (or end of string)
15269 // - start: position after the previous slash
15270 for (
15271 // search for the first slash after the first character
15272 std::size_t slash = reference_string.find_first_of('/', 1),
15273 // set the beginning of the first reference token
15274 start = 1;
15275 // we can stop if start == 0 (if slash == string_t::npos)
15276 start != 0;
15277 // set the beginning of the next reference token
15278 // (will eventually be 0 if slash == string_t::npos)
15279 start = (slash == string_t::npos) ? 0 : slash + 1,
15280 // find next slash
15281 slash = reference_string.find_first_of('/', start))
15282 {
15283 // use the text between the beginning of the reference token
15284 // (start) and the last slash (slash).
15285 auto reference_token = reference_string.substr(start, slash - start);
15286
15287 // check reference tokens are properly escaped
15288 for (std::size_t pos = reference_token.find_first_of('~');
15289 pos != string_t::npos;
15290 pos = reference_token.find_first_of('~', pos + 1))
15291 {
15292 JSON_ASSERT(reference_token[pos] == '~');
15293
15294 // ~ must be followed by 0 or 1
15295 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
15296 (reference_token[pos + 1] != '0' &&
15297 reference_token[pos + 1] != '1')))
15298 {
15299 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
15300 }
15301 }
15302
15303 // finally, store the reference token
15304 detail::unescape(reference_token);
15305 result.push_back(reference_token);
15306 }
15307
15308 return result;
15309 }
15310
15311 private:
15319 template<typename BasicJsonType>
15320 static void flatten(const string_t& reference_string,
15321 const BasicJsonType& value,
15322 BasicJsonType& result)
15323 {
15324 switch (value.type())
15325 {
15327 {
15328 if (value.m_data.m_value.array->empty())
15329 {
15330 // flatten empty array as null
15331 result[reference_string] = nullptr;
15332 }
15333 else
15334 {
15335 // iterate array and use index as a reference string
15336 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
15337 {
15338 flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
15339 value.m_data.m_value.array->operator[](i), result);
15340 }
15341 }
15342 break;
15343 }
15344
15346 {
15347 if (value.m_data.m_value.object->empty())
15348 {
15349 // flatten empty object as null
15350 result[reference_string] = nullptr;
15351 }
15352 else
15353 {
15354 // iterate object and use keys as reference string
15355 for (const auto& element : *value.m_data.m_value.object)
15356 {
15357 flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
15358 }
15359 }
15360 break;
15361 }
15362
15371 default:
15372 {
15373 // add a primitive value with its reference string
15374 result[reference_string] = value;
15375 break;
15376 }
15377 }
15378 }
15379
15390 template<typename BasicJsonType>
15391 static BasicJsonType
15392 unflatten(const BasicJsonType& value)
15393 {
15394 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
15395 {
15396 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
15397 }
15398
15399 BasicJsonType result;
15400
15401 // iterate the JSON object values
15402 for (const auto& element : *value.m_data.m_value.object)
15403 {
15404 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
15405 {
15406 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
15407 }
15408
15409 // Assign the value to the reference pointed to by JSON pointer. Note
15410 // that if the JSON pointer is "" (i.e., points to the whole value),
15411 // function get_and_create returns a reference to the result itself.
15412 // An assignment will then create a primitive value.
15413 json_pointer(element.first).get_and_create(result) = element.second;
15414 }
15415
15416 return result;
15417 }
15418
15419 // can't use the conversion operator because of ambiguity
15420 json_pointer<string_t> convert() const&
15421 {
15423 result.reference_tokens = reference_tokens;
15424 return result;
15425 }
15426
15427 json_pointer<string_t> convert()&&
15428 {
15430 result.reference_tokens = std::move(reference_tokens);
15431 return result;
15432 }
15433
15434 public:
15435#if JSON_HAS_THREE_WAY_COMPARISON
15438 template<typename RefStringTypeRhs>
15439 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
15440 {
15441 return reference_tokens == rhs.reference_tokens;
15442 }
15443
15446 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
15447 bool operator==(const string_t& rhs) const
15448 {
15449 return *this == json_pointer(rhs);
15450 }
15451
15453 template<typename RefStringTypeRhs>
15454 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
15455 {
15456 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
15457 }
15458#else
15461 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15462 // NOLINTNEXTLINE(readability-redundant-declaration)
15463 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15464 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15465
15468 template<typename RefStringTypeLhs, typename StringType>
15469 // NOLINTNEXTLINE(readability-redundant-declaration)
15470 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15471 const StringType& rhs);
15472
15475 template<typename RefStringTypeRhs, typename StringType>
15476 // NOLINTNEXTLINE(readability-redundant-declaration)
15477 friend bool operator==(const StringType& lhs,
15479
15482 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15483 // NOLINTNEXTLINE(readability-redundant-declaration)
15484 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15485 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15486
15489 template<typename RefStringTypeLhs, typename StringType>
15490 // NOLINTNEXTLINE(readability-redundant-declaration)
15491 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15492 const StringType& rhs);
15493
15496 template<typename RefStringTypeRhs, typename StringType>
15497 // NOLINTNEXTLINE(readability-redundant-declaration)
15498 friend bool operator!=(const StringType& lhs,
15500
15502 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15503 // NOLINTNEXTLINE(readability-redundant-declaration)
15504 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
15505 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15506#endif
15507
15508 private:
15510 std::vector<string_t> reference_tokens;
15511};
15512
15513#if !JSON_HAS_THREE_WAY_COMPARISON
15514// functions cannot be defined inside the class due to ODR violations
15515template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15517 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15518{
15519 return lhs.reference_tokens == rhs.reference_tokens;
15520}
15521
15522template<typename RefStringTypeLhs,
15523 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15524JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
15525inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15526 const StringType& rhs)
15527{
15528 return lhs == json_pointer<RefStringTypeLhs>(rhs);
15529}
15530
15531template<typename RefStringTypeRhs,
15532 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15533JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
15534inline bool operator==(const StringType& lhs,
15535 const json_pointer<RefStringTypeRhs>& rhs)
15536{
15537 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
15538}
15539
15540template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15542 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15543{
15544 return !(lhs == rhs);
15545}
15546
15547template<typename RefStringTypeLhs,
15548 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15549JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
15550inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15551 const StringType& rhs)
15552{
15553 return !(lhs == rhs);
15554}
15555
15556template<typename RefStringTypeRhs,
15557 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15558JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
15559inline bool operator!=(const StringType& lhs,
15560 const json_pointer<RefStringTypeRhs>& rhs)
15561{
15562 return !(lhs == rhs);
15563}
15564
15565template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15566inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
15567 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15568{
15569 return lhs.reference_tokens < rhs.reference_tokens;
15570}
15571#endif
15572
15573NLOHMANN_JSON_NAMESPACE_END
15574
15575// #include <nlohmann/detail/json_ref.hpp>
15576// __ _____ _____ _____
15577// __| | __| | | | JSON for Modern C++
15578// | | |__ | | | | | | version 3.12.0
15579// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15580//
15581// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15582// SPDX-License-Identifier: MIT
15583
15584
15585
15586#include <initializer_list>
15587#include <utility>
15588
15589// #include <nlohmann/detail/abi_macros.hpp>
15590
15591// #include <nlohmann/detail/meta/type_traits.hpp>
15592
15593
15594NLOHMANN_JSON_NAMESPACE_BEGIN
15595namespace detail
15596{
15597
15598template<typename BasicJsonType>
15600{
15601 public:
15602 using value_type = BasicJsonType;
15603
15604 json_ref(value_type&& value)
15605 : owned_value(std::move(value))
15606 {}
15607
15608 json_ref(const value_type& value)
15609 : value_ref(&value)
15610 {}
15611
15612 json_ref(std::initializer_list<json_ref> init)
15613 : owned_value(init)
15614 {}
15615
15616 template <
15617 class... Args,
15618 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
15619 json_ref(Args && ... args)
15620 : owned_value(std::forward<Args>(args)...)
15621 {}
15622
15623 // class should be movable only
15624 json_ref(json_ref&&) noexcept = default;
15625 json_ref(const json_ref&) = delete;
15626 json_ref& operator=(const json_ref&) = delete;
15627 json_ref& operator=(json_ref&&) = delete;
15628 ~json_ref() = default;
15629
15630 value_type moved_or_copied() const
15631 {
15632 if (value_ref == nullptr)
15633 {
15634 return std::move(owned_value);
15635 }
15636 return *value_ref;
15637 }
15638
15639 value_type const& operator*() const
15640 {
15641 return value_ref ? *value_ref : owned_value;
15642 }
15643
15644 value_type const* operator->() const
15645 {
15646 return &** this;
15647 }
15648
15649 private:
15650 mutable value_type owned_value = nullptr;
15651 value_type const* value_ref = nullptr;
15652};
15653
15654} // namespace detail
15655NLOHMANN_JSON_NAMESPACE_END
15656
15657// #include <nlohmann/detail/macro_scope.hpp>
15658
15659// #include <nlohmann/detail/string_concat.hpp>
15660
15661// #include <nlohmann/detail/string_escape.hpp>
15662
15663// #include <nlohmann/detail/string_utils.hpp>
15664
15665// #include <nlohmann/detail/meta/cpp_future.hpp>
15666
15667// #include <nlohmann/detail/meta/type_traits.hpp>
15668
15669// #include <nlohmann/detail/output/binary_writer.hpp>
15670// __ _____ _____ _____
15671// __| | __| | | | JSON for Modern C++
15672// | | |__ | | | | | | version 3.12.0
15673// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15674//
15675// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15676// SPDX-License-Identifier: MIT
15677
15678
15679
15680#include <algorithm> // reverse
15681#include <array> // array
15682#include <map> // map
15683#include <cmath> // isnan, isinf
15684#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
15685#include <cstring> // memcpy
15686#include <limits> // numeric_limits
15687#include <string> // string
15688#include <utility> // move
15689#include <vector> // vector
15690
15691// #include <nlohmann/detail/input/binary_reader.hpp>
15692
15693// #include <nlohmann/detail/macro_scope.hpp>
15694
15695// #include <nlohmann/detail/output/output_adapters.hpp>
15696// __ _____ _____ _____
15697// __| | __| | | | JSON for Modern C++
15698// | | |__ | | | | | | version 3.12.0
15699// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15700//
15701// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15702// SPDX-License-Identifier: MIT
15703
15704
15705
15706#include <algorithm> // copy
15707#include <cstddef> // size_t
15708#include <iterator> // back_inserter
15709#include <memory> // shared_ptr, make_shared
15710#include <string> // basic_string
15711#include <vector> // vector
15712
15713#ifndef JSON_NO_IO
15714 #include <ios> // streamsize
15715 #include <ostream> // basic_ostream
15716#endif // JSON_NO_IO
15717
15718// #include <nlohmann/detail/macro_scope.hpp>
15719
15720
15721NLOHMANN_JSON_NAMESPACE_BEGIN
15722namespace detail
15723{
15724
15726template<typename CharType> struct output_adapter_protocol
15727{
15728 virtual void write_character(CharType c) = 0;
15729 virtual void write_characters(const CharType* s, std::size_t length) = 0;
15730 virtual ~output_adapter_protocol() = default;
15731
15732 output_adapter_protocol() = default;
15733 output_adapter_protocol(const output_adapter_protocol&) = default;
15734 output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
15735 output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
15736 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
15737};
15738
15740template<typename CharType>
15741using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
15742
15744template<typename CharType, typename AllocatorType = std::allocator<CharType>>
15745class output_vector_adapter : public output_adapter_protocol<CharType>
15746{
15747 public:
15748 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
15749 : v(vec)
15750 {}
15751
15752 void write_character(CharType c) override
15753 {
15754 v.push_back(c);
15755 }
15756
15757 JSON_HEDLEY_NON_NULL(2)
15758 void write_characters(const CharType* s, std::size_t length) override
15759 {
15760 v.insert(v.end(), s, s + length);
15761 }
15762
15763 private:
15764 std::vector<CharType, AllocatorType>& v;
15765};
15766
15767#ifndef JSON_NO_IO
15769template<typename CharType>
15770class output_stream_adapter : public output_adapter_protocol<CharType>
15771{
15772 public:
15773 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15774 : stream(s)
15775 {}
15776
15777 void write_character(CharType c) override
15778 {
15779 stream.put(c);
15780 }
15781
15782 JSON_HEDLEY_NON_NULL(2)
15783 void write_characters(const CharType* s, std::size_t length) override
15784 {
15785 stream.write(s, static_cast<std::streamsize>(length));
15786 }
15787
15788 private:
15789 std::basic_ostream<CharType>& stream;
15790};
15791#endif // JSON_NO_IO
15792
15794template<typename CharType, typename StringType = std::basic_string<CharType>>
15795class output_string_adapter : public output_adapter_protocol<CharType>
15796{
15797 public:
15798 explicit output_string_adapter(StringType& s) noexcept
15799 : str(s)
15800 {}
15801
15802 void write_character(CharType c) override
15803 {
15804 str.push_back(c);
15805 }
15806
15807 JSON_HEDLEY_NON_NULL(2)
15808 void write_characters(const CharType* s, std::size_t length) override
15809 {
15810 str.append(s, length);
15811 }
15812
15813 private:
15814 StringType& str;
15815};
15816
15817template<typename CharType, typename StringType = std::basic_string<CharType>>
15818class output_adapter
15819{
15820 public:
15821 template<typename AllocatorType = std::allocator<CharType>>
15822 output_adapter(std::vector<CharType, AllocatorType>& vec)
15823 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15824
15825#ifndef JSON_NO_IO
15826 output_adapter(std::basic_ostream<CharType>& s)
15827 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15828#endif // JSON_NO_IO
15829
15830 output_adapter(StringType& s)
15831 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15832
15833 operator output_adapter_t<CharType>()
15834 {
15835 return oa;
15836 }
15837
15838 private:
15839 output_adapter_t<CharType> oa = nullptr;
15840};
15841
15842} // namespace detail
15843NLOHMANN_JSON_NAMESPACE_END
15844
15845// #include <nlohmann/detail/string_concat.hpp>
15846
15847
15848NLOHMANN_JSON_NAMESPACE_BEGIN
15849namespace detail
15850{
15851
15853enum class bjdata_version_t
15854{
15855 draft2,
15856 draft3,
15857};
15858
15860// binary writer //
15862
15866template<typename BasicJsonType, typename CharType>
15867class binary_writer
15868{
15869 using string_t = typename BasicJsonType::string_t;
15870 using binary_t = typename BasicJsonType::binary_t;
15871 using number_float_t = typename BasicJsonType::number_float_t;
15872
15873 public:
15879 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15880 {
15881 JSON_ASSERT(oa);
15882 }
15883
15888 void write_bson(const BasicJsonType& j)
15889 {
15890 switch (j.type())
15891 {
15892 case value_t::object:
15893 {
15894 write_bson_object(*j.m_data.m_value.object);
15895 break;
15896 }
15897
15898 case value_t::null:
15899 case value_t::array:
15900 case value_t::string:
15901 case value_t::boolean:
15902 case value_t::number_integer:
15903 case value_t::number_unsigned:
15904 case value_t::number_float:
15905 case value_t::binary:
15906 case value_t::discarded:
15907 default:
15908 {
15909 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15910 }
15911 }
15912 }
15913
15917 void write_cbor(const BasicJsonType& j)
15918 {
15919 switch (j.type())
15920 {
15921 case value_t::null:
15922 {
15923 oa->write_character(to_char_type(0xF6));
15924 break;
15925 }
15926
15927 case value_t::boolean:
15928 {
15929 oa->write_character(j.m_data.m_value.boolean
15930 ? to_char_type(0xF5)
15931 : to_char_type(0xF4));
15932 break;
15933 }
15934
15935 case value_t::number_integer:
15936 {
15937 if (j.m_data.m_value.number_integer >= 0)
15938 {
15939 // CBOR does not differentiate between positive signed
15940 // integers and unsigned integers. Therefore, we used the
15941 // code from the value_t::number_unsigned case here.
15942 if (j.m_data.m_value.number_integer <= 0x17)
15943 {
15944 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15945 }
15946 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15947 {
15948 oa->write_character(to_char_type(0x18));
15949 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15950 }
15951 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15952 {
15953 oa->write_character(to_char_type(0x19));
15954 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15955 }
15956 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15957 {
15958 oa->write_character(to_char_type(0x1A));
15959 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15960 }
15961 else
15962 {
15963 oa->write_character(to_char_type(0x1B));
15964 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15965 }
15966 }
15967 else
15968 {
15969 // The conversions below encode the sign in the first
15970 // byte, and the value is converted to a positive number.
15971 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15972 if (j.m_data.m_value.number_integer >= -24)
15973 {
15974 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15975 }
15976 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15977 {
15978 oa->write_character(to_char_type(0x38));
15979 write_number(static_cast<std::uint8_t>(positive_number));
15980 }
15981 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15982 {
15983 oa->write_character(to_char_type(0x39));
15984 write_number(static_cast<std::uint16_t>(positive_number));
15985 }
15986 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15987 {
15988 oa->write_character(to_char_type(0x3A));
15989 write_number(static_cast<std::uint32_t>(positive_number));
15990 }
15991 else
15992 {
15993 oa->write_character(to_char_type(0x3B));
15994 write_number(static_cast<std::uint64_t>(positive_number));
15995 }
15996 }
15997 break;
15998 }
15999
16000 case value_t::number_unsigned:
16001 {
16002 if (j.m_data.m_value.number_unsigned <= 0x17)
16003 {
16004 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
16005 }
16006 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16007 {
16008 oa->write_character(to_char_type(0x18));
16009 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
16010 }
16011 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16012 {
16013 oa->write_character(to_char_type(0x19));
16014 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
16015 }
16016 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16017 {
16018 oa->write_character(to_char_type(0x1A));
16019 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
16020 }
16021 else
16022 {
16023 oa->write_character(to_char_type(0x1B));
16024 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
16025 }
16026 break;
16027 }
16028
16029 case value_t::number_float:
16030 {
16031 if (std::isnan(j.m_data.m_value.number_float))
16032 {
16033 // NaN is 0xf97e00 in CBOR
16034 oa->write_character(to_char_type(0xF9));
16035 oa->write_character(to_char_type(0x7E));
16036 oa->write_character(to_char_type(0x00));
16037 }
16038 else if (std::isinf(j.m_data.m_value.number_float))
16039 {
16040 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
16041 oa->write_character(to_char_type(0xf9));
16042 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
16043 oa->write_character(to_char_type(0x00));
16044 }
16045 else
16046 {
16047 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
16048 }
16049 break;
16050 }
16051
16052 case value_t::string:
16053 {
16054 // step 1: write control byte and the string length
16055 const auto N = j.m_data.m_value.string->size();
16056 if (N <= 0x17)
16057 {
16058 write_number(static_cast<std::uint8_t>(0x60 + N));
16059 }
16060 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16061 {
16062 oa->write_character(to_char_type(0x78));
16063 write_number(static_cast<std::uint8_t>(N));
16064 }
16065 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16066 {
16067 oa->write_character(to_char_type(0x79));
16068 write_number(static_cast<std::uint16_t>(N));
16069 }
16070 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16071 {
16072 oa->write_character(to_char_type(0x7A));
16073 write_number(static_cast<std::uint32_t>(N));
16074 }
16075 // LCOV_EXCL_START
16076 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16077 {
16078 oa->write_character(to_char_type(0x7B));
16079 write_number(static_cast<std::uint64_t>(N));
16080 }
16081 // LCOV_EXCL_STOP
16082
16083 // step 2: write the string
16084 oa->write_characters(
16085 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16086 j.m_data.m_value.string->size());
16087 break;
16088 }
16089
16090 case value_t::array:
16091 {
16092 // step 1: write control byte and the array size
16093 const auto N = j.m_data.m_value.array->size();
16094 if (N <= 0x17)
16095 {
16096 write_number(static_cast<std::uint8_t>(0x80 + N));
16097 }
16098 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16099 {
16100 oa->write_character(to_char_type(0x98));
16101 write_number(static_cast<std::uint8_t>(N));
16102 }
16103 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16104 {
16105 oa->write_character(to_char_type(0x99));
16106 write_number(static_cast<std::uint16_t>(N));
16107 }
16108 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16109 {
16110 oa->write_character(to_char_type(0x9A));
16111 write_number(static_cast<std::uint32_t>(N));
16112 }
16113 // LCOV_EXCL_START
16114 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16115 {
16116 oa->write_character(to_char_type(0x9B));
16117 write_number(static_cast<std::uint64_t>(N));
16118 }
16119 // LCOV_EXCL_STOP
16120
16121 // step 2: write each element
16122 for (const auto& el : *j.m_data.m_value.array)
16123 {
16124 write_cbor(el);
16125 }
16126 break;
16127 }
16128
16129 case value_t::binary:
16130 {
16131 if (j.m_data.m_value.binary->has_subtype())
16132 {
16133 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
16134 {
16135 write_number(static_cast<std::uint8_t>(0xd8));
16136 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
16137 }
16138 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
16139 {
16140 write_number(static_cast<std::uint8_t>(0xd9));
16141 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
16142 }
16143 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
16144 {
16145 write_number(static_cast<std::uint8_t>(0xda));
16146 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
16147 }
16148 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
16149 {
16150 write_number(static_cast<std::uint8_t>(0xdb));
16151 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
16152 }
16153 }
16154
16155 // step 1: write control byte and the binary array size
16156 const auto N = j.m_data.m_value.binary->size();
16157 if (N <= 0x17)
16158 {
16159 write_number(static_cast<std::uint8_t>(0x40 + N));
16160 }
16161 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16162 {
16163 oa->write_character(to_char_type(0x58));
16164 write_number(static_cast<std::uint8_t>(N));
16165 }
16166 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16167 {
16168 oa->write_character(to_char_type(0x59));
16169 write_number(static_cast<std::uint16_t>(N));
16170 }
16171 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16172 {
16173 oa->write_character(to_char_type(0x5A));
16174 write_number(static_cast<std::uint32_t>(N));
16175 }
16176 // LCOV_EXCL_START
16177 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16178 {
16179 oa->write_character(to_char_type(0x5B));
16180 write_number(static_cast<std::uint64_t>(N));
16181 }
16182 // LCOV_EXCL_STOP
16183
16184 // step 2: write each element
16185 oa->write_characters(
16186 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16187 N);
16188
16189 break;
16190 }
16191
16192 case value_t::object:
16193 {
16194 // step 1: write control byte and the object size
16195 const auto N = j.m_data.m_value.object->size();
16196 if (N <= 0x17)
16197 {
16198 write_number(static_cast<std::uint8_t>(0xA0 + N));
16199 }
16200 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16201 {
16202 oa->write_character(to_char_type(0xB8));
16203 write_number(static_cast<std::uint8_t>(N));
16204 }
16205 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16206 {
16207 oa->write_character(to_char_type(0xB9));
16208 write_number(static_cast<std::uint16_t>(N));
16209 }
16210 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16211 {
16212 oa->write_character(to_char_type(0xBA));
16213 write_number(static_cast<std::uint32_t>(N));
16214 }
16215 // LCOV_EXCL_START
16216 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16217 {
16218 oa->write_character(to_char_type(0xBB));
16219 write_number(static_cast<std::uint64_t>(N));
16220 }
16221 // LCOV_EXCL_STOP
16222
16223 // step 2: write each element
16224 for (const auto& el : *j.m_data.m_value.object)
16225 {
16226 write_cbor(el.first);
16227 write_cbor(el.second);
16228 }
16229 break;
16230 }
16231
16232 case value_t::discarded:
16233 default:
16234 break;
16235 }
16236 }
16237
16241 void write_msgpack(const BasicJsonType& j)
16242 {
16243 switch (j.type())
16244 {
16245 case value_t::null: // nil
16246 {
16247 oa->write_character(to_char_type(0xC0));
16248 break;
16249 }
16250
16251 case value_t::boolean: // true and false
16252 {
16253 oa->write_character(j.m_data.m_value.boolean
16254 ? to_char_type(0xC3)
16255 : to_char_type(0xC2));
16256 break;
16257 }
16258
16259 case value_t::number_integer:
16260 {
16261 if (j.m_data.m_value.number_integer >= 0)
16262 {
16263 // MessagePack does not differentiate between positive
16264 // signed integers and unsigned integers. Therefore, we used
16265 // the code from the value_t::number_unsigned case here.
16266 if (j.m_data.m_value.number_unsigned < 128)
16267 {
16268 // positive fixnum
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::uint8_t>::max)())
16272 {
16273 // uint 8
16274 oa->write_character(to_char_type(0xCC));
16275 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16276 }
16277 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16278 {
16279 // uint 16
16280 oa->write_character(to_char_type(0xCD));
16281 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16282 }
16283 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16284 {
16285 // uint 32
16286 oa->write_character(to_char_type(0xCE));
16287 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16288 }
16289 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16290 {
16291 // uint 64
16292 oa->write_character(to_char_type(0xCF));
16293 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16294 }
16295 }
16296 else
16297 {
16298 if (j.m_data.m_value.number_integer >= -32)
16299 {
16300 // negative fixnum
16301 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16302 }
16303 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
16304 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16305 {
16306 // int 8
16307 oa->write_character(to_char_type(0xD0));
16308 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16309 }
16310 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
16311 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16312 {
16313 // int 16
16314 oa->write_character(to_char_type(0xD1));
16315 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
16316 }
16317 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
16318 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16319 {
16320 // int 32
16321 oa->write_character(to_char_type(0xD2));
16322 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
16323 }
16324 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
16325 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16326 {
16327 // int 64
16328 oa->write_character(to_char_type(0xD3));
16329 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
16330 }
16331 }
16332 break;
16333 }
16334
16335 case value_t::number_unsigned:
16336 {
16337 if (j.m_data.m_value.number_unsigned < 128)
16338 {
16339 // positive fixnum
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::uint8_t>::max)())
16343 {
16344 // uint 8
16345 oa->write_character(to_char_type(0xCC));
16346 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16347 }
16348 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16349 {
16350 // uint 16
16351 oa->write_character(to_char_type(0xCD));
16352 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16353 }
16354 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16355 {
16356 // uint 32
16357 oa->write_character(to_char_type(0xCE));
16358 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16359 }
16360 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16361 {
16362 // uint 64
16363 oa->write_character(to_char_type(0xCF));
16364 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16365 }
16366 break;
16367 }
16368
16369 case value_t::number_float:
16370 {
16371 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
16372 break;
16373 }
16374
16375 case value_t::string:
16376 {
16377 // step 1: write control byte and the string length
16378 const auto N = j.m_data.m_value.string->size();
16379 if (N <= 31)
16380 {
16381 // fixstr
16382 write_number(static_cast<std::uint8_t>(0xA0 | N));
16383 }
16384 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16385 {
16386 // str 8
16387 oa->write_character(to_char_type(0xD9));
16388 write_number(static_cast<std::uint8_t>(N));
16389 }
16390 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16391 {
16392 // str 16
16393 oa->write_character(to_char_type(0xDA));
16394 write_number(static_cast<std::uint16_t>(N));
16395 }
16396 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16397 {
16398 // str 32
16399 oa->write_character(to_char_type(0xDB));
16400 write_number(static_cast<std::uint32_t>(N));
16401 }
16402
16403 // step 2: write the string
16404 oa->write_characters(
16405 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16406 j.m_data.m_value.string->size());
16407 break;
16408 }
16409
16410 case value_t::array:
16411 {
16412 // step 1: write control byte and the array size
16413 const auto N = j.m_data.m_value.array->size();
16414 if (N <= 15)
16415 {
16416 // fixarray
16417 write_number(static_cast<std::uint8_t>(0x90 | N));
16418 }
16419 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16420 {
16421 // array 16
16422 oa->write_character(to_char_type(0xDC));
16423 write_number(static_cast<std::uint16_t>(N));
16424 }
16425 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16426 {
16427 // array 32
16428 oa->write_character(to_char_type(0xDD));
16429 write_number(static_cast<std::uint32_t>(N));
16430 }
16431
16432 // step 2: write each element
16433 for (const auto& el : *j.m_data.m_value.array)
16434 {
16435 write_msgpack(el);
16436 }
16437 break;
16438 }
16439
16440 case value_t::binary:
16441 {
16442 // step 0: determine if the binary type has a set subtype to
16443 // determine whether to use the ext or fixext types
16444 const bool use_ext = j.m_data.m_value.binary->has_subtype();
16445
16446 // step 1: write control byte and the byte string length
16447 const auto N = j.m_data.m_value.binary->size();
16448 if (N <= (std::numeric_limits<std::uint8_t>::max)())
16449 {
16450 std::uint8_t output_type{};
16451 bool fixed = true;
16452 if (use_ext)
16453 {
16454 switch (N)
16455 {
16456 case 1:
16457 output_type = 0xD4; // fixext 1
16458 break;
16459 case 2:
16460 output_type = 0xD5; // fixext 2
16461 break;
16462 case 4:
16463 output_type = 0xD6; // fixext 4
16464 break;
16465 case 8:
16466 output_type = 0xD7; // fixext 8
16467 break;
16468 case 16:
16469 output_type = 0xD8; // fixext 16
16470 break;
16471 default:
16472 output_type = 0xC7; // ext 8
16473 fixed = false;
16474 break;
16475 }
16476
16477 }
16478 else
16479 {
16480 output_type = 0xC4; // bin 8
16481 fixed = false;
16482 }
16483
16484 oa->write_character(to_char_type(output_type));
16485 if (!fixed)
16486 {
16487 write_number(static_cast<std::uint8_t>(N));
16488 }
16489 }
16490 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16491 {
16492 const std::uint8_t output_type = use_ext
16493 ? 0xC8 // ext 16
16494 : 0xC5; // bin 16
16495
16496 oa->write_character(to_char_type(output_type));
16497 write_number(static_cast<std::uint16_t>(N));
16498 }
16499 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16500 {
16501 const std::uint8_t output_type = use_ext
16502 ? 0xC9 // ext 32
16503 : 0xC6; // bin 32
16504
16505 oa->write_character(to_char_type(output_type));
16506 write_number(static_cast<std::uint32_t>(N));
16507 }
16508
16509 // step 1.5: if this is an ext type, write the subtype
16510 if (use_ext)
16511 {
16512 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
16513 }
16514
16515 // step 2: write the byte string
16516 oa->write_characters(
16517 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16518 N);
16519
16520 break;
16521 }
16522
16523 case value_t::object:
16524 {
16525 // step 1: write control byte and the object size
16526 const auto N = j.m_data.m_value.object->size();
16527 if (N <= 15)
16528 {
16529 // fixmap
16530 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
16531 }
16532 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16533 {
16534 // map 16
16535 oa->write_character(to_char_type(0xDE));
16536 write_number(static_cast<std::uint16_t>(N));
16537 }
16538 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16539 {
16540 // map 32
16541 oa->write_character(to_char_type(0xDF));
16542 write_number(static_cast<std::uint32_t>(N));
16543 }
16544
16545 // step 2: write each element
16546 for (const auto& el : *j.m_data.m_value.object)
16547 {
16548 write_msgpack(el.first);
16549 write_msgpack(el.second);
16550 }
16551 break;
16552 }
16553
16554 case value_t::discarded:
16555 default:
16556 break;
16557 }
16558 }
16559
16568 void write_ubjson(const BasicJsonType& j, const bool use_count,
16569 const bool use_type, const bool add_prefix = true,
16570 const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2)
16571 {
16572 const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3;
16573
16574 switch (j.type())
16575 {
16576 case value_t::null:
16577 {
16578 if (add_prefix)
16579 {
16580 oa->write_character(to_char_type('Z'));
16581 }
16582 break;
16583 }
16584
16585 case value_t::boolean:
16586 {
16587 if (add_prefix)
16588 {
16589 oa->write_character(j.m_data.m_value.boolean
16590 ? to_char_type('T')
16591 : to_char_type('F'));
16592 }
16593 break;
16594 }
16595
16596 case value_t::number_integer:
16597 {
16598 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
16599 break;
16600 }
16601
16602 case value_t::number_unsigned:
16603 {
16604 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
16605 break;
16606 }
16607
16608 case value_t::number_float:
16609 {
16610 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
16611 break;
16612 }
16613
16614 case value_t::string:
16615 {
16616 if (add_prefix)
16617 {
16618 oa->write_character(to_char_type('S'));
16619 }
16620 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
16621 oa->write_characters(
16622 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16623 j.m_data.m_value.string->size());
16624 break;
16625 }
16626
16627 case value_t::array:
16628 {
16629 if (add_prefix)
16630 {
16631 oa->write_character(to_char_type('['));
16632 }
16633
16634 bool prefix_required = true;
16635 if (use_type && !j.m_data.m_value.array->empty())
16636 {
16637 JSON_ASSERT(use_count);
16638 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16639 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
16640 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16641 {
16642 return ubjson_prefix(v, use_bjdata) == first_prefix;
16643 });
16644
16645 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16646
16647 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16648 {
16649 prefix_required = false;
16650 oa->write_character(to_char_type('$'));
16651 oa->write_character(first_prefix);
16652 }
16653 }
16654
16655 if (use_count)
16656 {
16657 oa->write_character(to_char_type('#'));
16658 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
16659 }
16660
16661 for (const auto& el : *j.m_data.m_value.array)
16662 {
16663 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16664 }
16665
16666 if (!use_count)
16667 {
16668 oa->write_character(to_char_type(']'));
16669 }
16670
16671 break;
16672 }
16673
16674 case value_t::binary:
16675 {
16676 if (add_prefix)
16677 {
16678 oa->write_character(to_char_type('['));
16679 }
16680
16681 if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
16682 {
16683 JSON_ASSERT(use_count);
16684 oa->write_character(to_char_type('$'));
16685 oa->write_character(bjdata_draft3 ? 'B' : 'U');
16686 }
16687
16688 if (use_count)
16689 {
16690 oa->write_character(to_char_type('#'));
16691 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
16692 }
16693
16694 if (use_type)
16695 {
16696 oa->write_characters(
16697 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16698 j.m_data.m_value.binary->size());
16699 }
16700 else
16701 {
16702 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
16703 {
16704 oa->write_character(to_char_type(bjdata_draft3 ? 'B' : 'U'));
16705 oa->write_character(j.m_data.m_value.binary->data()[i]);
16706 }
16707 }
16708
16709 if (!use_count)
16710 {
16711 oa->write_character(to_char_type(']'));
16712 }
16713
16714 break;
16715 }
16716
16717 case value_t::object:
16718 {
16719 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())
16720 {
16721 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)
16722 {
16723 break;
16724 }
16725 }
16726
16727 if (add_prefix)
16728 {
16729 oa->write_character(to_char_type('{'));
16730 }
16731
16732 bool prefix_required = true;
16733 if (use_type && !j.m_data.m_value.object->empty())
16734 {
16735 JSON_ASSERT(use_count);
16736 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16737 const bool same_prefix = std::all_of(j.begin(), j.end(),
16738 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16739 {
16740 return ubjson_prefix(v, use_bjdata) == first_prefix;
16741 });
16742
16743 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16744
16745 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16746 {
16747 prefix_required = false;
16748 oa->write_character(to_char_type('$'));
16749 oa->write_character(first_prefix);
16750 }
16751 }
16752
16753 if (use_count)
16754 {
16755 oa->write_character(to_char_type('#'));
16756 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
16757 }
16758
16759 for (const auto& el : *j.m_data.m_value.object)
16760 {
16761 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
16762 oa->write_characters(
16763 reinterpret_cast<const CharType*>(el.first.c_str()),
16764 el.first.size());
16765 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16766 }
16767
16768 if (!use_count)
16769 {
16770 oa->write_character(to_char_type('}'));
16771 }
16772
16773 break;
16774 }
16775
16776 case value_t::discarded:
16777 default:
16778 break;
16779 }
16780 }
16781
16782 private:
16784 // BSON //
16786
16791 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16792 {
16793 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16794 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16795 {
16796 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16797 }
16798
16799 static_cast<void>(j);
16800 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16801 }
16802
16806 void write_bson_entry_header(const string_t& name,
16807 const std::uint8_t element_type)
16808 {
16809 oa->write_character(to_char_type(element_type)); // boolean
16810 oa->write_characters(
16811 reinterpret_cast<const CharType*>(name.c_str()),
16812 name.size() + 1u);
16813 }
16814
16818 void write_bson_boolean(const string_t& name,
16819 const bool value)
16820 {
16821 write_bson_entry_header(name, 0x08);
16822 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16823 }
16824
16828 void write_bson_double(const string_t& name,
16829 const double value)
16830 {
16831 write_bson_entry_header(name, 0x01);
16832 write_number<double>(value, true);
16833 }
16834
16838 static std::size_t calc_bson_string_size(const string_t& value)
16839 {
16840 return sizeof(std::int32_t) + value.size() + 1ul;
16841 }
16842
16846 void write_bson_string(const string_t& name,
16847 const string_t& value)
16848 {
16849 write_bson_entry_header(name, 0x02);
16850
16851 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16852 oa->write_characters(
16853 reinterpret_cast<const CharType*>(value.c_str()),
16854 value.size() + 1);
16855 }
16856
16860 void write_bson_null(const string_t& name)
16861 {
16862 write_bson_entry_header(name, 0x0A);
16863 }
16864
16868 static std::size_t calc_bson_integer_size(const std::int64_t value)
16869 {
16870 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16871 ? sizeof(std::int32_t)
16872 : sizeof(std::int64_t);
16873 }
16874
16878 void write_bson_integer(const string_t& name,
16879 const std::int64_t value)
16880 {
16881 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16882 {
16883 write_bson_entry_header(name, 0x10); // int32
16884 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16885 }
16886 else
16887 {
16888 write_bson_entry_header(name, 0x12); // int64
16889 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16890 }
16891 }
16892
16896 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16897 {
16898 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16899 ? sizeof(std::int32_t)
16900 : sizeof(std::int64_t);
16901 }
16902
16906 void write_bson_unsigned(const string_t& name,
16907 const BasicJsonType& j)
16908 {
16909 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16910 {
16911 write_bson_entry_header(name, 0x10 /* int32 */);
16912 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16913 }
16914 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16915 {
16916 write_bson_entry_header(name, 0x12 /* int64 */);
16917 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16918 }
16919 else
16920 {
16921 write_bson_entry_header(name, 0x11 /* uint64 */);
16922 write_number<std::uint64_t>(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned), true);
16923 }
16924 }
16925
16929 void write_bson_object_entry(const string_t& name,
16930 const typename BasicJsonType::object_t& value)
16931 {
16932 write_bson_entry_header(name, 0x03); // object
16933 write_bson_object(value);
16934 }
16935
16939 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16940 {
16941 std::size_t array_index = 0ul;
16942
16943 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)
16944 {
16945 return result + calc_bson_element_size(std::to_string(array_index++), el);
16946 });
16947
16948 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16949 }
16950
16954 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16955 {
16956 return sizeof(std::int32_t) + value.size() + 1ul;
16957 }
16958
16962 void write_bson_array(const string_t& name,
16963 const typename BasicJsonType::array_t& value)
16964 {
16965 write_bson_entry_header(name, 0x04); // array
16966 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16967
16968 std::size_t array_index = 0ul;
16969
16970 for (const auto& el : value)
16971 {
16972 write_bson_element(std::to_string(array_index++), el);
16973 }
16974
16975 oa->write_character(to_char_type(0x00));
16976 }
16977
16981 void write_bson_binary(const string_t& name,
16982 const binary_t& value)
16983 {
16984 write_bson_entry_header(name, 0x05);
16985
16986 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16987 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16988
16989 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16990 }
16991
16996 static std::size_t calc_bson_element_size(const string_t& name,
16997 const BasicJsonType& j)
16998 {
16999 const auto header_size = calc_bson_entry_header_size(name, j);
17000 switch (j.type())
17001 {
17002 case value_t::object:
17003 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
17004
17005 case value_t::array:
17006 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
17007
17008 case value_t::binary:
17009 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
17010
17011 case value_t::boolean:
17012 return header_size + 1ul;
17013
17014 case value_t::number_float:
17015 return header_size + 8ul;
17016
17017 case value_t::number_integer:
17018 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
17019
17020 case value_t::number_unsigned:
17021 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
17022
17023 case value_t::string:
17024 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
17025
17026 case value_t::null:
17027 return header_size + 0ul;
17028
17029 // LCOV_EXCL_START
17030 case value_t::discarded:
17031 default:
17032 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17033 return 0ul;
17034 // LCOV_EXCL_STOP
17035 }
17036 }
17037
17044 void write_bson_element(const string_t& name,
17045 const BasicJsonType& j)
17046 {
17047 switch (j.type())
17048 {
17049 case value_t::object:
17050 return write_bson_object_entry(name, *j.m_data.m_value.object);
17051
17052 case value_t::array:
17053 return write_bson_array(name, *j.m_data.m_value.array);
17054
17055 case value_t::binary:
17056 return write_bson_binary(name, *j.m_data.m_value.binary);
17057
17058 case value_t::boolean:
17059 return write_bson_boolean(name, j.m_data.m_value.boolean);
17060
17061 case value_t::number_float:
17062 return write_bson_double(name, j.m_data.m_value.number_float);
17063
17064 case value_t::number_integer:
17065 return write_bson_integer(name, j.m_data.m_value.number_integer);
17066
17067 case value_t::number_unsigned:
17068 return write_bson_unsigned(name, j);
17069
17070 case value_t::string:
17071 return write_bson_string(name, *j.m_data.m_value.string);
17072
17073 case value_t::null:
17074 return write_bson_null(name);
17075
17076 // LCOV_EXCL_START
17077 case value_t::discarded:
17078 default:
17079 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17080 return;
17081 // LCOV_EXCL_STOP
17082 }
17083 }
17084
17091 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
17092 {
17093 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
17094 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
17095 {
17096 return result += calc_bson_element_size(el.first, el.second);
17097 });
17098
17099 return sizeof(std::int32_t) + document_size + 1ul;
17100 }
17101
17106 void write_bson_object(const typename BasicJsonType::object_t& value)
17107 {
17108 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
17109
17110 for (const auto& el : value)
17111 {
17112 write_bson_element(el.first, el.second);
17113 }
17114
17115 oa->write_character(to_char_type(0x00));
17116 }
17117
17119 // CBOR //
17121
17122 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
17123 {
17124 return to_char_type(0xFA); // Single-Precision Float
17125 }
17126
17127 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
17128 {
17129 return to_char_type(0xFB); // Double-Precision Float
17130 }
17131
17133 // MsgPack //
17135
17136 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
17137 {
17138 return to_char_type(0xCA); // float 32
17139 }
17140
17141 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
17142 {
17143 return to_char_type(0xCB); // float 64
17144 }
17145
17147 // UBJSON //
17149
17150 // UBJSON: write number (floating point)
17151 template<typename NumberType, typename std::enable_if<
17152 std::is_floating_point<NumberType>::value, int>::type = 0>
17153 void write_number_with_ubjson_prefix(const NumberType n,
17154 const bool add_prefix,
17155 const bool use_bjdata)
17156 {
17157 if (add_prefix)
17158 {
17159 oa->write_character(get_ubjson_float_prefix(n));
17160 }
17161 write_number(n, use_bjdata);
17162 }
17163
17164 // UBJSON: write number (unsigned integer)
17165 template<typename NumberType, typename std::enable_if<
17166 std::is_unsigned<NumberType>::value, int>::type = 0>
17167 void write_number_with_ubjson_prefix(const NumberType n,
17168 const bool add_prefix,
17169 const bool use_bjdata)
17170 {
17171 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17172 {
17173 if (add_prefix)
17174 {
17175 oa->write_character(to_char_type('i')); // int8
17176 }
17177 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17178 }
17179 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
17180 {
17181 if (add_prefix)
17182 {
17183 oa->write_character(to_char_type('U')); // uint8
17184 }
17185 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17186 }
17187 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17188 {
17189 if (add_prefix)
17190 {
17191 oa->write_character(to_char_type('I')); // int16
17192 }
17193 write_number(static_cast<std::int16_t>(n), use_bjdata);
17194 }
17195 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
17196 {
17197 if (add_prefix)
17198 {
17199 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17200 }
17201 write_number(static_cast<std::uint16_t>(n), use_bjdata);
17202 }
17203 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17204 {
17205 if (add_prefix)
17206 {
17207 oa->write_character(to_char_type('l')); // int32
17208 }
17209 write_number(static_cast<std::int32_t>(n), use_bjdata);
17210 }
17211 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
17212 {
17213 if (add_prefix)
17214 {
17215 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17216 }
17217 write_number(static_cast<std::uint32_t>(n), use_bjdata);
17218 }
17219 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17220 {
17221 if (add_prefix)
17222 {
17223 oa->write_character(to_char_type('L')); // int64
17224 }
17225 write_number(static_cast<std::int64_t>(n), use_bjdata);
17226 }
17227 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
17228 {
17229 if (add_prefix)
17230 {
17231 oa->write_character(to_char_type('M')); // uint64 - bjdata only
17232 }
17233 write_number(static_cast<std::uint64_t>(n), use_bjdata);
17234 }
17235 else
17236 {
17237 if (add_prefix)
17238 {
17239 oa->write_character(to_char_type('H')); // high-precision number
17240 }
17241
17242 const auto number = BasicJsonType(n).dump();
17243 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17244 for (std::size_t i = 0; i < number.size(); ++i)
17245 {
17246 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17247 }
17248 }
17249 }
17250
17251 // UBJSON: write number (signed integer)
17252 template < typename NumberType, typename std::enable_if <
17253 std::is_signed<NumberType>::value&&
17254 !std::is_floating_point<NumberType>::value, int >::type = 0 >
17255 void write_number_with_ubjson_prefix(const NumberType n,
17256 const bool add_prefix,
17257 const bool use_bjdata)
17258 {
17259 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
17260 {
17261 if (add_prefix)
17262 {
17263 oa->write_character(to_char_type('i')); // int8
17264 }
17265 write_number(static_cast<std::int8_t>(n), use_bjdata);
17266 }
17267 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)()))
17268 {
17269 if (add_prefix)
17270 {
17271 oa->write_character(to_char_type('U')); // uint8
17272 }
17273 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17274 }
17275 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
17276 {
17277 if (add_prefix)
17278 {
17279 oa->write_character(to_char_type('I')); // int16
17280 }
17281 write_number(static_cast<std::int16_t>(n), use_bjdata);
17282 }
17283 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)())))
17284 {
17285 if (add_prefix)
17286 {
17287 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17288 }
17289 write_number(static_cast<uint16_t>(n), use_bjdata);
17290 }
17291 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
17292 {
17293 if (add_prefix)
17294 {
17295 oa->write_character(to_char_type('l')); // int32
17296 }
17297 write_number(static_cast<std::int32_t>(n), use_bjdata);
17298 }
17299 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)())))
17300 {
17301 if (add_prefix)
17302 {
17303 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17304 }
17305 write_number(static_cast<uint32_t>(n), use_bjdata);
17306 }
17307 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
17308 {
17309 if (add_prefix)
17310 {
17311 oa->write_character(to_char_type('L')); // int64
17312 }
17313 write_number(static_cast<std::int64_t>(n), use_bjdata);
17314 }
17315 // LCOV_EXCL_START
17316 else
17317 {
17318 if (add_prefix)
17319 {
17320 oa->write_character(to_char_type('H')); // high-precision number
17321 }
17322
17323 const auto number = BasicJsonType(n).dump();
17324 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17325 for (std::size_t i = 0; i < number.size(); ++i)
17326 {
17327 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17328 }
17329 }
17330 // LCOV_EXCL_STOP
17331 }
17332
17336 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
17337 {
17338 switch (j.type())
17339 {
17340 case value_t::null:
17341 return 'Z';
17342
17343 case value_t::boolean:
17344 return j.m_data.m_value.boolean ? 'T' : 'F';
17345
17346 case value_t::number_integer:
17347 {
17348 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)())
17349 {
17350 return 'i';
17351 }
17352 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)())
17353 {
17354 return 'U';
17355 }
17356 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)())
17357 {
17358 return 'I';
17359 }
17360 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)()))
17361 {
17362 return 'u';
17363 }
17364 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)())
17365 {
17366 return 'l';
17367 }
17368 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)()))
17369 {
17370 return 'm';
17371 }
17372 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)())
17373 {
17374 return 'L';
17375 }
17376 // anything else is treated as a high-precision number
17377 return 'H'; // LCOV_EXCL_LINE
17378 }
17379
17380 case value_t::number_unsigned:
17381 {
17382 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17383 {
17384 return 'i';
17385 }
17386 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
17387 {
17388 return 'U';
17389 }
17390 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17391 {
17392 return 'I';
17393 }
17394 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
17395 {
17396 return 'u';
17397 }
17398 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17399 {
17400 return 'l';
17401 }
17402 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
17403 {
17404 return 'm';
17405 }
17406 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17407 {
17408 return 'L';
17409 }
17410 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
17411 {
17412 return 'M';
17413 }
17414 // anything else is treated as a high-precision number
17415 return 'H'; // LCOV_EXCL_LINE
17416 }
17417
17418 case value_t::number_float:
17419 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
17420
17421 case value_t::string:
17422 return 'S';
17423
17424 case value_t::array: // fallthrough
17425 case value_t::binary:
17426 return '[';
17427
17428 case value_t::object:
17429 return '{';
17430
17431 case value_t::discarded:
17432 default: // discarded values
17433 return 'N';
17434 }
17435 }
17436
17437 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
17438 {
17439 return 'd'; // float 32
17440 }
17441
17442 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
17443 {
17444 return 'D'; // float 64
17445 }
17446
17450 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
17451 {
17452 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
17453 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'},
17454 {"char", 'C'}, {"byte", 'B'}
17455 };
17456
17457 string_t key = "_ArrayType_";
17458 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
17459 if (it == bjdtype.end())
17460 {
17461 return true;
17462 }
17463 CharType dtype = it->second;
17464
17465 key = "_ArraySize_";
17466 std::size_t len = (value.at(key).empty() ? 0 : 1);
17467 for (const auto& el : value.at(key))
17468 {
17469 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
17470 }
17471
17472 key = "_ArrayData_";
17473 if (value.at(key).size() != len)
17474 {
17475 return true;
17476 }
17477
17478 oa->write_character('[');
17479 oa->write_character('$');
17480 oa->write_character(dtype);
17481 oa->write_character('#');
17482
17483 key = "_ArraySize_";
17484 write_ubjson(value.at(key), use_count, use_type, true, true, bjdata_version);
17485
17486 key = "_ArrayData_";
17487 if (dtype == 'U' || dtype == 'C' || dtype == 'B')
17488 {
17489 for (const auto& el : value.at(key))
17490 {
17491 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
17492 }
17493 }
17494 else if (dtype == 'i')
17495 {
17496 for (const auto& el : value.at(key))
17497 {
17498 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
17499 }
17500 }
17501 else if (dtype == 'u')
17502 {
17503 for (const auto& el : value.at(key))
17504 {
17505 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
17506 }
17507 }
17508 else if (dtype == 'I')
17509 {
17510 for (const auto& el : value.at(key))
17511 {
17512 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
17513 }
17514 }
17515 else if (dtype == 'm')
17516 {
17517 for (const auto& el : value.at(key))
17518 {
17519 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
17520 }
17521 }
17522 else if (dtype == 'l')
17523 {
17524 for (const auto& el : value.at(key))
17525 {
17526 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
17527 }
17528 }
17529 else if (dtype == 'M')
17530 {
17531 for (const auto& el : value.at(key))
17532 {
17533 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
17534 }
17535 }
17536 else if (dtype == 'L')
17537 {
17538 for (const auto& el : value.at(key))
17539 {
17540 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
17541 }
17542 }
17543 else if (dtype == 'd')
17544 {
17545 for (const auto& el : value.at(key))
17546 {
17547 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
17548 }
17549 }
17550 else if (dtype == 'D')
17551 {
17552 for (const auto& el : value.at(key))
17553 {
17554 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
17555 }
17556 }
17557 return false;
17558 }
17559
17561 // Utility functions //
17563
17564 /*
17565 @brief write a number to output input
17566 @param[in] n number of type @a NumberType
17567 @param[in] OutputIsLittleEndian Set to true if output data is
17568 required to be little endian
17569 @tparam NumberType the type of the number
17570
17571 @note This function needs to respect the system's endianness, because bytes
17572 in CBOR, MessagePack, and UBJSON are stored in network order (big
17573 endian) and therefore need reordering on little endian systems.
17574 On the other hand, BSON and BJData use little endian and should reorder
17575 on big endian systems.
17576 */
17577 template<typename NumberType>
17578 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
17579 {
17580 // step 1: write the number to an array of length NumberType
17581 std::array<CharType, sizeof(NumberType)> vec{};
17582 std::memcpy(vec.data(), &n, sizeof(NumberType));
17583
17584 // step 2: write the array to output (with possible reordering)
17585 if (is_little_endian != OutputIsLittleEndian)
17586 {
17587 // reverse byte order prior to conversion if necessary
17588 std::reverse(vec.begin(), vec.end());
17589 }
17590
17591 oa->write_characters(vec.data(), sizeof(NumberType));
17592 }
17593
17594 void write_compact_float(const number_float_t n, detail::input_format_t format)
17595 {
17596#ifdef __GNUC__
17597#pragma GCC diagnostic push
17598#pragma GCC diagnostic ignored "-Wfloat-equal"
17599#endif
17600 if (!std::isfinite(n) || ((static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
17601 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
17602 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))))
17603 {
17604 oa->write_character(format == detail::input_format_t::cbor
17605 ? get_cbor_float_prefix(static_cast<float>(n))
17606 : get_msgpack_float_prefix(static_cast<float>(n)));
17607 write_number(static_cast<float>(n));
17608 }
17609 else
17610 {
17611 oa->write_character(format == detail::input_format_t::cbor
17612 ? get_cbor_float_prefix(n)
17613 : get_msgpack_float_prefix(n));
17614 write_number(n);
17615 }
17616#ifdef __GNUC__
17617#pragma GCC diagnostic pop
17618#endif
17619 }
17620
17621 public:
17622 // The following to_char_type functions are implement the conversion
17623 // between uint8_t and CharType. In case CharType is not unsigned,
17624 // such a conversion is required to allow values greater than 128.
17625 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
17626 template < typename C = CharType,
17627 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
17628 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17629 {
17630 return *reinterpret_cast<char*>(&x);
17631 }
17632
17633 template < typename C = CharType,
17634 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
17635 static CharType to_char_type(std::uint8_t x) noexcept
17636 {
17637 // The std::is_trivial trait is deprecated in C++26. The replacement is to use
17638 // std::is_trivially_copyable and std::is_trivially_default_constructible.
17639 // However, some older library implementations support std::is_trivial
17640 // but not all the std::is_trivially_* traits.
17641 // Since detecting full support across all libraries is difficult,
17642 // we use std::is_trivial unless we are using a standard where it has been deprecated.
17643 // For more details, see: https://github.com/nlohmann/json/pull/4775#issuecomment-2884361627
17644#ifdef JSON_HAS_CPP_26
17645 static_assert(std::is_trivially_copyable<CharType>::value, "CharType must be trivially copyable");
17646 static_assert(std::is_trivially_default_constructible<CharType>::value, "CharType must be trivially default constructible");
17647#else
17648 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
17649#endif
17650
17651 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
17652 CharType result;
17653 std::memcpy(&result, &x, sizeof(x));
17654 return result;
17655 }
17656
17657 template<typename C = CharType,
17658 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
17659 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17660 {
17661 return x;
17662 }
17663
17664 template < typename InputCharType, typename C = CharType,
17665 enable_if_t <
17666 std::is_signed<C>::value &&
17667 std::is_signed<char>::value &&
17668 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
17669 > * = nullptr >
17670 static constexpr CharType to_char_type(InputCharType x) noexcept
17671 {
17672 return x;
17673 }
17674
17675 private:
17677 const bool is_little_endian = little_endianness();
17678
17680 output_adapter_t<CharType> oa = nullptr;
17681};
17682
17683} // namespace detail
17684NLOHMANN_JSON_NAMESPACE_END
17685
17686// #include <nlohmann/detail/output/output_adapters.hpp>
17687
17688// #include <nlohmann/detail/output/serializer.hpp>
17689// __ _____ _____ _____
17690// __| | __| | | | JSON for Modern C++
17691// | | |__ | | | | | | version 3.12.0
17692// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17693//
17694// SPDX-FileCopyrightText: 2008 - 2009 Björn Hoehrmann <bjoern@hoehrmann.de>
17695// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17696// SPDX-License-Identifier: MIT
17697
17698
17699
17700#include <algorithm> // reverse, remove, fill, find, none_of
17701#include <array> // array
17702#include <clocale> // localeconv, lconv
17703#include <cmath> // labs, isfinite, isnan, signbit
17704#include <cstddef> // size_t, ptrdiff_t
17705#include <cstdint> // uint8_t
17706#include <cstdio> // snprintf
17707#include <limits> // numeric_limits
17708#include <string> // string, char_traits
17709#include <iomanip> // setfill, setw
17710#include <type_traits> // is_same
17711#include <utility> // move
17712
17713// #include <nlohmann/detail/conversions/to_chars.hpp>
17714// __ _____ _____ _____
17715// __| | __| | | | JSON for Modern C++
17716// | | |__ | | | | | | version 3.12.0
17717// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17718//
17719// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
17720// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17721// SPDX-License-Identifier: MIT
17722
17723
17724
17725#include <array> // array
17726#include <cmath> // signbit, isfinite
17727#include <cstdint> // intN_t, uintN_t
17728#include <cstring> // memcpy, memmove
17729#include <limits> // numeric_limits
17730#include <type_traits> // conditional
17731
17732// #include <nlohmann/detail/macro_scope.hpp>
17733
17734
17735NLOHMANN_JSON_NAMESPACE_BEGIN
17736namespace detail
17737{
17738
17758namespace dtoa_impl
17759{
17760
17761template<typename Target, typename Source>
17762Target reinterpret_bits(const Source source)
17763{
17764 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
17765
17766 Target target;
17767 std::memcpy(&target, &source, sizeof(Source));
17768 return target;
17769}
17770
17771struct diyfp // f * 2^e
17772{
17773 static constexpr int kPrecision = 64; // = q
17774
17775 std::uint64_t f = 0;
17776 int e = 0;
17777
17778 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
17779
17784 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
17785 {
17786 JSON_ASSERT(x.e == y.e);
17787 JSON_ASSERT(x.f >= y.f);
17788
17789 return {x.f - y.f, x.e};
17790 }
17791
17796 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17797 {
17798 static_assert(kPrecision == 64, "internal error");
17799
17800 // Computes:
17801 // f = round((x.f * y.f) / 2^q)
17802 // e = x.e + y.e + q
17803
17804 // Emulate the 64-bit * 64-bit multiplication:
17805 //
17806 // p = u * v
17807 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17808 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17809 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17810 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17811 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17812 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17813 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17814 //
17815 // (Since Q might be larger than 2^32 - 1)
17816 //
17817 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17818 //
17819 // (Q_hi + H does not overflow a 64-bit int)
17820 //
17821 // = p_lo + 2^64 p_hi
17822
17823 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17824 const std::uint64_t u_hi = x.f >> 32u;
17825 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17826 const std::uint64_t v_hi = y.f >> 32u;
17827
17828 const std::uint64_t p0 = u_lo * v_lo;
17829 const std::uint64_t p1 = u_lo * v_hi;
17830 const std::uint64_t p2 = u_hi * v_lo;
17831 const std::uint64_t p3 = u_hi * v_hi;
17832
17833 const std::uint64_t p0_hi = p0 >> 32u;
17834 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17835 const std::uint64_t p1_hi = p1 >> 32u;
17836 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17837 const std::uint64_t p2_hi = p2 >> 32u;
17838
17839 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17840
17841 // The full product might now be computed as
17842 //
17843 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17844 // p_lo = p0_lo + (Q << 32)
17845 //
17846 // But in this particular case here, the full p_lo is not required.
17847 // Effectively, we only need to add the highest bit in p_lo to p_hi (and
17848 // Q_hi + 1 does not overflow).
17849
17850 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17851
17852 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17853
17854 return {h, x.e + y.e + 64};
17855 }
17856
17861 static diyfp normalize(diyfp x) noexcept
17862 {
17863 JSON_ASSERT(x.f != 0);
17864
17865 while ((x.f >> 63u) == 0)
17866 {
17867 x.f <<= 1u;
17868 x.e--;
17869 }
17870
17871 return x;
17872 }
17873
17878 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17879 {
17880 const int delta = x.e - target_exponent;
17881
17882 JSON_ASSERT(delta >= 0);
17883 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17884
17885 return {x.f << delta, target_exponent};
17886 }
17887};
17888
17889struct boundaries
17890{
17891 diyfp w;
17892 diyfp minus;
17893 diyfp plus;
17894};
17895
17902template<typename FloatType>
17903boundaries compute_boundaries(FloatType value)
17904{
17905 JSON_ASSERT(std::isfinite(value));
17906 JSON_ASSERT(value > 0);
17907
17908 // Convert the IEEE representation into a diyfp.
17909 //
17910 // If v is denormal:
17911 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17912 // If v is normalized:
17913 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17914
17915 static_assert(std::numeric_limits<FloatType>::is_iec559,
17916 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17917
17918 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17919 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17920 constexpr int kMinExp = 1 - kBias;
17921 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17922
17923 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17924
17925 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17926 const std::uint64_t E = bits >> (kPrecision - 1);
17927 const std::uint64_t F = bits & (kHiddenBit - 1);
17928
17929 const bool is_denormal = E == 0;
17930 const diyfp v = is_denormal
17931 ? diyfp(F, kMinExp)
17932 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17933
17934 // Compute the boundaries m- and m+ of the floating-point value
17935 // v = f * 2^e.
17936 //
17937 // Determine v- and v+, the floating-point predecessor and successor of v,
17938 // respectively.
17939 //
17940 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17941 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17942 //
17943 // v+ = v + 2^e
17944 //
17945 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17946 // between m- and m+ round to v, regardless of how the input rounding
17947 // algorithm breaks ties.
17948 //
17949 // ---+-------------+-------------+-------------+-------------+--- (A)
17950 // v- m- v m+ v+
17951 //
17952 // -----------------+------+------+-------------+-------------+--- (B)
17953 // v- m- v m+ v+
17954
17955 const bool lower_boundary_is_closer = F == 0 && E > 1;
17956 const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
17957 const diyfp m_minus = lower_boundary_is_closer
17958 ? diyfp((4 * v.f) - 1, v.e - 2) // (B)
17959 : diyfp((2 * v.f) - 1, v.e - 1); // (A)
17960
17961 // Determine the normalized w+ = m+.
17962 const diyfp w_plus = diyfp::normalize(m_plus);
17963
17964 // Determine w- = m- such that e_(w-) = e_(w+).
17965 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17966
17967 return {diyfp::normalize(v), w_minus, w_plus};
17968}
17969
17970// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17971// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17972// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17973//
17974// alpha <= e = e_c + e_w + q <= gamma
17975//
17976// or
17977//
17978// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17979// <= f_c * f_w * 2^gamma
17980//
17981// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17982//
17983// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17984//
17985// or
17986//
17987// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17988//
17989// The choice of (alpha,gamma) determines the size of the table and the form of
17990// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17991// in practice:
17992//
17993// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17994// processed independently: An integral part p1, and a fractional part p2:
17995//
17996// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17997// = (f div 2^-e) + (f mod 2^-e) * 2^e
17998// = p1 + p2 * 2^e
17999//
18000// The conversion of p1 into decimal form requires a series of divisions and
18001// modulos by (a power of) 10. These operations are faster for 32-bit than for
18002// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
18003// achieved by choosing
18004//
18005// -e >= 32 or e <= -32 := gamma
18006//
18007// In order to convert the fractional part
18008//
18009// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
18010//
18011// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
18012// d[-i] are extracted in order:
18013//
18014// (10 * p2) div 2^-e = d[-1]
18015// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
18016//
18017// The multiplication by 10 must not overflow. It is sufficient to choose
18018//
18019// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
18020//
18021// Since p2 = f mod 2^-e < 2^-e,
18022//
18023// -e <= 60 or e >= -60 := alpha
18024
18025constexpr int kAlpha = -60;
18026constexpr int kGamma = -32;
18027
18028struct cached_power // c = f * 2^e ~= 10^k
18029{
18030 std::uint64_t f;
18031 int e;
18032 int k;
18033};
18034
18042inline cached_power get_cached_power_for_binary_exponent(int e)
18043{
18044 // Now
18045 //
18046 // alpha <= e_c + e + q <= gamma (1)
18047 // ==> f_c * 2^alpha <= c * 2^e * 2^q
18048 //
18049 // and since the c's are normalized, 2^(q-1) <= f_c,
18050 //
18051 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
18052 // ==> 2^(alpha - e - 1) <= c
18053 //
18054 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
18055 //
18056 // k = ceil( log_10( 2^(alpha - e - 1) ) )
18057 // = ceil( (alpha - e - 1) * log_10(2) )
18058 //
18059 // From the paper:
18060 // "In theory the result of the procedure could be wrong since c is rounded,
18061 // and the computation itself is approximated [...]. In practice, however,
18062 // this simple function is sufficient."
18063 //
18064 // For IEEE double precision floating-point numbers converted into
18065 // normalized diyfp's w = f * 2^e, with q = 64,
18066 //
18067 // e >= -1022 (min IEEE exponent)
18068 // -52 (p - 1)
18069 // -52 (p - 1, possibly normalize denormal IEEE numbers)
18070 // -11 (normalize the diyfp)
18071 // = -1137
18072 //
18073 // and
18074 //
18075 // e <= +1023 (max IEEE exponent)
18076 // -52 (p - 1)
18077 // -11 (normalize the diyfp)
18078 // = 960
18079 //
18080 // This binary exponent range [-1137,960] results in a decimal exponent
18081 // range [-307,324]. One does not need to store a cached power for each
18082 // k in this range. For each such k it suffices to find a cached power
18083 // such that the exponent of the product lies in [alpha,gamma].
18084 // This implies that the difference of the decimal exponents of adjacent
18085 // table entries must be less than or equal to
18086 //
18087 // floor( (gamma - alpha) * log_10(2) ) = 8.
18088 //
18089 // (A smaller distance gamma-alpha would require a larger table.)
18090
18091 // NB:
18092 // Actually, this function returns c, such that -60 <= e_c + e + 64 <= -34.
18093
18094 constexpr int kCachedPowersMinDecExp = -300;
18095 constexpr int kCachedPowersDecStep = 8;
18096
18097 static constexpr std::array<cached_power, 79> kCachedPowers =
18098 {
18099 {
18100 { 0xAB70FE17C79AC6CA, -1060, -300 },
18101 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
18102 { 0xBE5691EF416BD60C, -1007, -284 },
18103 { 0x8DD01FAD907FFC3C, -980, -276 },
18104 { 0xD3515C2831559A83, -954, -268 },
18105 { 0x9D71AC8FADA6C9B5, -927, -260 },
18106 { 0xEA9C227723EE8BCB, -901, -252 },
18107 { 0xAECC49914078536D, -874, -244 },
18108 { 0x823C12795DB6CE57, -847, -236 },
18109 { 0xC21094364DFB5637, -821, -228 },
18110 { 0x9096EA6F3848984F, -794, -220 },
18111 { 0xD77485CB25823AC7, -768, -212 },
18112 { 0xA086CFCD97BF97F4, -741, -204 },
18113 { 0xEF340A98172AACE5, -715, -196 },
18114 { 0xB23867FB2A35B28E, -688, -188 },
18115 { 0x84C8D4DFD2C63F3B, -661, -180 },
18116 { 0xC5DD44271AD3CDBA, -635, -172 },
18117 { 0x936B9FCEBB25C996, -608, -164 },
18118 { 0xDBAC6C247D62A584, -582, -156 },
18119 { 0xA3AB66580D5FDAF6, -555, -148 },
18120 { 0xF3E2F893DEC3F126, -529, -140 },
18121 { 0xB5B5ADA8AAFF80B8, -502, -132 },
18122 { 0x87625F056C7C4A8B, -475, -124 },
18123 { 0xC9BCFF6034C13053, -449, -116 },
18124 { 0x964E858C91BA2655, -422, -108 },
18125 { 0xDFF9772470297EBD, -396, -100 },
18126 { 0xA6DFBD9FB8E5B88F, -369, -92 },
18127 { 0xF8A95FCF88747D94, -343, -84 },
18128 { 0xB94470938FA89BCF, -316, -76 },
18129 { 0x8A08F0F8BF0F156B, -289, -68 },
18130 { 0xCDB02555653131B6, -263, -60 },
18131 { 0x993FE2C6D07B7FAC, -236, -52 },
18132 { 0xE45C10C42A2B3B06, -210, -44 },
18133 { 0xAA242499697392D3, -183, -36 },
18134 { 0xFD87B5F28300CA0E, -157, -28 },
18135 { 0xBCE5086492111AEB, -130, -20 },
18136 { 0x8CBCCC096F5088CC, -103, -12 },
18137 { 0xD1B71758E219652C, -77, -4 },
18138 { 0x9C40000000000000, -50, 4 },
18139 { 0xE8D4A51000000000, -24, 12 },
18140 { 0xAD78EBC5AC620000, 3, 20 },
18141 { 0x813F3978F8940984, 30, 28 },
18142 { 0xC097CE7BC90715B3, 56, 36 },
18143 { 0x8F7E32CE7BEA5C70, 83, 44 },
18144 { 0xD5D238A4ABE98068, 109, 52 },
18145 { 0x9F4F2726179A2245, 136, 60 },
18146 { 0xED63A231D4C4FB27, 162, 68 },
18147 { 0xB0DE65388CC8ADA8, 189, 76 },
18148 { 0x83C7088E1AAB65DB, 216, 84 },
18149 { 0xC45D1DF942711D9A, 242, 92 },
18150 { 0x924D692CA61BE758, 269, 100 },
18151 { 0xDA01EE641A708DEA, 295, 108 },
18152 { 0xA26DA3999AEF774A, 322, 116 },
18153 { 0xF209787BB47D6B85, 348, 124 },
18154 { 0xB454E4A179DD1877, 375, 132 },
18155 { 0x865B86925B9BC5C2, 402, 140 },
18156 { 0xC83553C5C8965D3D, 428, 148 },
18157 { 0x952AB45CFA97A0B3, 455, 156 },
18158 { 0xDE469FBD99A05FE3, 481, 164 },
18159 { 0xA59BC234DB398C25, 508, 172 },
18160 { 0xF6C69A72A3989F5C, 534, 180 },
18161 { 0xB7DCBF5354E9BECE, 561, 188 },
18162 { 0x88FCF317F22241E2, 588, 196 },
18163 { 0xCC20CE9BD35C78A5, 614, 204 },
18164 { 0x98165AF37B2153DF, 641, 212 },
18165 { 0xE2A0B5DC971F303A, 667, 220 },
18166 { 0xA8D9D1535CE3B396, 694, 228 },
18167 { 0xFB9B7CD9A4A7443C, 720, 236 },
18168 { 0xBB764C4CA7A44410, 747, 244 },
18169 { 0x8BAB8EEFB6409C1A, 774, 252 },
18170 { 0xD01FEF10A657842C, 800, 260 },
18171 { 0x9B10A4E5E9913129, 827, 268 },
18172 { 0xE7109BFBA19C0C9D, 853, 276 },
18173 { 0xAC2820D9623BF429, 880, 284 },
18174 { 0x80444B5E7AA7CF85, 907, 292 },
18175 { 0xBF21E44003ACDD2D, 933, 300 },
18176 { 0x8E679C2F5E44FF8F, 960, 308 },
18177 { 0xD433179D9C8CB841, 986, 316 },
18178 { 0x9E19DB92B4E31BA9, 1013, 324 },
18179 }
18180 };
18181
18182 // This computation gives exactly the same results for k as
18183 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
18184 // for |e| <= 1500, but doesn't require floating-point operations.
18185 // NB: log_10(2) ~= 78913 / 2^18
18186 JSON_ASSERT(e >= -1500);
18187 JSON_ASSERT(e <= 1500);
18188 const int f = kAlpha - e - 1;
18189 const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
18190
18191 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
18192 JSON_ASSERT(index >= 0);
18193 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
18194
18195 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
18196 JSON_ASSERT(kAlpha <= cached.e + e + 64);
18197 JSON_ASSERT(kGamma >= cached.e + e + 64);
18198
18199 return cached;
18200}
18201
18206inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
18207{
18208 // LCOV_EXCL_START
18209 if (n >= 1000000000)
18210 {
18211 pow10 = 1000000000;
18212 return 10;
18213 }
18214 // LCOV_EXCL_STOP
18215 if (n >= 100000000)
18216 {
18217 pow10 = 100000000;
18218 return 9;
18219 }
18220 if (n >= 10000000)
18221 {
18222 pow10 = 10000000;
18223 return 8;
18224 }
18225 if (n >= 1000000)
18226 {
18227 pow10 = 1000000;
18228 return 7;
18229 }
18230 if (n >= 100000)
18231 {
18232 pow10 = 100000;
18233 return 6;
18234 }
18235 if (n >= 10000)
18236 {
18237 pow10 = 10000;
18238 return 5;
18239 }
18240 if (n >= 1000)
18241 {
18242 pow10 = 1000;
18243 return 4;
18244 }
18245 if (n >= 100)
18246 {
18247 pow10 = 100;
18248 return 3;
18249 }
18250 if (n >= 10)
18251 {
18252 pow10 = 10;
18253 return 2;
18254 }
18255
18256 pow10 = 1;
18257 return 1;
18258}
18259
18260inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
18261 std::uint64_t rest, std::uint64_t ten_k)
18262{
18263 JSON_ASSERT(len >= 1);
18264 JSON_ASSERT(dist <= delta);
18265 JSON_ASSERT(rest <= delta);
18266 JSON_ASSERT(ten_k > 0);
18267
18268 // <--------------------------- delta ---->
18269 // <---- dist --------->
18270 // --------------[------------------+-------------------]--------------
18271 // M- w M+
18272 //
18273 // ten_k
18274 // <------>
18275 // <---- rest ---->
18276 // --------------[------------------+----+--------------]--------------
18277 // w V
18278 // = buf * 10^k
18279 //
18280 // ten_k represents a unit-in-the-last-place in the decimal representation
18281 // stored in buf.
18282 // Decrement buf by ten_k while this takes buf closer to w.
18283
18284 // The tests are written in this order to avoid overflow in unsigned
18285 // integer arithmetic.
18286
18287 while (rest < dist
18288 && delta - rest >= ten_k
18289 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
18290 {
18291 JSON_ASSERT(buf[len - 1] != '0');
18292 buf[len - 1]--;
18293 rest += ten_k;
18294 }
18295}
18296
18301inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
18302 diyfp M_minus, diyfp w, diyfp M_plus)
18303{
18304 static_assert(kAlpha >= -60, "internal error");
18305 static_assert(kGamma <= -32, "internal error");
18306
18307 // Generates the digits (and the exponent) of a decimal floating-point
18308 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
18309 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
18310 //
18311 // <--------------------------- delta ---->
18312 // <---- dist --------->
18313 // --------------[------------------+-------------------]--------------
18314 // M- w M+
18315 //
18316 // Grisu2 generates the digits of M+ from left to right and stops as soon as
18317 // V is in [M-,M+].
18318
18319 JSON_ASSERT(M_plus.e >= kAlpha);
18320 JSON_ASSERT(M_plus.e <= kGamma);
18321
18322 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
18323 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
18324
18325 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
18326 //
18327 // M+ = f * 2^e
18328 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
18329 // = ((p1 ) * 2^-e + (p2 )) * 2^e
18330 // = p1 + p2 * 2^e
18331
18332 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
18333
18334 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.)
18335 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
18336
18337 // 1)
18338 //
18339 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
18340
18341 JSON_ASSERT(p1 > 0);
18342
18343 std::uint32_t pow10{};
18344 const int k = find_largest_pow10(p1, pow10);
18345
18346 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
18347 //
18348 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
18349 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
18350 //
18351 // M+ = p1 + p2 * 2^e
18352 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
18353 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
18354 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
18355 //
18356 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
18357 //
18358 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
18359 //
18360 // but stop as soon as
18361 //
18362 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
18363
18364 int n = k;
18365 while (n > 0)
18366 {
18367 // Invariants:
18368 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
18369 // pow10 = 10^(n-1) <= p1 < 10^n
18370 //
18371 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
18372 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
18373 //
18374 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
18375 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
18376 //
18377 JSON_ASSERT(d <= 9);
18378 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18379 //
18380 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
18381 //
18382 p1 = r;
18383 n--;
18384 //
18385 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
18386 // pow10 = 10^n
18387 //
18388
18389 // Now check if enough digits have been generated.
18390 // Compute
18391 //
18392 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
18393 //
18394 // Note:
18395 // Since rest and delta share the same exponent e, it suffices to
18396 // compare the significands.
18397 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
18398 if (rest <= delta)
18399 {
18400 // V = buffer * 10^n, with M- <= V <= M+.
18401
18402 decimal_exponent += n;
18403
18404 // We may now just stop. But instead, it looks as if the buffer
18405 // could be decremented to bring V closer to w.
18406 //
18407 // pow10 = 10^n is now 1 ulp in the decimal representation V.
18408 // The rounding procedure works with diyfp's with an implicit
18409 // exponent of e.
18410 //
18411 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
18412 //
18413 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
18414 grisu2_round(buffer, length, dist, delta, rest, ten_n);
18415
18416 return;
18417 }
18418
18419 pow10 /= 10;
18420 //
18421 // pow10 = 10^(n-1) <= p1 < 10^n
18422 // Invariants restored.
18423 }
18424
18425 // 2)
18426 //
18427 // The digits of the integral part have been generated:
18428 //
18429 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
18430 // = buffer + p2 * 2^e
18431 //
18432 // Now generate the digits of the fractional part p2 * 2^e.
18433 //
18434 // Note:
18435 // No decimal point is generated: the exponent is adjusted instead.
18436 //
18437 // p2 actually represents the fraction
18438 //
18439 // p2 * 2^e
18440 // = p2 / 2^-e
18441 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
18442 //
18443 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
18444 //
18445 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
18446 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
18447 //
18448 // using
18449 //
18450 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
18451 // = ( d) * 2^-e + ( r)
18452 //
18453 // or
18454 // 10^m * p2 * 2^e = d + r * 2^e
18455 //
18456 // i.e.
18457 //
18458 // M+ = buffer + p2 * 2^e
18459 // = buffer + 10^-m * (d + r * 2^e)
18460 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
18461 //
18462 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
18463
18464 JSON_ASSERT(p2 > delta);
18465
18466 int m = 0;
18467 for (;;)
18468 {
18469 // Invariant:
18470 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
18471 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
18472 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
18473 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
18474 //
18475 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
18476 p2 *= 10;
18477 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
18478 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
18479 //
18480 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
18481 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
18482 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
18483 //
18484 JSON_ASSERT(d <= 9);
18485 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18486 //
18487 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
18488 //
18489 p2 = r;
18490 m++;
18491 //
18492 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
18493 // Invariant restored.
18494
18495 // Check if enough digits have been generated.
18496 //
18497 // 10^-m * p2 * 2^e <= delta * 2^e
18498 // p2 * 2^e <= 10^m * delta * 2^e
18499 // p2 <= 10^m * delta
18500 delta *= 10;
18501 dist *= 10;
18502 if (p2 <= delta)
18503 {
18504 break;
18505 }
18506 }
18507
18508 // V = buffer * 10^-m, with M- <= V <= M+.
18509
18510 decimal_exponent -= m;
18511
18512 // 1 ulp in the decimal representation is now 10^-m.
18513 // Since delta and dist are now scaled by 10^m, we need to do the
18514 // same with ulp in order to keep the units in sync.
18515 //
18516 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
18517 //
18518 const std::uint64_t ten_m = one.f;
18519 grisu2_round(buffer, length, dist, delta, p2, ten_m);
18520
18521 // By construction this algorithm generates the shortest possible decimal
18522 // number (Loitsch, Theorem 6.2) which rounds back to w.
18523 // For an input number of precision p, at least
18524 //
18525 // N = 1 + ceil(p * log_10(2))
18526 //
18527 // decimal digits are sufficient to identify all binary floating-point
18528 // numbers (Matula, "In-and-Out conversions").
18529 // This implies that the algorithm does not produce more than N decimal
18530 // digits.
18531 //
18532 // N = 17 for p = 53 (IEEE double precision)
18533 // N = 9 for p = 24 (IEEE single precision)
18534}
18535
18541JSON_HEDLEY_NON_NULL(1)
18542inline void grisu2(char* buf, int& len, int& decimal_exponent,
18543 diyfp m_minus, diyfp v, diyfp m_plus)
18544{
18545 JSON_ASSERT(m_plus.e == m_minus.e);
18546 JSON_ASSERT(m_plus.e == v.e);
18547
18548 // --------(-----------------------+-----------------------)-------- (A)
18549 // m- v m+
18550 //
18551 // --------------------(-----------+-----------------------)-------- (B)
18552 // m- v m+
18553 //
18554 // First scale v (and m- and m+) such that the exponent is in the range
18555 // [alpha, gamma].
18556
18557 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
18558
18559 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
18560
18561 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
18562 const diyfp w = diyfp::mul(v, c_minus_k);
18563 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
18564 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
18565
18566 // ----(---+---)---------------(---+---)---------------(---+---)----
18567 // w- w w+
18568 // = c*m- = c*v = c*m+
18569 //
18570 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
18571 // w+ are now off by a small amount.
18572 // In fact:
18573 //
18574 // w - v * 10^k < 1 ulp
18575 //
18576 // To account for this inaccuracy, add resp. subtract 1 ulp.
18577 //
18578 // --------+---[---------------(---+---)---------------]---+--------
18579 // w- M- w M+ w+
18580 //
18581 // Now any number in [M-, M+] (bounds included) will round to w when input,
18582 // regardless of how the input rounding algorithm breaks ties.
18583 //
18584 // And digit_gen generates the shortest possible such number in [M-, M+].
18585 // Note that this does not mean that Grisu2 always generates the shortest
18586 // possible number in the interval (m-, m+).
18587 const diyfp M_minus(w_minus.f + 1, w_minus.e);
18588 const diyfp M_plus (w_plus.f - 1, w_plus.e );
18589
18590 decimal_exponent = -cached.k; // = -(-k) = k
18591
18592 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
18593}
18594
18600template<typename FloatType>
18601JSON_HEDLEY_NON_NULL(1)
18602void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
18603{
18604 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
18605 "internal error: not enough precision");
18606
18607 JSON_ASSERT(std::isfinite(value));
18608 JSON_ASSERT(value > 0);
18609
18610 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
18611 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
18612 // decimal representations are not exactly "short".
18613 //
18614 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
18615 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
18616 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
18617 // does.
18618 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
18619 // representation using the corresponding std::from_chars function recovers value exactly". That
18620 // indicates that single precision floating-point numbers should be recovered using
18621 // 'std::strtof'.
18622 //
18623 // NB: If the neighbors are computed for single-precision numbers, there is a single float
18624 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
18625 // value is off by 1 ulp.
18626#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
18627 const boundaries w = compute_boundaries(static_cast<double>(value));
18628#else
18629 const boundaries w = compute_boundaries(value);
18630#endif
18631
18632 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
18633}
18634
18640JSON_HEDLEY_NON_NULL(1)
18641JSON_HEDLEY_RETURNS_NON_NULL
18642inline char* append_exponent(char* buf, int e)
18643{
18644 JSON_ASSERT(e > -1000);
18645 JSON_ASSERT(e < 1000);
18646
18647 if (e < 0)
18648 {
18649 e = -e;
18650 *buf++ = '-';
18651 }
18652 else
18653 {
18654 *buf++ = '+';
18655 }
18656
18657 auto k = static_cast<std::uint32_t>(e);
18658 if (k < 10)
18659 {
18660 // Always print at least two digits in the exponent.
18661 // This is for compatibility with printf("%g").
18662 *buf++ = '0';
18663 *buf++ = static_cast<char>('0' + k);
18664 }
18665 else if (k < 100)
18666 {
18667 *buf++ = static_cast<char>('0' + (k / 10));
18668 k %= 10;
18669 *buf++ = static_cast<char>('0' + k);
18670 }
18671 else
18672 {
18673 *buf++ = static_cast<char>('0' + (k / 100));
18674 k %= 100;
18675 *buf++ = static_cast<char>('0' + (k / 10));
18676 k %= 10;
18677 *buf++ = static_cast<char>('0' + k);
18678 }
18679
18680 return buf;
18681}
18682
18692JSON_HEDLEY_NON_NULL(1)
18693JSON_HEDLEY_RETURNS_NON_NULL
18694inline char* format_buffer(char* buf, int len, int decimal_exponent,
18695 int min_exp, int max_exp)
18696{
18697 JSON_ASSERT(min_exp < 0);
18698 JSON_ASSERT(max_exp > 0);
18699
18700 const int k = len;
18701 const int n = len + decimal_exponent;
18702
18703 // v = buf * 10^(n-k)
18704 // k is the length of the buffer (number of decimal digits)
18705 // n is the position of the decimal point relative to the start of the buffer.
18706
18707 if (k <= n && n <= max_exp)
18708 {
18709 // digits[000]
18710 // len <= max_exp + 2
18711
18712 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
18713 // Make it look like a floating-point number (#362, #378)
18714 buf[n + 0] = '.';
18715 buf[n + 1] = '0';
18716 return buf + (static_cast<size_t>(n) + 2);
18717 }
18718
18719 if (0 < n && n <= max_exp)
18720 {
18721 // dig.its
18722 // len <= max_digits10 + 1
18723
18724 JSON_ASSERT(k > n);
18725
18726 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
18727 buf[n] = '.';
18728 return buf + (static_cast<size_t>(k) + 1U);
18729 }
18730
18731 if (min_exp < n && n <= 0)
18732 {
18733 // 0.[000]digits
18734 // len <= 2 + (-min_exp - 1) + max_digits10
18735
18736 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
18737 buf[0] = '0';
18738 buf[1] = '.';
18739 std::memset(buf + 2, '0', static_cast<size_t>(-n));
18740 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
18741 }
18742
18743 if (k == 1)
18744 {
18745 // dE+123
18746 // len <= 1 + 5
18747
18748 buf += 1;
18749 }
18750 else
18751 {
18752 // d.igitsE+123
18753 // len <= max_digits10 + 1 + 5
18754
18755 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
18756 buf[1] = '.';
18757 buf += 1 + static_cast<size_t>(k);
18758 }
18759
18760 *buf++ = 'e';
18761 return append_exponent(buf, n - 1);
18762}
18763
18764} // namespace dtoa_impl
18765
18776template<typename FloatType>
18777JSON_HEDLEY_NON_NULL(1, 2)
18778JSON_HEDLEY_RETURNS_NON_NULL
18779char* to_chars(char* first, const char* last, FloatType value)
18780{
18781 static_cast<void>(last); // maybe unused - fix warning
18782 JSON_ASSERT(std::isfinite(value));
18783
18784 // Use signbit(value) instead of (value < 0) since signbit works for -0.
18785 if (std::signbit(value))
18786 {
18787 value = -value;
18788 *first++ = '-';
18789 }
18790
18791#ifdef __GNUC__
18792#pragma GCC diagnostic push
18793#pragma GCC diagnostic ignored "-Wfloat-equal"
18794#endif
18795 if (value == 0) // +-0
18796 {
18797 *first++ = '0';
18798 // Make it look like a floating-point number (#362, #378)
18799 *first++ = '.';
18800 *first++ = '0';
18801 return first;
18802 }
18803#ifdef __GNUC__
18804#pragma GCC diagnostic pop
18805#endif
18806
18807 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18808
18809 // Compute v = buffer * 10^decimal_exponent.
18810 // The decimal digits are stored in the buffer, which needs to be interpreted
18811 // as an unsigned decimal integer.
18812 // len is the length of the buffer, i.e., the number of decimal digits.
18813 int len = 0;
18814 int decimal_exponent = 0;
18815 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18816
18817 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18818
18819 // Format the buffer like printf("%.*g", prec, value)
18820 constexpr int kMinExp = -4;
18821 // Use digits10 here to increase compatibility with version 2.
18822 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18823
18824 JSON_ASSERT(last - first >= kMaxExp + 2);
18825 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18826 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18827
18828 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18829}
18830
18831} // namespace detail
18832NLOHMANN_JSON_NAMESPACE_END
18833
18834// #include <nlohmann/detail/exceptions.hpp>
18835
18836// #include <nlohmann/detail/macro_scope.hpp>
18837
18838// #include <nlohmann/detail/meta/cpp_future.hpp>
18839
18840// #include <nlohmann/detail/output/binary_writer.hpp>
18841
18842// #include <nlohmann/detail/output/output_adapters.hpp>
18843
18844// #include <nlohmann/detail/string_concat.hpp>
18845
18846// #include <nlohmann/detail/value_t.hpp>
18847
18848
18849NLOHMANN_JSON_NAMESPACE_BEGIN
18850namespace detail
18851{
18852
18854// serialization //
18856
18859{
18860 strict,
18861 replace,
18862 ignore
18863};
18864
18865template<typename BasicJsonType>
18867{
18868 using string_t = typename BasicJsonType::string_t;
18869 using number_float_t = typename BasicJsonType::number_float_t;
18870 using number_integer_t = typename BasicJsonType::number_integer_t;
18871 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18872 using binary_char_t = typename BasicJsonType::binary_t::value_type;
18873 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18874 static constexpr std::uint8_t UTF8_REJECT = 1;
18875
18876 public:
18882 serializer(output_adapter_t<char> s, const char ichar,
18883 error_handler_t error_handler_ = error_handler_t::strict)
18884 : o(std::move(s))
18885 , loc(std::localeconv())
18886 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18887 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18888 , indent_char(ichar)
18889 , indent_string(512, indent_char)
18890 , error_handler(error_handler_)
18891 {}
18892
18893 // deleted because of pointer members
18894 serializer(const serializer&) = delete;
18895 serializer& operator=(const serializer&) = delete;
18896 serializer(serializer&&) = delete;
18897 serializer& operator=(serializer&&) = delete;
18898 ~serializer() = default;
18899
18922 void dump(const BasicJsonType& val,
18923 const bool pretty_print,
18924 const bool ensure_ascii,
18925 const unsigned int indent_step,
18926 const unsigned int current_indent = 0)
18927 {
18928 switch (val.m_data.m_type)
18929 {
18930 case value_t::object:
18931 {
18932 if (val.m_data.m_value.object->empty())
18933 {
18934 o->write_characters("{}", 2);
18935 return;
18936 }
18937
18938 if (pretty_print)
18939 {
18940 o->write_characters("{\n", 2);
18941
18942 // variable to hold indentation for recursive calls
18943 const auto new_indent = current_indent + indent_step;
18944 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18945 {
18946 indent_string.resize(indent_string.size() * 2, ' ');
18947 }
18948
18949 // first n-1 elements
18950 auto i = val.m_data.m_value.object->cbegin();
18951 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18952 {
18953 o->write_characters(indent_string.c_str(), new_indent);
18954 o->write_character('\"');
18955 dump_escaped(i->first, ensure_ascii);
18956 o->write_characters("\": ", 3);
18957 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18958 o->write_characters(",\n", 2);
18959 }
18960
18961 // last element
18962 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18963 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18964 o->write_characters(indent_string.c_str(), new_indent);
18965 o->write_character('\"');
18966 dump_escaped(i->first, ensure_ascii);
18967 o->write_characters("\": ", 3);
18968 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18969
18970 o->write_character('\n');
18971 o->write_characters(indent_string.c_str(), current_indent);
18972 o->write_character('}');
18973 }
18974 else
18975 {
18976 o->write_character('{');
18977
18978 // first n-1 elements
18979 auto i = val.m_data.m_value.object->cbegin();
18980 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18981 {
18982 o->write_character('\"');
18983 dump_escaped(i->first, ensure_ascii);
18984 o->write_characters("\":", 2);
18985 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18986 o->write_character(',');
18987 }
18988
18989 // last element
18990 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18991 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18992 o->write_character('\"');
18993 dump_escaped(i->first, ensure_ascii);
18994 o->write_characters("\":", 2);
18995 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18996
18997 o->write_character('}');
18998 }
18999
19000 return;
19001 }
19002
19003 case value_t::array:
19004 {
19005 if (val.m_data.m_value.array->empty())
19006 {
19007 o->write_characters("[]", 2);
19008 return;
19009 }
19010
19011 if (pretty_print)
19012 {
19013 o->write_characters("[\n", 2);
19014
19015 // variable to hold indentation for recursive calls
19016 const auto new_indent = current_indent + indent_step;
19017 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
19018 {
19019 indent_string.resize(indent_string.size() * 2, ' ');
19020 }
19021
19022 // first n-1 elements
19023 for (auto i = val.m_data.m_value.array->cbegin();
19024 i != val.m_data.m_value.array->cend() - 1; ++i)
19025 {
19026 o->write_characters(indent_string.c_str(), new_indent);
19027 dump(*i, true, ensure_ascii, indent_step, new_indent);
19028 o->write_characters(",\n", 2);
19029 }
19030
19031 // last element
19032 JSON_ASSERT(!val.m_data.m_value.array->empty());
19033 o->write_characters(indent_string.c_str(), new_indent);
19034 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
19035
19036 o->write_character('\n');
19037 o->write_characters(indent_string.c_str(), current_indent);
19038 o->write_character(']');
19039 }
19040 else
19041 {
19042 o->write_character('[');
19043
19044 // first n-1 elements
19045 for (auto i = val.m_data.m_value.array->cbegin();
19046 i != val.m_data.m_value.array->cend() - 1; ++i)
19047 {
19048 dump(*i, false, ensure_ascii, indent_step, current_indent);
19049 o->write_character(',');
19050 }
19051
19052 // last element
19053 JSON_ASSERT(!val.m_data.m_value.array->empty());
19054 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
19055
19056 o->write_character(']');
19057 }
19058
19059 return;
19060 }
19061
19062 case value_t::string:
19063 {
19064 o->write_character('\"');
19065 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
19066 o->write_character('\"');
19067 return;
19068 }
19069
19070 case value_t::binary:
19071 {
19072 if (pretty_print)
19073 {
19074 o->write_characters("{\n", 2);
19075
19076 // variable to hold indentation for recursive calls
19077 const auto new_indent = current_indent + indent_step;
19078 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
19079 {
19080 indent_string.resize(indent_string.size() * 2, ' ');
19081 }
19082
19083 o->write_characters(indent_string.c_str(), new_indent);
19084
19085 o->write_characters("\"bytes\": [", 10);
19086
19087 if (!val.m_data.m_value.binary->empty())
19088 {
19089 for (auto i = val.m_data.m_value.binary->cbegin();
19090 i != val.m_data.m_value.binary->cend() - 1; ++i)
19091 {
19092 dump_integer(*i);
19093 o->write_characters(", ", 2);
19094 }
19095 dump_integer(val.m_data.m_value.binary->back());
19096 }
19097
19098 o->write_characters("],\n", 3);
19099 o->write_characters(indent_string.c_str(), new_indent);
19100
19101 o->write_characters("\"subtype\": ", 11);
19102 if (val.m_data.m_value.binary->has_subtype())
19103 {
19104 dump_integer(val.m_data.m_value.binary->subtype());
19105 }
19106 else
19107 {
19108 o->write_characters("null", 4);
19109 }
19110 o->write_character('\n');
19111 o->write_characters(indent_string.c_str(), current_indent);
19112 o->write_character('}');
19113 }
19114 else
19115 {
19116 o->write_characters("{\"bytes\":[", 10);
19117
19118 if (!val.m_data.m_value.binary->empty())
19119 {
19120 for (auto i = val.m_data.m_value.binary->cbegin();
19121 i != val.m_data.m_value.binary->cend() - 1; ++i)
19122 {
19123 dump_integer(*i);
19124 o->write_character(',');
19125 }
19126 dump_integer(val.m_data.m_value.binary->back());
19127 }
19128
19129 o->write_characters("],\"subtype\":", 12);
19130 if (val.m_data.m_value.binary->has_subtype())
19131 {
19132 dump_integer(val.m_data.m_value.binary->subtype());
19133 o->write_character('}');
19134 }
19135 else
19136 {
19137 o->write_characters("null}", 5);
19138 }
19139 }
19140 return;
19141 }
19142
19143 case value_t::boolean:
19144 {
19145 if (val.m_data.m_value.boolean)
19146 {
19147 o->write_characters("true", 4);
19148 }
19149 else
19150 {
19151 o->write_characters("false", 5);
19152 }
19153 return;
19154 }
19155
19156 case value_t::number_integer:
19157 {
19158 dump_integer(val.m_data.m_value.number_integer);
19159 return;
19160 }
19161
19162 case value_t::number_unsigned:
19163 {
19164 dump_integer(val.m_data.m_value.number_unsigned);
19165 return;
19166 }
19167
19168 case value_t::number_float:
19169 {
19170 dump_float(val.m_data.m_value.number_float);
19171 return;
19172 }
19173
19174 case value_t::discarded:
19175 {
19176 o->write_characters("<discarded>", 11);
19177 return;
19178 }
19179
19180 case value_t::null:
19181 {
19182 o->write_characters("null", 4);
19183 return;
19184 }
19185
19186 default: // LCOV_EXCL_LINE
19187 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19188 }
19189 }
19190
19191 JSON_PRIVATE_UNLESS_TESTED:
19206 void dump_escaped(const string_t& s, const bool ensure_ascii)
19207 {
19208 std::uint32_t codepoint{};
19209 std::uint8_t state = UTF8_ACCEPT;
19210 std::size_t bytes = 0; // number of bytes written to string_buffer
19211
19212 // number of bytes written at the point of the last valid byte
19213 std::size_t bytes_after_last_accept = 0;
19214 std::size_t undumped_chars = 0;
19215
19216 for (std::size_t i = 0; i < s.size(); ++i)
19217 {
19218 const auto byte = static_cast<std::uint8_t>(s[i]);
19219
19220 switch (decode(state, codepoint, byte))
19221 {
19222 case UTF8_ACCEPT: // decode found a new code point
19223 {
19224 switch (codepoint)
19225 {
19226 case 0x08: // backspace
19227 {
19228 string_buffer[bytes++] = '\\';
19229 string_buffer[bytes++] = 'b';
19230 break;
19231 }
19232
19233 case 0x09: // horizontal tab
19234 {
19235 string_buffer[bytes++] = '\\';
19236 string_buffer[bytes++] = 't';
19237 break;
19238 }
19239
19240 case 0x0A: // newline
19241 {
19242 string_buffer[bytes++] = '\\';
19243 string_buffer[bytes++] = 'n';
19244 break;
19245 }
19246
19247 case 0x0C: // formfeed
19248 {
19249 string_buffer[bytes++] = '\\';
19250 string_buffer[bytes++] = 'f';
19251 break;
19252 }
19253
19254 case 0x0D: // carriage return
19255 {
19256 string_buffer[bytes++] = '\\';
19257 string_buffer[bytes++] = 'r';
19258 break;
19259 }
19260
19261 case 0x22: // quotation mark
19262 {
19263 string_buffer[bytes++] = '\\';
19264 string_buffer[bytes++] = '\"';
19265 break;
19266 }
19267
19268 case 0x5C: // reverse solidus
19269 {
19270 string_buffer[bytes++] = '\\';
19271 string_buffer[bytes++] = '\\';
19272 break;
19273 }
19274
19275 default:
19276 {
19277 // escape control characters (0x00..0x1F) or, if
19278 // ensure_ascii parameter is used, non-ASCII characters
19279 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
19280 {
19281 if (codepoint <= 0xFFFF)
19282 {
19283 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19284 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
19285 static_cast<std::uint16_t>(codepoint)));
19286 bytes += 6;
19287 }
19288 else
19289 {
19290 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19291 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
19292 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
19293 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
19294 bytes += 12;
19295 }
19296 }
19297 else
19298 {
19299 // copy byte to buffer (all previous bytes
19300 // been copied have in default case above)
19301 string_buffer[bytes++] = s[i];
19302 }
19303 break;
19304 }
19305 }
19306
19307 // write buffer and reset index; there must be 13 bytes
19308 // left, as this is the maximal number of bytes to be
19309 // written ("\uxxxx\uxxxx\0") for one code point
19310 if (string_buffer.size() - bytes < 13)
19311 {
19312 o->write_characters(string_buffer.data(), bytes);
19313 bytes = 0;
19314 }
19315
19316 // remember the byte position of this accept
19317 bytes_after_last_accept = bytes;
19318 undumped_chars = 0;
19319 break;
19320 }
19321
19322 case UTF8_REJECT: // decode found invalid UTF-8 byte
19323 {
19324 switch (error_handler)
19325 {
19326 case error_handler_t::strict:
19327 {
19328 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
19329 }
19330
19331 case error_handler_t::ignore:
19332 case error_handler_t::replace:
19333 {
19334 // in case we saw this character the first time, we
19335 // would like to read it again, because the byte
19336 // may be OK for itself, but just not OK for the
19337 // previous sequence
19338 if (undumped_chars > 0)
19339 {
19340 --i;
19341 }
19342
19343 // reset length buffer to the last accepted index;
19344 // thus removing/ignoring the invalid characters
19345 bytes = bytes_after_last_accept;
19346
19347 if (error_handler == error_handler_t::replace)
19348 {
19349 // add a replacement character
19350 if (ensure_ascii)
19351 {
19352 string_buffer[bytes++] = '\\';
19353 string_buffer[bytes++] = 'u';
19354 string_buffer[bytes++] = 'f';
19355 string_buffer[bytes++] = 'f';
19356 string_buffer[bytes++] = 'f';
19357 string_buffer[bytes++] = 'd';
19358 }
19359 else
19360 {
19361 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
19362 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
19363 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
19364 }
19365
19366 // write buffer and reset index; there must be 13 bytes
19367 // left, as this is the maximal number of bytes to be
19368 // written ("\uxxxx\uxxxx\0") for one code point
19369 if (string_buffer.size() - bytes < 13)
19370 {
19371 o->write_characters(string_buffer.data(), bytes);
19372 bytes = 0;
19373 }
19374
19375 bytes_after_last_accept = bytes;
19376 }
19377
19378 undumped_chars = 0;
19379
19380 // continue processing the string
19381 state = UTF8_ACCEPT;
19382 break;
19383 }
19384
19385 default: // LCOV_EXCL_LINE
19386 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19387 }
19388 break;
19389 }
19390
19391 default: // decode found yet incomplete multibyte code point
19392 {
19393 if (!ensure_ascii)
19394 {
19395 // code point will not be escaped - copy byte to buffer
19396 string_buffer[bytes++] = s[i];
19397 }
19398 ++undumped_chars;
19399 break;
19400 }
19401 }
19402 }
19403
19404 // we finished processing the string
19405 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
19406 {
19407 // write buffer
19408 if (bytes > 0)
19409 {
19410 o->write_characters(string_buffer.data(), bytes);
19411 }
19412 }
19413 else
19414 {
19415 // we finish reading, but do not accept: string was incomplete
19416 switch (error_handler)
19417 {
19418 case error_handler_t::strict:
19419 {
19420 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));
19421 }
19422
19423 case error_handler_t::ignore:
19424 {
19425 // write all accepted bytes
19426 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19427 break;
19428 }
19429
19430 case error_handler_t::replace:
19431 {
19432 // write all accepted bytes
19433 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19434 // add a replacement character
19435 if (ensure_ascii)
19436 {
19437 o->write_characters("\\ufffd", 6);
19438 }
19439 else
19440 {
19441 o->write_characters("\xEF\xBF\xBD", 3);
19442 }
19443 break;
19444 }
19445
19446 default: // LCOV_EXCL_LINE
19447 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19448 }
19449 }
19450 }
19451
19452 private:
19461 unsigned int count_digits(number_unsigned_t x) noexcept
19462 {
19463 unsigned int n_digits = 1;
19464 for (;;)
19465 {
19466 if (x < 10)
19467 {
19468 return n_digits;
19469 }
19470 if (x < 100)
19471 {
19472 return n_digits + 1;
19473 }
19474 if (x < 1000)
19475 {
19476 return n_digits + 2;
19477 }
19478 if (x < 10000)
19479 {
19480 return n_digits + 3;
19481 }
19482 x = x / 10000u;
19483 n_digits += 4;
19484 }
19485 }
19486
19492 static std::string hex_bytes(std::uint8_t byte)
19493 {
19494 std::string result = "FF";
19495 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
19496 result[0] = nibble_to_hex[byte / 16];
19497 result[1] = nibble_to_hex[byte % 16];
19498 return result;
19499 }
19500
19501 // templates to avoid warnings about useless casts
19502 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
19503 bool is_negative_number(NumberType x)
19504 {
19505 return x < 0;
19506 }
19507
19508 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
19509 bool is_negative_number(NumberType /*unused*/)
19510 {
19511 return false;
19512 }
19513
19523 template < typename NumberType, detail::enable_if_t <
19524 std::is_integral<NumberType>::value ||
19525 std::is_same<NumberType, number_unsigned_t>::value ||
19526 std::is_same<NumberType, number_integer_t>::value ||
19527 std::is_same<NumberType, binary_char_t>::value,
19528 int > = 0 >
19529 void dump_integer(NumberType x)
19530 {
19531 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
19532 {
19533 {
19534 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
19535 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
19536 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
19537 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
19538 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
19539 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
19540 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
19541 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
19542 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
19543 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
19544 }
19545 };
19546
19547 // special case for "0"
19548 if (x == 0)
19549 {
19550 o->write_character('0');
19551 return;
19552 }
19553
19554 // use a pointer to fill the buffer
19555 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19556
19557 number_unsigned_t abs_value;
19558
19559 unsigned int n_chars{};
19560
19561 if (is_negative_number(x))
19562 {
19563 *buffer_ptr = '-';
19564 abs_value = remove_sign(static_cast<number_integer_t>(x));
19565
19566 // account one more byte for the minus sign
19567 n_chars = 1 + count_digits(abs_value);
19568 }
19569 else
19570 {
19571 abs_value = static_cast<number_unsigned_t>(x);
19572 n_chars = count_digits(abs_value);
19573 }
19574
19575 // spare 1 byte for '\0'
19576 JSON_ASSERT(n_chars < number_buffer.size() - 1);
19577
19578 // jump to the end to generate the string from backward,
19579 // so we later avoid reversing the result
19580 buffer_ptr += static_cast<typename decltype(number_buffer)::difference_type>(n_chars);
19581
19582 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
19583 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
19584 while (abs_value >= 100)
19585 {
19586 const auto digits_index = static_cast<unsigned>((abs_value % 100));
19587 abs_value /= 100;
19588 *(--buffer_ptr) = digits_to_99[digits_index][1];
19589 *(--buffer_ptr) = digits_to_99[digits_index][0];
19590 }
19591
19592 if (abs_value >= 10)
19593 {
19594 const auto digits_index = static_cast<unsigned>(abs_value);
19595 *(--buffer_ptr) = digits_to_99[digits_index][1];
19596 *(--buffer_ptr) = digits_to_99[digits_index][0];
19597 }
19598 else
19599 {
19600 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
19601 }
19602
19603 o->write_characters(number_buffer.data(), n_chars);
19604 }
19605
19614 void dump_float(number_float_t x)
19615 {
19616 // NaN / inf
19617 if (!std::isfinite(x))
19618 {
19619 o->write_characters("null", 4);
19620 return;
19621 }
19622
19623 // If number_float_t is an IEEE-754 single or double precision number,
19624 // use the Grisu2 algorithm to produce short numbers which are
19625 // guaranteed to round-trip, using strtof and strtod, resp.
19626 //
19627 // NB: The test below works if <long double> == <double>.
19628 static constexpr bool is_ieee_single_or_double
19629 = (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) ||
19630 (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);
19631
19632 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
19633 }
19634
19635 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
19636 {
19637 auto* begin = number_buffer.data();
19638 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
19639
19640 o->write_characters(begin, static_cast<size_t>(end - begin));
19641 }
19642
19643 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
19644 {
19645 // get the number of digits for a float -> text -> float round-trip
19646 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
19647
19648 // the actual conversion
19649 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19650 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
19651
19652 // negative value indicates an error
19653 JSON_ASSERT(len > 0);
19654 // check if the buffer was large enough
19655 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
19656
19657 // erase thousands separators
19658 if (thousands_sep != '\0')
19659 {
19660 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
19661 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
19662 std::fill(end, number_buffer.end(), '\0');
19663 JSON_ASSERT((end - number_buffer.begin()) <= len);
19664 len = (end - number_buffer.begin());
19665 }
19666
19667 // convert decimal point to '.'
19668 if (decimal_point != '\0' && decimal_point != '.')
19669 {
19670 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
19671 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
19672 if (dec_pos != number_buffer.end())
19673 {
19674 *dec_pos = '.';
19675 }
19676 }
19677
19678 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
19679
19680 // determine if we need to append ".0"
19681 const bool value_is_int_like =
19682 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
19683 [](char c)
19684 {
19685 return c == '.' || c == 'e';
19686 });
19687
19688 if (value_is_int_like)
19689 {
19690 o->write_characters(".0", 2);
19691 }
19692 }
19693
19715 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
19716 {
19717 static const std::array<std::uint8_t, 400> utf8d =
19718 {
19719 {
19720 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
19721 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
19722 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
19723 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
19724 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
19725 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
19726 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
19727 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
19728 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
19729 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
19730 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
19731 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
19732 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
19733 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
19734 }
19735 };
19736
19737 JSON_ASSERT(byte < utf8d.size());
19738 const std::uint8_t type = utf8d[byte];
19739
19740 codep = (state != UTF8_ACCEPT)
19741 ? (byte & 0x3fu) | (codep << 6u)
19742 : (0xFFu >> type) & (byte);
19743
19744 const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
19745 JSON_ASSERT(index < utf8d.size());
19746 state = utf8d[index];
19747 return state;
19748 }
19749
19750 /*
19751 * Overload to make the compiler happy while it is instantiating
19752 * dump_integer for number_unsigned_t.
19753 * Must never be called.
19754 */
19755 number_unsigned_t remove_sign(number_unsigned_t x)
19756 {
19757 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19758 return x; // LCOV_EXCL_LINE
19759 }
19760
19761 /*
19762 * Helper function for dump_integer
19763 *
19764 * This function takes a negative signed integer and returns its absolute
19765 * value as an unsigned integer. The plus/minus shuffling is necessary as we
19766 * cannot directly remove the sign of an arbitrary signed integer as the
19767 * absolute values of INT_MIN and INT_MAX are usually not the same. See
19768 * #1708 for details.
19769 */
19770 number_unsigned_t remove_sign(number_integer_t x) noexcept
19771 {
19772 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
19773 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
19774 }
19775
19776 private:
19778 output_adapter_t<char> o = nullptr;
19779
19781 std::array<char, 64> number_buffer{{}};
19782
19784 const std::lconv* loc = nullptr;
19786 const char thousands_sep = '\0';
19788 const char decimal_point = '\0';
19789
19791 std::array<char, 512> string_buffer{{}};
19792
19794 const char indent_char;
19797
19800};
19801
19802} // namespace detail
19803NLOHMANN_JSON_NAMESPACE_END
19804
19805// #include <nlohmann/detail/value_t.hpp>
19806
19807// #include <nlohmann/json_fwd.hpp>
19808
19809// #include <nlohmann/ordered_map.hpp>
19810// __ _____ _____ _____
19811// __| | __| | | | JSON for Modern C++
19812// | | |__ | | | | | | version 3.12.0
19813// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19814//
19815// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
19816// SPDX-License-Identifier: MIT
19817
19818
19819
19820#include <functional> // equal_to, less
19821#include <initializer_list> // initializer_list
19822#include <iterator> // input_iterator_tag, iterator_traits
19823#include <memory> // allocator
19824#include <stdexcept> // for out_of_range
19825#include <type_traits> // enable_if, is_convertible
19826#include <utility> // pair
19827#include <vector> // vector
19828
19829// #include <nlohmann/detail/macro_scope.hpp>
19830
19831// #include <nlohmann/detail/meta/type_traits.hpp>
19832
19833
19834NLOHMANN_JSON_NAMESPACE_BEGIN
19835
19838template <class Key, class T, class IgnoredLess = std::less<Key>,
19839 class Allocator = std::allocator<std::pair<const Key, T>>>
19840 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19841{
19842 using key_type = Key;
19843 using mapped_type = T;
19844 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19845 using iterator = typename Container::iterator;
19846 using const_iterator = typename Container::const_iterator;
19847 using size_type = typename Container::size_type;
19848 using value_type = typename Container::value_type;
19849#ifdef JSON_HAS_CPP_14
19850 using key_compare = std::equal_to<>;
19851#else
19852 using key_compare = std::equal_to<Key>;
19853#endif
19854
19855 // Explicit constructors instead of `using Container::Container`
19856 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19857 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19858 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19859 template <class It>
19860 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19861 : Container{first, last, alloc} {}
19862 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19863 : Container{init, alloc} {}
19864
19865 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19866 {
19867 for (auto it = this->begin(); it != this->end(); ++it)
19868 {
19869 if (m_compare(it->first, key))
19870 {
19871 return {it, false};
19872 }
19873 }
19874 Container::emplace_back(key, std::forward<T>(t));
19875 return {std::prev(this->end()), true};
19876 }
19877
19878 template<class KeyType, detail::enable_if_t<
19879 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19880 std::pair<iterator, bool> emplace(KeyType && key, T && t)
19881 {
19882 for (auto it = this->begin(); it != this->end(); ++it)
19883 {
19884 if (m_compare(it->first, key))
19885 {
19886 return {it, false};
19887 }
19888 }
19889 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19890 return {std::prev(this->end()), true};
19891 }
19892
19893 T& operator[](const key_type& key)
19894 {
19895 return emplace(key, T{}).first->second;
19896 }
19897
19898 template<class KeyType, detail::enable_if_t<
19899 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19900 T & operator[](KeyType && key)
19901 {
19902 return emplace(std::forward<KeyType>(key), T{}).first->second;
19903 }
19904
19905 const T& operator[](const key_type& key) const
19906 {
19907 return at(key);
19908 }
19909
19910 template<class KeyType, detail::enable_if_t<
19911 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19912 const T & operator[](KeyType && key) const
19913 {
19914 return at(std::forward<KeyType>(key));
19915 }
19916
19917 T& at(const key_type& key)
19918 {
19919 for (auto it = this->begin(); it != this->end(); ++it)
19920 {
19921 if (m_compare(it->first, key))
19922 {
19923 return it->second;
19924 }
19925 }
19926
19927 JSON_THROW(std::out_of_range("key not found"));
19928 }
19929
19930 template<class KeyType, detail::enable_if_t<
19931 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19932 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19933 {
19934 for (auto it = this->begin(); it != this->end(); ++it)
19935 {
19936 if (m_compare(it->first, key))
19937 {
19938 return it->second;
19939 }
19940 }
19941
19942 JSON_THROW(std::out_of_range("key not found"));
19943 }
19944
19945 const T& at(const key_type& key) const
19946 {
19947 for (auto it = this->begin(); it != this->end(); ++it)
19948 {
19949 if (m_compare(it->first, key))
19950 {
19951 return it->second;
19952 }
19953 }
19954
19955 JSON_THROW(std::out_of_range("key not found"));
19956 }
19957
19958 template<class KeyType, detail::enable_if_t<
19959 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19960 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19961 {
19962 for (auto it = this->begin(); it != this->end(); ++it)
19963 {
19964 if (m_compare(it->first, key))
19965 {
19966 return it->second;
19967 }
19968 }
19969
19970 JSON_THROW(std::out_of_range("key not found"));
19971 }
19972
19973 size_type erase(const key_type& key)
19974 {
19975 for (auto it = this->begin(); it != this->end(); ++it)
19976 {
19977 if (m_compare(it->first, key))
19978 {
19979 // Since we cannot move const Keys, re-construct them in place
19980 for (auto next = it; ++next != this->end(); ++it)
19981 {
19982 it->~value_type(); // Destroy but keep allocation
19983 new (&*it) value_type{std::move(*next)};
19984 }
19985 Container::pop_back();
19986 return 1;
19987 }
19988 }
19989 return 0;
19990 }
19991
19992 template<class KeyType, detail::enable_if_t<
19993 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19994 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19995 {
19996 for (auto it = this->begin(); it != this->end(); ++it)
19997 {
19998 if (m_compare(it->first, key))
19999 {
20000 // Since we cannot move const Keys, re-construct them in place
20001 for (auto next = it; ++next != this->end(); ++it)
20002 {
20003 it->~value_type(); // Destroy but keep allocation
20004 new (&*it) value_type{std::move(*next)};
20005 }
20006 Container::pop_back();
20007 return 1;
20008 }
20009 }
20010 return 0;
20011 }
20012
20013 iterator erase(iterator pos)
20014 {
20015 return erase(pos, std::next(pos));
20016 }
20017
20018 iterator erase(iterator first, iterator last)
20019 {
20020 if (first == last)
20021 {
20022 return first;
20023 }
20024
20025 const auto elements_affected = std::distance(first, last);
20026 const auto offset = std::distance(Container::begin(), first);
20027
20028 // This is the start situation. We need to delete elements_affected
20029 // elements (3 in this example: e, f, g), and need to return an
20030 // iterator past the last deleted element (h in this example).
20031 // Note that offset is the distance from the start of the vector
20032 // to first. We will need this later.
20033
20034 // [ a, b, c, d, e, f, g, h, i, j ]
20035 // ^ ^
20036 // first last
20037
20038 // Since we cannot move const Keys, we re-construct them in place.
20039 // We start at first and re-construct (viz. copy) the elements from
20040 // the back of the vector. Example for the first iteration:
20041
20042 // ,--------.
20043 // v | destroy e and re-construct with h
20044 // [ a, b, c, d, e, f, g, h, i, j ]
20045 // ^ ^
20046 // it it + elements_affected
20047
20048 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
20049 {
20050 it->~value_type(); // destroy but keep allocation
20051 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
20052 }
20053
20054 // [ a, b, c, d, h, i, j, h, i, j ]
20055 // ^ ^
20056 // first last
20057
20058 // remove the unneeded elements at the end of the vector
20059 Container::resize(this->size() - static_cast<size_type>(elements_affected));
20060
20061 // [ a, b, c, d, h, i, j ]
20062 // ^ ^
20063 // first last
20064
20065 // first is now pointing past the last deleted element, but we cannot
20066 // use this iterator, because it may have been invalidated by the
20067 // resize call. Instead, we can return begin() + offset.
20068 return Container::begin() + offset;
20069 }
20070
20071 size_type count(const key_type& key) const
20072 {
20073 for (auto it = this->begin(); it != this->end(); ++it)
20074 {
20075 if (m_compare(it->first, key))
20076 {
20077 return 1;
20078 }
20079 }
20080 return 0;
20081 }
20082
20083 template<class KeyType, detail::enable_if_t<
20084 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
20085 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
20086 {
20087 for (auto it = this->begin(); it != this->end(); ++it)
20088 {
20089 if (m_compare(it->first, key))
20090 {
20091 return 1;
20092 }
20093 }
20094 return 0;
20095 }
20096
20097 iterator find(const key_type& key)
20098 {
20099 for (auto it = this->begin(); it != this->end(); ++it)
20100 {
20101 if (m_compare(it->first, key))
20102 {
20103 return it;
20104 }
20105 }
20106 return Container::end();
20107 }
20108
20109 template<class KeyType, detail::enable_if_t<
20110 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
20111 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
20112 {
20113 for (auto it = this->begin(); it != this->end(); ++it)
20114 {
20115 if (m_compare(it->first, key))
20116 {
20117 return it;
20118 }
20119 }
20120 return Container::end();
20121 }
20122
20123 const_iterator find(const key_type& key) const
20124 {
20125 for (auto it = this->begin(); it != this->end(); ++it)
20126 {
20127 if (m_compare(it->first, key))
20128 {
20129 return it;
20130 }
20131 }
20132 return Container::end();
20133 }
20134
20135 std::pair<iterator, bool> insert( value_type&& value )
20136 {
20137 return emplace(value.first, std::move(value.second));
20138 }
20139
20140 std::pair<iterator, bool> insert( const value_type& value )
20141 {
20142 for (auto it = this->begin(); it != this->end(); ++it)
20143 {
20144 if (m_compare(it->first, value.first))
20145 {
20146 return {it, false};
20147 }
20148 }
20149 Container::push_back(value);
20150 return {--this->end(), true};
20151 }
20152
20153 template<typename InputIt>
20154 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
20155 std::input_iterator_tag>::value>::type;
20156
20157 template<typename InputIt, typename = require_input_iter<InputIt>>
20158 void insert(InputIt first, InputIt last)
20159 {
20160 for (auto it = first; it != last; ++it)
20161 {
20162 insert(*it);
20163 }
20164 }
20165
20166private:
20167 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
20168};
20169
20170NLOHMANN_JSON_NAMESPACE_END
20171
20172
20173#if defined(JSON_HAS_CPP_17)
20174 #if JSON_HAS_STATIC_RTTI
20175 #include <any>
20176 #endif
20177 #include <string_view>
20178#endif
20179
20185NLOHMANN_JSON_NAMESPACE_BEGIN
20186
20205NLOHMANN_BASIC_JSON_TPL_DECLARATION
20206class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
20207 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
20208{
20209 private:
20210 template<detail::value_t> friend struct detail::external_constructor;
20211
20212 template<typename>
20213 friend class ::nlohmann::json_pointer;
20214 // can be restored when json_pointer backwards compatibility is removed
20215 // friend ::nlohmann::json_pointer<StringType>;
20216
20217 template<typename BasicJsonType, typename InputType>
20218 friend class ::nlohmann::detail::parser;
20219 friend ::nlohmann::detail::serializer<basic_json>;
20220 template<typename BasicJsonType>
20221 friend class ::nlohmann::detail::iter_impl;
20222 template<typename BasicJsonType, typename CharType>
20223 friend class ::nlohmann::detail::binary_writer;
20224 template<typename BasicJsonType, typename InputType, typename SAX>
20225 friend class ::nlohmann::detail::binary_reader;
20226 template<typename BasicJsonType, typename InputAdapterType>
20227 friend class ::nlohmann::detail::json_sax_dom_parser;
20228 template<typename BasicJsonType, typename InputAdapterType>
20229 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
20230 friend class ::nlohmann::detail::exception;
20231
20233 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
20234 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
20235
20236 JSON_PRIVATE_UNLESS_TESTED:
20237 // convenience aliases for types residing in namespace detail;
20238 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
20239
20240 template<typename InputAdapterType>
20241 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
20242 InputAdapterType adapter,
20243 detail::parser_callback_t<basic_json>cb = nullptr,
20244 const bool allow_exceptions = true,
20245 const bool ignore_comments = false,
20246 const bool ignore_trailing_commas = false
20247 )
20248 {
20249 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
20250 std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
20251 }
20252
20253 private:
20254 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
20255 template<typename BasicJsonType>
20256 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
20257 template<typename BasicJsonType>
20258 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
20259 template<typename Iterator>
20260 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
20261 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
20262
20263 template<typename CharType>
20264 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
20265
20266 template<typename InputType>
20267 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
20268 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
20269
20270 JSON_PRIVATE_UNLESS_TESTED:
20271 using serializer = ::nlohmann::detail::serializer<basic_json>;
20272
20273 public:
20274 using value_t = detail::value_t;
20276 using json_pointer = ::nlohmann::json_pointer<StringType>;
20277 template<typename T, typename SFINAE>
20278 using json_serializer = JSONSerializer<T, SFINAE>;
20284 using bjdata_version_t = detail::bjdata_version_t;
20286 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
20287
20288 using input_format_t = detail::input_format_t;
20291
20293 // exceptions //
20295
20299
20306
20308
20310 // container types //
20312
20317
20320
20325
20327 using difference_type = std::ptrdiff_t;
20329 using size_type = std::size_t;
20330
20332 using allocator_type = AllocatorType<basic_json>;
20333
20335 using pointer = typename std::allocator_traits<allocator_type>::pointer;
20337 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
20338
20340 using iterator = iter_impl<basic_json>;
20342 using const_iterator = iter_impl<const basic_json>;
20344 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
20346 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
20347
20349
20353 {
20354 return allocator_type();
20355 }
20356
20359 JSON_HEDLEY_WARN_UNUSED_RESULT
20361 {
20362 basic_json result;
20363
20364 result["copyright"] = "(C) 2013-2025 Niels Lohmann";
20365 result["name"] = "JSON for Modern C++";
20366 result["url"] = "https://github.com/nlohmann/json";
20367 result["version"]["string"] =
20368 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
20369 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
20370 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
20371 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
20372 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
20373 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
20374
20375#ifdef _WIN32
20376 result["platform"] = "win32";
20377#elif defined __linux__
20378 result["platform"] = "linux";
20379#elif defined __APPLE__
20380 result["platform"] = "apple";
20381#elif defined __unix__
20382 result["platform"] = "unix";
20383#else
20384 result["platform"] = "unknown";
20385#endif
20386
20387#if defined(__ICC) || defined(__INTEL_COMPILER)
20388 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
20389#elif defined(__clang__)
20390 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
20391#elif defined(__GNUC__) || defined(__GNUG__)
20392 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
20393 std::to_string(__GNUC__), '.',
20394 std::to_string(__GNUC_MINOR__), '.',
20395 std::to_string(__GNUC_PATCHLEVEL__))
20396 }
20397 };
20398#elif defined(__HP_cc) || defined(__HP_aCC)
20399 result["compiler"] = "hp"
20400#elif defined(__IBMCPP__)
20401 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
20402#elif defined(_MSC_VER)
20403 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
20404#elif defined(__PGI)
20405 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
20406#elif defined(__SUNPRO_CC)
20407 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
20408#else
20409 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
20410#endif
20411
20412#if defined(_MSVC_LANG)
20413 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
20414#elif defined(__cplusplus)
20415 result["compiler"]["c++"] = std::to_string(__cplusplus);
20416#else
20417 result["compiler"]["c++"] = "unknown";
20418#endif
20419 return result;
20420 }
20421
20423 // JSON value data types //
20425
20430
20435#if defined(JSON_HAS_CPP_14)
20436 // use of transparent comparator avoids unnecessary repeated construction of temporaries
20437 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
20438 using default_object_comparator_t = std::less<>;
20439#else
20440 using default_object_comparator_t = std::less<StringType>;
20441#endif
20442
20445 using object_t = ObjectType<StringType,
20446 basic_json,
20448 AllocatorType<std::pair<const StringType,
20449 basic_json>>>;
20450
20453 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
20454
20457 using string_t = StringType;
20458
20461 using boolean_t = BooleanType;
20462
20465 using number_integer_t = NumberIntegerType;
20466
20469 using number_unsigned_t = NumberUnsignedType;
20470
20473 using number_float_t = NumberFloatType;
20474
20477 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
20478
20481 using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
20482
20484
20485 private:
20486
20488 template<typename T, typename... Args>
20489 JSON_HEDLEY_RETURNS_NON_NULL
20490 static T* create(Args&& ... args)
20491 {
20492 AllocatorType<T> alloc;
20493 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
20494
20495 auto deleter = [&](T * obj)
20496 {
20497 AllocatorTraits::deallocate(alloc, obj, 1);
20498 };
20499 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
20500 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
20501 JSON_ASSERT(obj != nullptr);
20502 return obj.release();
20503 }
20504
20506 // JSON value storage //
20508
20509 JSON_PRIVATE_UNLESS_TESTED:
20535 union json_value
20536 {
20538 object_t* object;
20540 array_t* array;
20542 string_t* string;
20544 binary_t* binary;
20546 boolean_t boolean;
20548 number_integer_t number_integer;
20550 number_unsigned_t number_unsigned;
20552 number_float_t number_float;
20553
20555 json_value() = default;
20557 json_value(boolean_t v) noexcept : boolean(v) {}
20559 json_value(number_integer_t v) noexcept : number_integer(v) {}
20561 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
20563 json_value(number_float_t v) noexcept : number_float(v) {}
20565 json_value(value_t t)
20566 {
20567 switch (t)
20568 {
20569 case value_t::object:
20570 {
20571 object = create<object_t>();
20572 break;
20573 }
20574
20575 case value_t::array:
20576 {
20577 array = create<array_t>();
20578 break;
20579 }
20580
20581 case value_t::string:
20582 {
20583 string = create<string_t>("");
20584 break;
20585 }
20586
20587 case value_t::binary:
20588 {
20589 binary = create<binary_t>();
20590 break;
20591 }
20592
20593 case value_t::boolean:
20594 {
20595 boolean = static_cast<boolean_t>(false);
20596 break;
20597 }
20598
20599 case value_t::number_integer:
20600 {
20601 number_integer = static_cast<number_integer_t>(0);
20602 break;
20603 }
20604
20605 case value_t::number_unsigned:
20606 {
20607 number_unsigned = static_cast<number_unsigned_t>(0);
20608 break;
20609 }
20610
20611 case value_t::number_float:
20612 {
20613 number_float = static_cast<number_float_t>(0.0);
20614 break;
20615 }
20616
20617 case value_t::null:
20618 {
20619 object = nullptr; // silence warning, see #821
20620 break;
20621 }
20622
20623 case value_t::discarded:
20624 default:
20625 {
20626 object = nullptr; // silence warning, see #821
20627 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
20628 {
20629 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.12.0", nullptr)); // LCOV_EXCL_LINE
20630 }
20631 break;
20632 }
20633 }
20634 }
20635
20637 json_value(const string_t& value) : string(create<string_t>(value)) {}
20638
20640 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
20641
20643 json_value(const object_t& value) : object(create<object_t>(value)) {}
20644
20646 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
20647
20649 json_value(const array_t& value) : array(create<array_t>(value)) {}
20650
20652 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
20653
20655 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
20656
20658 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
20659
20661 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
20662
20664 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
20665
20666 void destroy(value_t t)
20667 {
20668 if (
20669 (t == value_t::object && object == nullptr) ||
20670 (t == value_t::array && array == nullptr) ||
20671 (t == value_t::string && string == nullptr) ||
20672 (t == value_t::binary && binary == nullptr)
20673 )
20674 {
20675 // not initialized (e.g., due to exception in the ctor)
20676 return;
20677 }
20678 if (t == value_t::array || t == value_t::object)
20679 {
20680 // flatten the current json_value to a heap-allocated stack
20681 std::vector<basic_json> stack;
20682
20683 // move the top-level items to stack
20684 if (t == value_t::array)
20685 {
20686 stack.reserve(array->size());
20687 std::move(array->begin(), array->end(), std::back_inserter(stack));
20688 }
20689 else
20690 {
20691 stack.reserve(object->size());
20692 for (auto&& it : *object)
20693 {
20694 stack.push_back(std::move(it.second));
20695 }
20696 }
20697
20698 while (!stack.empty())
20699 {
20700 // move the last item to a local variable to be processed
20701 basic_json current_item(std::move(stack.back()));
20702 stack.pop_back();
20703
20704 // if current_item is array/object, move
20705 // its children to the stack to be processed later
20706 if (current_item.is_array())
20707 {
20708 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
20709
20710 current_item.m_data.m_value.array->clear();
20711 }
20712 else if (current_item.is_object())
20713 {
20714 for (auto&& it : *current_item.m_data.m_value.object)
20715 {
20716 stack.push_back(std::move(it.second));
20717 }
20718
20719 current_item.m_data.m_value.object->clear();
20720 }
20721
20722 // it's now safe that current_item gets destructed
20723 // since it doesn't have any children
20724 }
20725 }
20726
20727 switch (t)
20728 {
20729 case value_t::object:
20730 {
20731 AllocatorType<object_t> alloc;
20732 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
20733 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
20734 break;
20735 }
20736
20737 case value_t::array:
20738 {
20739 AllocatorType<array_t> alloc;
20740 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
20741 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
20742 break;
20743 }
20744
20745 case value_t::string:
20746 {
20747 AllocatorType<string_t> alloc;
20748 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
20749 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
20750 break;
20751 }
20752
20753 case value_t::binary:
20754 {
20755 AllocatorType<binary_t> alloc;
20756 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
20757 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
20758 break;
20759 }
20760
20761 case value_t::null:
20762 case value_t::boolean:
20763 case value_t::number_integer:
20764 case value_t::number_unsigned:
20765 case value_t::number_float:
20766 case value_t::discarded:
20767 default:
20768 {
20769 break;
20770 }
20771 }
20772 }
20773 };
20774
20775 private:
20794 void assert_invariant(bool check_parents = true) const noexcept
20795 {
20796 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20797 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20798 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20799 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20800
20801#if JSON_DIAGNOSTICS
20802 JSON_TRY
20803 {
20804 // cppcheck-suppress assertWithSideEffect
20805 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20806 {
20807 return j.m_parent == this;
20808 }));
20809 }
20810 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20811#endif
20812 static_cast<void>(check_parents);
20813 }
20814
20815 void set_parents()
20816 {
20817#if JSON_DIAGNOSTICS
20818 switch (m_data.m_type)
20819 {
20820 case value_t::array:
20821 {
20822 for (auto& element : *m_data.m_value.array)
20823 {
20824 element.m_parent = this;
20825 }
20826 break;
20827 }
20828
20829 case value_t::object:
20830 {
20831 for (auto& element : *m_data.m_value.object)
20832 {
20833 element.second.m_parent = this;
20834 }
20835 break;
20836 }
20837
20838 case value_t::null:
20839 case value_t::string:
20840 case value_t::boolean:
20841 case value_t::number_integer:
20842 case value_t::number_unsigned:
20843 case value_t::number_float:
20844 case value_t::binary:
20845 case value_t::discarded:
20846 default:
20847 break;
20848 }
20849#endif
20850 }
20851
20852 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20853 {
20854#if JSON_DIAGNOSTICS
20855 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20856 {
20857 (it + i)->m_parent = this;
20858 }
20859#else
20860 static_cast<void>(count_set_parents);
20861#endif
20862 return it;
20863 }
20864
20865 reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size())
20866 {
20867#if JSON_DIAGNOSTICS
20868 if (old_capacity != detail::unknown_size())
20869 {
20870 // see https://github.com/nlohmann/json/issues/2838
20871 JSON_ASSERT(type() == value_t::array);
20872 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20873 {
20874 // capacity has changed: update all parents
20875 set_parents();
20876 return j;
20877 }
20878 }
20879
20880 // ordered_json uses a vector internally, so pointers could have
20881 // been invalidated; see https://github.com/nlohmann/json/issues/2962
20882#ifdef JSON_HEDLEY_MSVC_VERSION
20883#pragma warning(push )
20884#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20885#endif
20887 {
20888 set_parents();
20889 return j;
20890 }
20891#ifdef JSON_HEDLEY_MSVC_VERSION
20892#pragma warning( pop )
20893#endif
20894
20895 j.m_parent = this;
20896#else
20897 static_cast<void>(j);
20898 static_cast<void>(old_capacity);
20899#endif
20900 return j;
20901 }
20902
20903 public:
20905 // JSON parser callback //
20907
20910 using parse_event_t = detail::parse_event_t;
20911
20914 using parser_callback_t = detail::parser_callback_t<basic_json>;
20915
20917 // constructors //
20919
20924
20928 : m_data(v)
20929 {
20930 assert_invariant();
20931 }
20932
20935 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20936 : basic_json(value_t::null)
20937 {
20938 assert_invariant();
20939 }
20940
20943 template < typename CompatibleType,
20944 typename U = detail::uncvref_t<CompatibleType>,
20945 detail::enable_if_t <
20947 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20948 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20949 std::forward<CompatibleType>(val))))
20950 {
20951 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20952 set_parents();
20953 assert_invariant();
20954 }
20955
20958 template < typename BasicJsonType,
20959 detail::enable_if_t <
20960 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20961 basic_json(const BasicJsonType& val)
20962#if JSON_DIAGNOSTIC_POSITIONS
20963 : start_position(val.start_pos()),
20964 end_position(val.end_pos())
20965#endif
20966 {
20967 using other_boolean_t = typename BasicJsonType::boolean_t;
20968 using other_number_float_t = typename BasicJsonType::number_float_t;
20969 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20970 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20971 using other_string_t = typename BasicJsonType::string_t;
20972 using other_object_t = typename BasicJsonType::object_t;
20973 using other_array_t = typename BasicJsonType::array_t;
20974 using other_binary_t = typename BasicJsonType::binary_t;
20975
20976 switch (val.type())
20977 {
20978 case value_t::boolean:
20979 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20980 break;
20981 case value_t::number_float:
20982 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20983 break;
20984 case value_t::number_integer:
20985 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20986 break;
20987 case value_t::number_unsigned:
20988 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20989 break;
20990 case value_t::string:
20991 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20992 break;
20993 case value_t::object:
20994 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20995 break;
20996 case value_t::array:
20997 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20998 break;
20999 case value_t::binary:
21000 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
21001 break;
21002 case value_t::null:
21003 *this = nullptr;
21004 break;
21005 case value_t::discarded:
21006 m_data.m_type = value_t::discarded;
21007 break;
21008 default: // LCOV_EXCL_LINE
21009 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
21010 }
21011 JSON_ASSERT(m_data.m_type == val.type());
21012
21013 set_parents();
21014 assert_invariant();
21015 }
21016
21020 bool type_deduction = true,
21021 value_t manual_type = value_t::array)
21022 {
21023 // check if each element is an array with two elements whose first
21024 // element is a string
21025 bool is_an_object = std::all_of(init.begin(), init.end(),
21026 [](const detail::json_ref<basic_json>& element_ref)
21027 {
21028 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
21029 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
21030 // broken call to op[key_type], the wrong semantics, and a 4804 warning on Windows)
21031 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
21032 });
21033
21034 // adjust type if type deduction is not wanted
21035 if (!type_deduction)
21036 {
21037 // if an array is wanted, do not create an object though possible
21038 if (manual_type == value_t::array)
21039 {
21040 is_an_object = false;
21041 }
21042
21043 // if an object is wanted but impossible, throw an exception
21044 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
21045 {
21046 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
21047 }
21048 }
21049
21050 if (is_an_object)
21051 {
21052 // the initializer list is a list of pairs -> create an object
21053 m_data.m_type = value_t::object;
21054 m_data.m_value = value_t::object;
21055
21056 for (auto& element_ref : init)
21057 {
21058 auto element = element_ref.moved_or_copied();
21059 m_data.m_value.object->emplace(
21060 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
21061 std::move((*element.m_data.m_value.array)[1]));
21062 }
21063 }
21064 else
21065 {
21066 // the initializer list describes an array -> create an array
21067 m_data.m_type = value_t::array;
21068 m_data.m_value.array = create<array_t>(init.begin(), init.end());
21069 }
21070
21071 set_parents();
21072 assert_invariant();
21073 }
21074
21077 JSON_HEDLEY_WARN_UNUSED_RESULT
21078 static basic_json binary(const typename binary_t::container_type& init)
21079 {
21080 auto res = basic_json();
21081 res.m_data.m_type = value_t::binary;
21082 res.m_data.m_value = init;
21083 return res;
21084 }
21085
21088 JSON_HEDLEY_WARN_UNUSED_RESULT
21089 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
21090 {
21091 auto res = basic_json();
21092 res.m_data.m_type = value_t::binary;
21093 res.m_data.m_value = binary_t(init, subtype);
21094 return res;
21095 }
21096
21099 JSON_HEDLEY_WARN_UNUSED_RESULT
21100 static basic_json binary(typename binary_t::container_type&& init)
21101 {
21102 auto res = basic_json();
21103 res.m_data.m_type = value_t::binary;
21104 res.m_data.m_value = std::move(init);
21105 return res;
21106 }
21107
21110 JSON_HEDLEY_WARN_UNUSED_RESULT
21111 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
21112 {
21113 auto res = basic_json();
21114 res.m_data.m_type = value_t::binary;
21115 res.m_data.m_value = binary_t(std::move(init), subtype);
21116 return res;
21117 }
21118
21121 JSON_HEDLEY_WARN_UNUSED_RESULT
21123 {
21124 return basic_json(init, false, value_t::array);
21125 }
21126
21129 JSON_HEDLEY_WARN_UNUSED_RESULT
21131 {
21132 return basic_json(init, false, value_t::object);
21133 }
21134
21138 m_data{cnt, val}
21139 {
21140 set_parents();
21141 assert_invariant();
21142 }
21143
21146 template < class InputIT, typename std::enable_if <
21147 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
21148 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
21149 basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
21150 {
21151 JSON_ASSERT(first.m_object != nullptr);
21152 JSON_ASSERT(last.m_object != nullptr);
21153
21154 // make sure the iterator fits the current value
21155 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
21156 {
21157 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
21158 }
21159
21160 // copy type from the first iterator
21161 m_data.m_type = first.m_object->m_data.m_type;
21162
21163 // check if the iterator range is complete for primitive values
21164 switch (m_data.m_type)
21165 {
21166 case value_t::boolean:
21167 case value_t::number_float:
21168 case value_t::number_integer:
21169 case value_t::number_unsigned:
21170 case value_t::string:
21171 {
21172 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
21173 || !last.m_it.primitive_iterator.is_end()))
21174 {
21175 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
21176 }
21177 break;
21178 }
21179
21180 case value_t::null:
21181 case value_t::object:
21182 case value_t::array:
21183 case value_t::binary:
21184 case value_t::discarded:
21185 default:
21186 break;
21187 }
21188
21189 switch (m_data.m_type)
21190 {
21191 case value_t::number_integer:
21192 {
21193 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
21194 break;
21195 }
21196
21197 case value_t::number_unsigned:
21198 {
21199 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
21200 break;
21201 }
21202
21203 case value_t::number_float:
21204 {
21205 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
21206 break;
21207 }
21208
21209 case value_t::boolean:
21210 {
21211 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
21212 break;
21213 }
21214
21215 case value_t::string:
21216 {
21217 m_data.m_value = *first.m_object->m_data.m_value.string;
21218 break;
21219 }
21220
21221 case value_t::object:
21222 {
21223 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
21224 last.m_it.object_iterator);
21225 break;
21226 }
21227
21228 case value_t::array:
21229 {
21230 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
21231 last.m_it.array_iterator);
21232 break;
21233 }
21234
21235 case value_t::binary:
21236 {
21237 m_data.m_value = *first.m_object->m_data.m_value.binary;
21238 break;
21239 }
21240
21241 case value_t::null:
21242 case value_t::discarded:
21243 default:
21244 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
21245 }
21246
21247 set_parents();
21248 assert_invariant();
21249 }
21250
21252 // other constructors and destructor //
21254
21255 template<typename JsonRef,
21256 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
21257 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
21258 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
21259
21263 : json_base_class_t(other)
21264#if JSON_DIAGNOSTIC_POSITIONS
21265 , start_position(other.start_position)
21266 , end_position(other.end_position)
21267#endif
21268 {
21269 m_data.m_type = other.m_data.m_type;
21270 // check of passed value is valid
21271 other.assert_invariant();
21272
21273 switch (m_data.m_type)
21274 {
21275 case value_t::object:
21276 {
21277 m_data.m_value = *other.m_data.m_value.object;
21278 break;
21279 }
21280
21281 case value_t::array:
21282 {
21283 m_data.m_value = *other.m_data.m_value.array;
21284 break;
21285 }
21286
21287 case value_t::string:
21288 {
21289 m_data.m_value = *other.m_data.m_value.string;
21290 break;
21291 }
21292
21293 case value_t::boolean:
21294 {
21295 m_data.m_value = other.m_data.m_value.boolean;
21296 break;
21297 }
21298
21299 case value_t::number_integer:
21300 {
21301 m_data.m_value = other.m_data.m_value.number_integer;
21302 break;
21303 }
21304
21305 case value_t::number_unsigned:
21306 {
21307 m_data.m_value = other.m_data.m_value.number_unsigned;
21308 break;
21309 }
21310
21311 case value_t::number_float:
21312 {
21313 m_data.m_value = other.m_data.m_value.number_float;
21314 break;
21315 }
21316
21317 case value_t::binary:
21318 {
21319 m_data.m_value = *other.m_data.m_value.binary;
21320 break;
21321 }
21322
21323 case value_t::null:
21324 case value_t::discarded:
21325 default:
21326 break;
21327 }
21328
21329 set_parents();
21330 assert_invariant();
21331 }
21332
21335 basic_json(basic_json&& other) noexcept
21336 : json_base_class_t(std::forward<json_base_class_t>(other)),
21337 m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
21338#if JSON_DIAGNOSTIC_POSITIONS
21339 , start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
21340 , end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
21341#endif
21342 {
21343 // check that the passed value is valid
21344 other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
21345
21346 // invalidate payload
21347 other.m_data.m_type = value_t::null;
21348 other.m_data.m_value = {};
21349
21350#if JSON_DIAGNOSTIC_POSITIONS
21351 other.start_position = std::string::npos;
21352 other.end_position = std::string::npos;
21353#endif
21354
21355 set_parents();
21356 assert_invariant();
21357 }
21358
21362 std::is_nothrow_move_constructible<value_t>::value&&
21363 std::is_nothrow_move_assignable<value_t>::value&&
21364 std::is_nothrow_move_constructible<json_value>::value&&
21365 std::is_nothrow_move_assignable<json_value>::value&&
21366 std::is_nothrow_move_assignable<json_base_class_t>::value
21367 )
21368 {
21369 // check that the passed value is valid
21370 other.assert_invariant();
21371
21372 using std::swap;
21373 swap(m_data.m_type, other.m_data.m_type);
21374 swap(m_data.m_value, other.m_data.m_value);
21375
21376#if JSON_DIAGNOSTIC_POSITIONS
21377 swap(start_position, other.start_position);
21378 swap(end_position, other.end_position);
21379#endif
21380
21381 json_base_class_t::operator=(std::move(other));
21382
21383 set_parents();
21384 assert_invariant();
21385 return *this;
21386 }
21387
21390 ~basic_json() noexcept
21391 {
21392 assert_invariant(false);
21393 }
21394
21396
21397 public:
21399 // object inspection //
21401
21405
21408 string_t dump(const int indent = -1,
21409 const char indent_char = ' ',
21410 const bool ensure_ascii = false,
21411 const error_handler_t error_handler = error_handler_t::strict) const
21412 {
21413 string_t result;
21414 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
21415
21416 if (indent >= 0)
21417 {
21418 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
21419 }
21420 else
21421 {
21422 s.dump(*this, false, ensure_ascii, 0);
21423 }
21424
21425 return result;
21426 }
21427
21430 constexpr value_t type() const noexcept
21431 {
21432 return m_data.m_type;
21433 }
21434
21437 constexpr bool is_primitive() const noexcept
21438 {
21439 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
21440 }
21441
21444 constexpr bool is_structured() const noexcept
21445 {
21446 return is_array() || is_object();
21447 }
21448
21451 constexpr bool is_null() const noexcept
21452 {
21453 return m_data.m_type == value_t::null;
21454 }
21455
21458 constexpr bool is_boolean() const noexcept
21459 {
21460 return m_data.m_type == value_t::boolean;
21461 }
21462
21465 constexpr bool is_number() const noexcept
21466 {
21467 return is_number_integer() || is_number_float();
21468 }
21469
21472 constexpr bool is_number_integer() const noexcept
21473 {
21474 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
21475 }
21476
21479 constexpr bool is_number_unsigned() const noexcept
21480 {
21481 return m_data.m_type == value_t::number_unsigned;
21482 }
21483
21486 constexpr bool is_number_float() const noexcept
21487 {
21488 return m_data.m_type == value_t::number_float;
21489 }
21490
21493 constexpr bool is_object() const noexcept
21494 {
21495 return m_data.m_type == value_t::object;
21496 }
21497
21500 constexpr bool is_array() const noexcept
21501 {
21502 return m_data.m_type == value_t::array;
21503 }
21504
21507 constexpr bool is_string() const noexcept
21508 {
21509 return m_data.m_type == value_t::string;
21510 }
21511
21514 constexpr bool is_binary() const noexcept
21515 {
21516 return m_data.m_type == value_t::binary;
21517 }
21518
21521 constexpr bool is_discarded() const noexcept
21522 {
21523 return m_data.m_type == value_t::discarded;
21524 }
21525
21528 constexpr operator value_t() const noexcept
21529 {
21530 return m_data.m_type;
21531 }
21532
21534
21535 private:
21537 // value access //
21539
21541 boolean_t get_impl(boolean_t* /*unused*/) const
21542 {
21543 if (JSON_HEDLEY_LIKELY(is_boolean()))
21544 {
21545 return m_data.m_value.boolean;
21546 }
21547
21548 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
21549 }
21550
21552 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
21553 {
21554 return is_object() ? m_data.m_value.object : nullptr;
21555 }
21556
21558 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
21559 {
21560 return is_object() ? m_data.m_value.object : nullptr;
21561 }
21562
21564 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
21565 {
21566 return is_array() ? m_data.m_value.array : nullptr;
21567 }
21568
21570 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
21571 {
21572 return is_array() ? m_data.m_value.array : nullptr;
21573 }
21574
21576 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
21577 {
21578 return is_string() ? m_data.m_value.string : nullptr;
21579 }
21580
21582 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
21583 {
21584 return is_string() ? m_data.m_value.string : nullptr;
21585 }
21586
21588 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
21589 {
21590 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21591 }
21592
21594 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
21595 {
21596 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21597 }
21598
21600 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
21601 {
21602 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21603 }
21604
21606 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
21607 {
21608 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21609 }
21610
21612 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
21613 {
21614 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21615 }
21616
21618 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
21619 {
21620 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21621 }
21622
21624 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
21625 {
21626 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21627 }
21628
21630 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
21631 {
21632 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21633 }
21634
21636 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
21637 {
21638 return is_binary() ? m_data.m_value.binary : nullptr;
21639 }
21640
21642 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
21643 {
21644 return is_binary() ? m_data.m_value.binary : nullptr;
21645 }
21646
21658 template<typename ReferenceType, typename ThisType>
21659 static ReferenceType get_ref_impl(ThisType& obj)
21660 {
21661 // delegate the call to get_ptr<>()
21662 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
21663
21664 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
21665 {
21666 return *ptr;
21667 }
21668
21669 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
21670 }
21671
21672 public:
21676
21679 template<typename PointerType, typename std::enable_if<
21680 std::is_pointer<PointerType>::value, int>::type = 0>
21681 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21682 {
21683 // delegate the call to get_impl_ptr<>()
21684 return get_impl_ptr(static_cast<PointerType>(nullptr));
21685 }
21686
21689 template < typename PointerType, typename std::enable_if <
21690 std::is_pointer<PointerType>::value&&
21691 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
21692 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21693 {
21694 // delegate the call to get_impl_ptr<>() const
21695 return get_impl_ptr(static_cast<PointerType>(nullptr));
21696 }
21697
21698 private:
21737 template < typename ValueType,
21738 detail::enable_if_t <
21741 int > = 0 >
21742 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
21743 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
21744 {
21745 auto ret = ValueType();
21746 JSONSerializer<ValueType>::from_json(*this, ret);
21747 return ret;
21748 }
21749
21780 template < typename ValueType,
21781 detail::enable_if_t <
21783 int > = 0 >
21784 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
21785 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
21786 {
21787 return JSONSerializer<ValueType>::from_json(*this);
21788 }
21789
21805 template < typename BasicJsonType,
21806 detail::enable_if_t <
21808 int > = 0 >
21809 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
21810 {
21811 return *this;
21812 }
21813
21828 template<typename BasicJsonType,
21829 detail::enable_if_t<
21830 std::is_same<BasicJsonType, basic_json_t>::value,
21831 int> = 0>
21832 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
21833 {
21834 return *this;
21835 }
21836
21841 template<typename PointerType,
21842 detail::enable_if_t<
21843 std::is_pointer<PointerType>::value,
21844 int> = 0>
21845 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21846 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21847 {
21848 // delegate the call to get_ptr
21849 return get_ptr<PointerType>();
21850 }
21851
21852 public:
21876 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21877#if defined(JSON_HAS_CPP_14)
21878 constexpr
21879#endif
21880 auto get() const noexcept(
21881 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21882 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21883 {
21884 // we cannot static_assert on ValueTypeCV being non-const, because
21885 // there is support for get<const basic_json_t>(), which is why we
21886 // still need the uncvref
21887 static_assert(!std::is_reference<ValueTypeCV>::value,
21888 "get() cannot be used with reference types, you might want to use get_ref()");
21889 return get_impl<ValueType>(detail::priority_tag<4> {});
21890 }
21891
21919 template<typename PointerType, typename std::enable_if<
21920 std::is_pointer<PointerType>::value, int>::type = 0>
21921 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21922 {
21923 // delegate the call to get_ptr
21924 return get_ptr<PointerType>();
21925 }
21926
21929 template < typename ValueType,
21930 detail::enable_if_t <
21933 int > = 0 >
21934 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21935 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21936 {
21937 JSONSerializer<ValueType>::from_json(*this, v);
21938 return v;
21939 }
21940
21941 // specialization to allow calling get_to with a basic_json value
21942 // see https://github.com/nlohmann/json/issues/2175
21943 template<typename ValueType,
21944 detail::enable_if_t <
21946 int> = 0>
21947 ValueType & get_to(ValueType& v) const
21948 {
21949 v = *this;
21950 return v;
21951 }
21952
21953 template <
21954 typename T, std::size_t N,
21955 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21956 detail::enable_if_t <
21958 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21959 noexcept(noexcept(JSONSerializer<Array>::from_json(
21960 std::declval<const basic_json_t&>(), v)))
21961 {
21962 JSONSerializer<Array>::from_json(*this, v);
21963 return v;
21964 }
21965
21968 template<typename ReferenceType, typename std::enable_if<
21969 std::is_reference<ReferenceType>::value, int>::type = 0>
21970 ReferenceType get_ref()
21971 {
21972 // delegate call to get_ref_impl
21973 return get_ref_impl<ReferenceType>(*this);
21974 }
21975
21978 template < typename ReferenceType, typename std::enable_if <
21979 std::is_reference<ReferenceType>::value&&
21980 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21981 ReferenceType get_ref() const
21982 {
21983 // delegate call to get_ref_impl
21984 return get_ref_impl<ReferenceType>(*this);
21985 }
21986
22016 template < typename ValueType, typename std::enable_if <
22024#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
22026#endif
22027#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
22029#endif
22031 >::value, int >::type = 0 >
22032 JSON_EXPLICIT operator ValueType() const
22033 {
22034 // delegate the call to get<>() const
22035 return get<ValueType>();
22036 }
22037
22041 {
22042 if (!is_binary())
22043 {
22044 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
22045 }
22046
22047 return *get_ptr<binary_t*>();
22048 }
22049
22052 const binary_t& get_binary() const
22053 {
22054 if (!is_binary())
22055 {
22056 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
22057 }
22058
22059 return *get_ptr<const binary_t*>();
22060 }
22061
22063
22065 // element access //
22067
22071
22075 {
22076 // at only works for arrays
22077 if (JSON_HEDLEY_LIKELY(is_array()))
22078 {
22079 JSON_TRY
22080 {
22081 return set_parent(m_data.m_value.array->at(idx));
22082 }
22083 JSON_CATCH (std::out_of_range&)
22084 {
22085 // create a better exception explanation
22086 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22087 } // cppcheck-suppress[missingReturn]
22088 }
22089 else
22090 {
22091 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22092 }
22093 }
22094
22098 {
22099 // at only works for arrays
22100 if (JSON_HEDLEY_LIKELY(is_array()))
22101 {
22102 JSON_TRY
22103 {
22104 return m_data.m_value.array->at(idx);
22105 }
22106 JSON_CATCH (std::out_of_range&)
22107 {
22108 // create a better exception explanation
22109 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22110 } // cppcheck-suppress[missingReturn]
22111 }
22112 else
22113 {
22114 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22115 }
22116 }
22117
22120 reference at(const typename object_t::key_type& key)
22121 {
22122 // at only works for objects
22123 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22124 {
22125 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22126 }
22127
22128 auto it = m_data.m_value.object->find(key);
22129 if (it == m_data.m_value.object->end())
22130 {
22131 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22132 }
22133 return set_parent(it->second);
22134 }
22135
22138 template<class KeyType, detail::enable_if_t<
22139 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22140 reference at(KeyType && key)
22141 {
22142 // at only works for objects
22143 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22144 {
22145 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22146 }
22147
22148 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22149 if (it == m_data.m_value.object->end())
22150 {
22151 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22152 }
22153 return set_parent(it->second);
22154 }
22155
22158 const_reference at(const typename object_t::key_type& key) const
22159 {
22160 // at only works for objects
22161 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22162 {
22163 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22164 }
22165
22166 auto it = m_data.m_value.object->find(key);
22167 if (it == m_data.m_value.object->end())
22168 {
22169 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22170 }
22171 return it->second;
22172 }
22173
22176 template<class KeyType, detail::enable_if_t<
22177 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22178 const_reference at(KeyType && key) const
22179 {
22180 // at only works for objects
22181 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22182 {
22183 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22184 }
22185
22186 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22187 if (it == m_data.m_value.object->end())
22188 {
22189 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22190 }
22191 return it->second;
22192 }
22193
22197 {
22198 // implicitly convert a null value to an empty array
22199 if (is_null())
22200 {
22201 m_data.m_type = value_t::array;
22202 m_data.m_value.array = create<array_t>();
22203 assert_invariant();
22204 }
22205
22206 // operator[] only works for arrays
22207 if (JSON_HEDLEY_LIKELY(is_array()))
22208 {
22209 // fill up the array with null values if given idx is outside the range
22210 if (idx >= m_data.m_value.array->size())
22211 {
22212#if JSON_DIAGNOSTICS
22213 // remember array size & capacity before resizing
22214 const auto old_size = m_data.m_value.array->size();
22215 const auto old_capacity = m_data.m_value.array->capacity();
22216#endif
22217 m_data.m_value.array->resize(idx + 1);
22218
22219#if JSON_DIAGNOSTICS
22220 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
22221 {
22222 // capacity has changed: update all parents
22223 set_parents();
22224 }
22225 else
22226 {
22227 // set parent for values added above
22228 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
22229 }
22230#endif
22231 assert_invariant();
22232 }
22233
22234 return m_data.m_value.array->operator[](idx);
22235 }
22236
22237 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22238 }
22239
22243 {
22244 // const operator[] only works for arrays
22245 if (JSON_HEDLEY_LIKELY(is_array()))
22246 {
22247 return m_data.m_value.array->operator[](idx);
22248 }
22249
22250 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22251 }
22252
22255 reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
22256 {
22257 // implicitly convert a null value to an empty object
22258 if (is_null())
22259 {
22260 m_data.m_type = value_t::object;
22261 m_data.m_value.object = create<object_t>();
22262 assert_invariant();
22263 }
22264
22265 // operator[] only works for objects
22266 if (JSON_HEDLEY_LIKELY(is_object()))
22267 {
22268 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
22269 return set_parent(result.first->second);
22270 }
22271
22272 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22273 }
22274
22277 const_reference operator[](const typename object_t::key_type& key) const
22278 {
22279 // const operator[] only works for objects
22280 if (JSON_HEDLEY_LIKELY(is_object()))
22281 {
22282 auto it = m_data.m_value.object->find(key);
22283 JSON_ASSERT(it != m_data.m_value.object->end());
22284 return it->second;
22285 }
22286
22287 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22288 }
22289
22290 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
22291 // (they seemingly cannot be constrained to resolve the ambiguity)
22292 template<typename T>
22293 reference operator[](T* key)
22294 {
22295 return operator[](typename object_t::key_type(key));
22296 }
22297
22298 template<typename T>
22299 const_reference operator[](T* key) const
22300 {
22301 return operator[](typename object_t::key_type(key));
22302 }
22303
22306 template<class KeyType, detail::enable_if_t<
22307 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
22308 reference operator[](KeyType && key)
22309 {
22310 // implicitly convert a null value to an empty object
22311 if (is_null())
22312 {
22313 m_data.m_type = value_t::object;
22314 m_data.m_value.object = create<object_t>();
22315 assert_invariant();
22316 }
22317
22318 // operator[] only works for objects
22319 if (JSON_HEDLEY_LIKELY(is_object()))
22320 {
22321 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
22322 return set_parent(result.first->second);
22323 }
22324
22325 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22326 }
22327
22330 template<class KeyType, detail::enable_if_t<
22331 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
22332 const_reference operator[](KeyType && key) const
22333 {
22334 // const operator[] only works for objects
22335 if (JSON_HEDLEY_LIKELY(is_object()))
22336 {
22337 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22338 JSON_ASSERT(it != m_data.m_value.object->end());
22339 return it->second;
22340 }
22341
22342 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22343 }
22344
22345 private:
22346 template<typename KeyType>
22347 using is_comparable_with_object_key = detail::is_comparable <
22348 object_comparator_t, const typename object_t::key_type&, KeyType >;
22349
22350 template<typename ValueType>
22351 using value_return_type = std::conditional <
22352 detail::is_c_string_uncvref<ValueType>::value,
22353 string_t, typename std::decay<ValueType>::type >;
22354
22355 public:
22358 template < class ValueType, detail::enable_if_t <
22361 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22362 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
22363 {
22364 // value only works for objects
22365 if (JSON_HEDLEY_LIKELY(is_object()))
22366 {
22367 // If 'key' is found, return its value. Otherwise, return `default_value'.
22368 const auto it = find(key);
22369 if (it != end())
22370 {
22371 return it->template get<ValueType>();
22372 }
22373
22374 return default_value;
22375 }
22376
22377 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22378 }
22379
22382 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22383 detail::enable_if_t <
22386 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22387 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
22388 {
22389 // value only works for objects
22390 if (JSON_HEDLEY_LIKELY(is_object()))
22391 {
22392 // If 'key' is found, return its value. Otherwise, return `default_value'.
22393 const auto it = find(key);
22394 if (it != end())
22395 {
22396 return it->template get<ReturnType>();
22397 }
22398
22399 return std::forward<ValueType>(default_value);
22400 }
22401
22402 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22403 }
22404
22407 template < class ValueType, class KeyType, detail::enable_if_t <
22409 && !detail::is_json_pointer<KeyType>::value
22410 && is_comparable_with_object_key<KeyType>::value
22412 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22413 ValueType value(KeyType && key, const ValueType& default_value) const
22414 {
22415 // value only works for objects
22416 if (JSON_HEDLEY_LIKELY(is_object()))
22417 {
22418 // If 'key' is found, return its value. Otherwise, return `default_value'.
22419 const auto it = find(std::forward<KeyType>(key));
22420 if (it != end())
22421 {
22422 return it->template get<ValueType>();
22423 }
22424
22425 return default_value;
22426 }
22427
22428 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22429 }
22430
22433 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
22434 detail::enable_if_t <
22436 && !detail::is_json_pointer<KeyType>::value
22437 && is_comparable_with_object_key<KeyType>::value
22439 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22440 ReturnType value(KeyType && key, ValueType && default_value) const
22441 {
22442 // value only works for objects
22443 if (JSON_HEDLEY_LIKELY(is_object()))
22444 {
22445 // If 'key' is found, return its value. Otherwise, return `default_value'.
22446 const auto it = find(std::forward<KeyType>(key));
22447 if (it != end())
22448 {
22449 return it->template get<ReturnType>();
22450 }
22451
22452 return std::forward<ValueType>(default_value);
22453 }
22454
22455 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22456 }
22457
22460 template < class ValueType, detail::enable_if_t <
22462 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22463 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
22464 {
22465 // value only works for objects
22466 if (JSON_HEDLEY_LIKELY(is_object()))
22467 {
22468 // If the pointer resolves to a value, return it. Otherwise, return
22469 // 'default_value'.
22470 JSON_TRY
22471 {
22472 return ptr.get_checked(this).template get<ValueType>();
22473 }
22474 JSON_INTERNAL_CATCH (out_of_range&)
22475 {
22476 return default_value;
22477 }
22478 }
22479
22480 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22481 }
22482
22485 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22486 detail::enable_if_t <
22488 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22489 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
22490 {
22491 // value only works for objects
22492 if (JSON_HEDLEY_LIKELY(is_object()))
22493 {
22494 // If the pointer resolves to a value, return it. Otherwise, return
22495 // 'default_value'.
22496 JSON_TRY
22497 {
22498 return ptr.get_checked(this).template get<ReturnType>();
22499 }
22500 JSON_INTERNAL_CATCH (out_of_range&)
22501 {
22502 return std::forward<ValueType>(default_value);
22503 }
22504 }
22505
22506 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22507 }
22508
22509 template < class ValueType, class BasicJsonType, detail::enable_if_t <
22512 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22513 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22514 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
22515 {
22516 return value(ptr.convert(), default_value);
22517 }
22518
22519 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
22520 detail::enable_if_t <
22523 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22524 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22525 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
22526 {
22527 return value(ptr.convert(), std::forward<ValueType>(default_value));
22528 }
22529
22533 {
22534 return *begin();
22535 }
22536
22540 {
22541 return *cbegin();
22542 }
22543
22547 {
22548 auto tmp = end();
22549 --tmp;
22550 return *tmp;
22551 }
22552
22556 {
22557 auto tmp = cend();
22558 --tmp;
22559 return *tmp;
22560 }
22561
22564 template < class IteratorType, detail::enable_if_t <
22565 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22566 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22567 IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
22568 {
22569 // make sure the iterator fits the current value
22570 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
22571 {
22572 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22573 }
22574
22575 IteratorType result = end();
22576
22577 switch (m_data.m_type)
22578 {
22579 case value_t::boolean:
22580 case value_t::number_float:
22581 case value_t::number_integer:
22582 case value_t::number_unsigned:
22583 case value_t::string:
22584 case value_t::binary:
22585 {
22586 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
22587 {
22588 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
22589 }
22590
22591 if (is_string())
22592 {
22593 AllocatorType<string_t> alloc;
22594 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22595 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22596 m_data.m_value.string = nullptr;
22597 }
22598 else if (is_binary())
22599 {
22600 AllocatorType<binary_t> alloc;
22601 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22602 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22603 m_data.m_value.binary = nullptr;
22604 }
22605
22606 m_data.m_type = value_t::null;
22607 assert_invariant();
22608 break;
22609 }
22610
22611 case value_t::object:
22612 {
22613 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
22614 break;
22615 }
22616
22617 case value_t::array:
22618 {
22619 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
22620 break;
22621 }
22622
22623 case value_t::null:
22624 case value_t::discarded:
22625 default:
22626 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22627 }
22628
22629 return result;
22630 }
22631
22634 template < class IteratorType, detail::enable_if_t <
22635 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22636 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22637 IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
22638 {
22639 // make sure the iterator fits the current value
22640 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
22641 {
22642 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
22643 }
22644
22645 IteratorType result = end();
22646
22647 switch (m_data.m_type)
22648 {
22649 case value_t::boolean:
22650 case value_t::number_float:
22651 case value_t::number_integer:
22652 case value_t::number_unsigned:
22653 case value_t::string:
22654 case value_t::binary:
22655 {
22656 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
22657 || !last.m_it.primitive_iterator.is_end()))
22658 {
22659 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
22660 }
22661
22662 if (is_string())
22663 {
22664 AllocatorType<string_t> alloc;
22665 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22666 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22667 m_data.m_value.string = nullptr;
22668 }
22669 else if (is_binary())
22670 {
22671 AllocatorType<binary_t> alloc;
22672 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22673 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22674 m_data.m_value.binary = nullptr;
22675 }
22676
22677 m_data.m_type = value_t::null;
22678 assert_invariant();
22679 break;
22680 }
22681
22682 case value_t::object:
22683 {
22684 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
22685 last.m_it.object_iterator);
22686 break;
22687 }
22688
22689 case value_t::array:
22690 {
22691 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
22692 last.m_it.array_iterator);
22693 break;
22694 }
22695
22696 case value_t::null:
22697 case value_t::discarded:
22698 default:
22699 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22700 }
22701
22702 return result;
22703 }
22704
22705 private:
22706 template < typename KeyType, detail::enable_if_t <
22707 detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
22708 size_type erase_internal(KeyType && key)
22709 {
22710 // this erase only works for objects
22711 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22712 {
22713 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22714 }
22715
22716 return m_data.m_value.object->erase(std::forward<KeyType>(key));
22717 }
22718
22719 template < typename KeyType, detail::enable_if_t <
22720 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
22721 size_type erase_internal(KeyType && key)
22722 {
22723 // this erase only works for objects
22724 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22725 {
22726 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22727 }
22728
22729 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22730 if (it != m_data.m_value.object->end())
22731 {
22732 m_data.m_value.object->erase(it);
22733 return 1;
22734 }
22735 return 0;
22736 }
22737
22738 public:
22739
22742 size_type erase(const typename object_t::key_type& key)
22743 {
22744 // the indirection via erase_internal() is added to avoid making this
22745 // function a template and thus de-rank it during overload resolution
22746 return erase_internal(key);
22747 }
22748
22751 template<class KeyType, detail::enable_if_t<
22752 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22753 size_type erase(KeyType && key)
22754 {
22755 return erase_internal(std::forward<KeyType>(key));
22756 }
22757
22760 void erase(const size_type idx)
22761 {
22762 // this erase only works for arrays
22763 if (JSON_HEDLEY_LIKELY(is_array()))
22764 {
22765 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
22766 {
22767 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22768 }
22769
22770 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
22771 }
22772 else
22773 {
22774 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22775 }
22776 }
22777
22779
22781 // lookup //
22783
22786
22789 iterator find(const typename object_t::key_type& key)
22790 {
22791 auto result = end();
22792
22793 if (is_object())
22794 {
22795 result.m_it.object_iterator = m_data.m_value.object->find(key);
22796 }
22797
22798 return result;
22799 }
22800
22803 const_iterator find(const typename object_t::key_type& key) const
22804 {
22805 auto result = cend();
22806
22807 if (is_object())
22808 {
22809 result.m_it.object_iterator = m_data.m_value.object->find(key);
22810 }
22811
22812 return result;
22813 }
22814
22817 template<class KeyType, detail::enable_if_t<
22818 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22819 iterator find(KeyType && key)
22820 {
22821 auto result = end();
22822
22823 if (is_object())
22824 {
22825 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22826 }
22827
22828 return result;
22829 }
22830
22833 template<class KeyType, detail::enable_if_t<
22834 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22835 const_iterator find(KeyType && key) const
22836 {
22837 auto result = cend();
22838
22839 if (is_object())
22840 {
22841 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22842 }
22843
22844 return result;
22845 }
22846
22849 size_type count(const typename object_t::key_type& key) const
22850 {
22851 // return 0 for all nonobject types
22852 return is_object() ? m_data.m_value.object->count(key) : 0;
22853 }
22854
22857 template<class KeyType, detail::enable_if_t<
22858 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22859 size_type count(KeyType && key) const
22860 {
22861 // return 0 for all nonobject types
22862 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22863 }
22864
22867 bool contains(const typename object_t::key_type& key) const
22868 {
22869 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22870 }
22871
22874 template<class KeyType, detail::enable_if_t<
22875 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22876 bool contains(KeyType && key) const
22877 {
22878 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22879 }
22880
22883 bool contains(const json_pointer& ptr) const
22884 {
22885 return ptr.contains(this);
22886 }
22887
22888 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22889 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22890 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22891 {
22892 return ptr.contains(this);
22893 }
22894
22896
22898 // iterators //
22900
22903
22906 iterator begin() noexcept
22907 {
22908 iterator result(this);
22909 result.set_begin();
22910 return result;
22911 }
22912
22915 const_iterator begin() const noexcept
22916 {
22917 return cbegin();
22918 }
22919
22922 const_iterator cbegin() const noexcept
22923 {
22924 const_iterator result(this);
22925 result.set_begin();
22926 return result;
22927 }
22928
22931 iterator end() noexcept
22932 {
22933 iterator result(this);
22934 result.set_end();
22935 return result;
22936 }
22937
22940 const_iterator end() const noexcept
22941 {
22942 return cend();
22943 }
22944
22947 const_iterator cend() const noexcept
22948 {
22949 const_iterator result(this);
22950 result.set_end();
22951 return result;
22952 }
22953
22957 {
22958 return reverse_iterator(end());
22959 }
22960
22964 {
22965 return crbegin();
22966 }
22967
22971 {
22972 return reverse_iterator(begin());
22973 }
22974
22978 {
22979 return crend();
22980 }
22981
22985 {
22986 return const_reverse_iterator(cend());
22987 }
22988
22992 {
22993 return const_reverse_iterator(cbegin());
22994 }
22995
22996 public:
23002 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
23003 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
23004 {
23005 return ref.items();
23006 }
23007
23013 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
23014 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
23015 {
23016 return ref.items();
23017 }
23018
23021 iteration_proxy<iterator> items() noexcept
23022 {
23023 return iteration_proxy<iterator>(*this);
23024 }
23025
23028 iteration_proxy<const_iterator> items() const noexcept
23029 {
23030 return iteration_proxy<const_iterator>(*this);
23031 }
23032
23034
23036 // capacity //
23038
23041
23044 bool empty() const noexcept
23045 {
23046 switch (m_data.m_type)
23047 {
23048 case value_t::null:
23049 {
23050 // null values are empty
23051 return true;
23052 }
23053
23054 case value_t::array:
23055 {
23056 // delegate call to array_t::empty()
23057 return m_data.m_value.array->empty();
23058 }
23059
23060 case value_t::object:
23061 {
23062 // delegate call to object_t::empty()
23063 return m_data.m_value.object->empty();
23064 }
23065
23066 case value_t::string:
23067 case value_t::boolean:
23068 case value_t::number_integer:
23069 case value_t::number_unsigned:
23070 case value_t::number_float:
23071 case value_t::binary:
23072 case value_t::discarded:
23073 default:
23074 {
23075 // all other types are nonempty
23076 return false;
23077 }
23078 }
23079 }
23080
23083 size_type size() const noexcept
23084 {
23085 switch (m_data.m_type)
23086 {
23087 case value_t::null:
23088 {
23089 // null values are empty
23090 return 0;
23091 }
23092
23093 case value_t::array:
23094 {
23095 // delegate call to array_t::size()
23096 return m_data.m_value.array->size();
23097 }
23098
23099 case value_t::object:
23100 {
23101 // delegate call to object_t::size()
23102 return m_data.m_value.object->size();
23103 }
23104
23105 case value_t::string:
23106 case value_t::boolean:
23107 case value_t::number_integer:
23108 case value_t::number_unsigned:
23109 case value_t::number_float:
23110 case value_t::binary:
23111 case value_t::discarded:
23112 default:
23113 {
23114 // all other types have size 1
23115 return 1;
23116 }
23117 }
23118 }
23119
23122 size_type max_size() const noexcept
23123 {
23124 switch (m_data.m_type)
23125 {
23126 case value_t::array:
23127 {
23128 // delegate call to array_t::max_size()
23129 return m_data.m_value.array->max_size();
23130 }
23131
23132 case value_t::object:
23133 {
23134 // delegate call to object_t::max_size()
23135 return m_data.m_value.object->max_size();
23136 }
23137
23138 case value_t::null:
23139 case value_t::string:
23140 case value_t::boolean:
23141 case value_t::number_integer:
23142 case value_t::number_unsigned:
23143 case value_t::number_float:
23144 case value_t::binary:
23145 case value_t::discarded:
23146 default:
23147 {
23148 // all other types have max_size() == size()
23149 return size();
23150 }
23151 }
23152 }
23153
23155
23157 // modifiers //
23159
23162
23165 void clear() noexcept
23166 {
23167 switch (m_data.m_type)
23168 {
23169 case value_t::number_integer:
23170 {
23171 m_data.m_value.number_integer = 0;
23172 break;
23173 }
23174
23175 case value_t::number_unsigned:
23176 {
23177 m_data.m_value.number_unsigned = 0;
23178 break;
23179 }
23180
23181 case value_t::number_float:
23182 {
23183 m_data.m_value.number_float = 0.0;
23184 break;
23185 }
23186
23187 case value_t::boolean:
23188 {
23189 m_data.m_value.boolean = false;
23190 break;
23191 }
23192
23193 case value_t::string:
23194 {
23195 m_data.m_value.string->clear();
23196 break;
23197 }
23198
23199 case value_t::binary:
23200 {
23201 m_data.m_value.binary->clear();
23202 break;
23203 }
23204
23205 case value_t::array:
23206 {
23207 m_data.m_value.array->clear();
23208 break;
23209 }
23210
23211 case value_t::object:
23212 {
23213 m_data.m_value.object->clear();
23214 break;
23215 }
23216
23217 case value_t::null:
23218 case value_t::discarded:
23219 default:
23220 break;
23221 }
23222 }
23223
23227 {
23228 // push_back only works for null objects or arrays
23229 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23230 {
23231 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23232 }
23233
23234 // transform a null object into an array
23235 if (is_null())
23236 {
23237 m_data.m_type = value_t::array;
23238 m_data.m_value = value_t::array;
23239 assert_invariant();
23240 }
23241
23242 // add the element to the array (move semantics)
23243 const auto old_capacity = m_data.m_value.array->capacity();
23244 m_data.m_value.array->push_back(std::move(val));
23245 set_parent(m_data.m_value.array->back(), old_capacity);
23246 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
23247 }
23248
23252 {
23253 push_back(std::move(val));
23254 return *this;
23255 }
23256
23259 void push_back(const basic_json& val)
23260 {
23261 // push_back only works for null objects or arrays
23262 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23263 {
23264 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23265 }
23266
23267 // transform a null object into an array
23268 if (is_null())
23269 {
23270 m_data.m_type = value_t::array;
23271 m_data.m_value = value_t::array;
23272 assert_invariant();
23273 }
23274
23275 // add the element to the array
23276 const auto old_capacity = m_data.m_value.array->capacity();
23277 m_data.m_value.array->push_back(val);
23278 set_parent(m_data.m_value.array->back(), old_capacity);
23279 }
23280
23284 {
23285 push_back(val);
23286 return *this;
23287 }
23288
23291 void push_back(const typename object_t::value_type& val)
23292 {
23293 // push_back only works for null objects or objects
23294 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23295 {
23296 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23297 }
23298
23299 // transform a null object into an object
23300 if (is_null())
23301 {
23302 m_data.m_type = value_t::object;
23303 m_data.m_value = value_t::object;
23304 assert_invariant();
23305 }
23306
23307 // add the element to the object
23308 auto res = m_data.m_value.object->insert(val);
23309 set_parent(res.first->second);
23310 }
23311
23314 reference operator+=(const typename object_t::value_type& val)
23315 {
23316 push_back(val);
23317 return *this;
23318 }
23319
23323 {
23324 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
23325 {
23326 basic_json&& key = init.begin()->moved_or_copied();
23327 push_back(typename object_t::value_type(
23328 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
23329 }
23330 else
23331 {
23332 push_back(basic_json(init));
23333 }
23334 }
23335
23339 {
23340 push_back(init);
23341 return *this;
23342 }
23343
23346 template<class... Args>
23347 reference emplace_back(Args&& ... args)
23348 {
23349 // emplace_back only works for null objects or arrays
23350 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23351 {
23352 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
23353 }
23354
23355 // transform a null object into an array
23356 if (is_null())
23357 {
23358 m_data.m_type = value_t::array;
23359 m_data.m_value = value_t::array;
23360 assert_invariant();
23361 }
23362
23363 // add the element to the array (perfect forwarding)
23364 const auto old_capacity = m_data.m_value.array->capacity();
23365 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
23366 return set_parent(m_data.m_value.array->back(), old_capacity);
23367 }
23368
23371 template<class... Args>
23372 std::pair<iterator, bool> emplace(Args&& ... args)
23373 {
23374 // emplace only works for null objects or arrays
23375 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23376 {
23377 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
23378 }
23379
23380 // transform a null object into an object
23381 if (is_null())
23382 {
23383 m_data.m_type = value_t::object;
23384 m_data.m_value = value_t::object;
23385 assert_invariant();
23386 }
23387
23388 // add the element to the array (perfect forwarding)
23389 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
23390 set_parent(res.first->second);
23391
23392 // create a result iterator and set iterator to the result of emplace
23393 auto it = begin();
23394 it.m_it.object_iterator = res.first;
23395
23396 // return pair of iterator and boolean
23397 return {it, res.second};
23398 }
23399
23403 template<typename... Args>
23404 iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
23405 {
23406 iterator result(this);
23407 JSON_ASSERT(m_data.m_value.array != nullptr);
23408
23409 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
23410 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
23411 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
23412
23413 // This could have been written as:
23414 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
23415 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
23416
23417 set_parents();
23418 return result;
23419 }
23420
23423 iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23424 {
23425 // insert only works for arrays
23426 if (JSON_HEDLEY_LIKELY(is_array()))
23427 {
23428 // check if iterator pos fits to this JSON value
23429 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23430 {
23431 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23432 }
23433
23434 // insert to array and return iterator
23435 return insert_iterator(pos, val);
23436 }
23437
23438 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23439 }
23440
23443 iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
23444 {
23445 return insert(pos, val);
23446 }
23447
23450 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23451 {
23452 // insert only works for arrays
23453 if (JSON_HEDLEY_LIKELY(is_array()))
23454 {
23455 // check if iterator pos fits to this JSON value
23456 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23457 {
23458 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23459 }
23460
23461 // insert to array and return iterator
23462 return insert_iterator(pos, cnt, val);
23463 }
23464
23465 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23466 }
23467
23470 iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23471 {
23472 // insert only works for arrays
23473 if (JSON_HEDLEY_UNLIKELY(!is_array()))
23474 {
23475 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23476 }
23477
23478 // check if iterator pos fits to this JSON value
23479 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23480 {
23481 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23482 }
23483
23484 // check if range iterators belong to the same JSON object
23485 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23486 {
23487 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23488 }
23489
23490 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
23491 {
23492 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
23493 }
23494
23495 // insert to array and return iterator
23496 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
23497 }
23498
23501 iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
23502 {
23503 // insert only works for arrays
23504 if (JSON_HEDLEY_UNLIKELY(!is_array()))
23505 {
23506 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23507 }
23508
23509 // check if iterator pos fits to this JSON value
23510 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23511 {
23512 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23513 }
23514
23515 // insert to array and return iterator
23516 return insert_iterator(pos, ilist.begin(), ilist.end());
23517 }
23518
23521 void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23522 {
23523 // insert only works for objects
23524 if (JSON_HEDLEY_UNLIKELY(!is_object()))
23525 {
23526 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23527 }
23528
23529 // check if range iterators belong to the same JSON object
23530 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23531 {
23532 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23533 }
23534
23535 // passed iterators must belong to objects
23536 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23537 {
23538 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
23539 }
23540
23541 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
23542 set_parents();
23543 }
23544
23547 void update(const_reference j, bool merge_objects = false)
23548 {
23549 update(j.begin(), j.end(), merge_objects);
23550 }
23551
23554 void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
23555 {
23556 // implicitly convert a null value to an empty object
23557 if (is_null())
23558 {
23559 m_data.m_type = value_t::object;
23560 m_data.m_value.object = create<object_t>();
23561 assert_invariant();
23562 }
23563
23564 if (JSON_HEDLEY_UNLIKELY(!is_object()))
23565 {
23566 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
23567 }
23568
23569 // check if range iterators belong to the same JSON object
23570 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23571 {
23572 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23573 }
23574
23575 // passed iterators must belong to objects
23576 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23577 {
23578 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
23579 }
23580
23581 for (auto it = first; it != last; ++it)
23582 {
23583 if (merge_objects && it.value().is_object())
23584 {
23585 auto it2 = m_data.m_value.object->find(it.key());
23586 if (it2 != m_data.m_value.object->end())
23587 {
23588 it2->second.update(it.value(), true);
23589 continue;
23590 }
23591 }
23592 m_data.m_value.object->operator[](it.key()) = it.value();
23593#if JSON_DIAGNOSTICS
23594 m_data.m_value.object->operator[](it.key()).m_parent = this;
23595#endif
23596 }
23597 }
23598
23601 void swap(reference other) noexcept (
23602 std::is_nothrow_move_constructible<value_t>::value&&
23603 std::is_nothrow_move_assignable<value_t>::value&&
23604 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23605 std::is_nothrow_move_assignable<json_value>::value
23606 )
23607 {
23608 std::swap(m_data.m_type, other.m_data.m_type);
23609 std::swap(m_data.m_value, other.m_data.m_value);
23610
23611 set_parents();
23612 other.set_parents();
23613 assert_invariant();
23614 }
23615
23618 friend void swap(reference left, reference right) noexcept (
23619 std::is_nothrow_move_constructible<value_t>::value&&
23620 std::is_nothrow_move_assignable<value_t>::value&&
23621 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23622 std::is_nothrow_move_assignable<json_value>::value
23623 )
23624 {
23625 left.swap(right);
23626 }
23627
23630 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23631 {
23632 // swap only works for arrays
23633 if (JSON_HEDLEY_LIKELY(is_array()))
23634 {
23635 using std::swap;
23636 swap(*(m_data.m_value.array), other);
23637 }
23638 else
23639 {
23640 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
23641 }
23642 }
23643
23646 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23647 {
23648 // swap only works for objects
23649 if (JSON_HEDLEY_LIKELY(is_object()))
23650 {
23651 using std::swap;
23652 swap(*(m_data.m_value.object), other);
23653 }
23654 else
23655 {
23656 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
23657 }
23658 }
23659
23662 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23663 {
23664 // swap only works for strings
23665 if (JSON_HEDLEY_LIKELY(is_string()))
23666 {
23667 using std::swap;
23668 swap(*(m_data.m_value.string), other);
23669 }
23670 else
23671 {
23672 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
23673 }
23674 }
23675
23678 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23679 {
23680 // swap only works for strings
23681 if (JSON_HEDLEY_LIKELY(is_binary()))
23682 {
23683 using std::swap;
23684 swap(*(m_data.m_value.binary), other);
23685 }
23686 else
23687 {
23688 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
23689 }
23690 }
23691
23694 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
23695 {
23696 // swap only works for strings
23697 if (JSON_HEDLEY_LIKELY(is_binary()))
23698 {
23699 using std::swap;
23700 swap(*(m_data.m_value.binary), other);
23701 }
23702 else
23703 {
23704 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
23705 }
23706 }
23707
23709
23711 // lexicographical comparison operators //
23713
23716
23717 // note parentheses around operands are necessary; see
23718 // https://github.com/nlohmann/json/issues/1530
23719#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
23720 const auto lhs_type = lhs.type(); \
23721 const auto rhs_type = rhs.type(); \
23722 \
23723 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
23724 { \
23725 switch (lhs_type) \
23726 { \
23727 case value_t::array: \
23728 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
23729 \
23730 case value_t::object: \
23731 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
23732 \
23733 case value_t::null: \
23734 return (null_result); \
23735 \
23736 case value_t::string: \
23737 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
23738 \
23739 case value_t::boolean: \
23740 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
23741 \
23742 case value_t::number_integer: \
23743 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
23744 \
23745 case value_t::number_unsigned: \
23746 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
23747 \
23748 case value_t::number_float: \
23749 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
23750 \
23751 case value_t::binary: \
23752 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
23753 \
23754 case value_t::discarded: \
23755 default: \
23756 return (unordered_result); \
23757 } \
23758 } \
23759 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
23760 { \
23761 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
23762 } \
23763 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
23764 { \
23765 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
23766 } \
23767 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
23768 { \
23769 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
23770 } \
23771 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
23772 { \
23773 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
23774 } \
23775 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
23776 { \
23777 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
23778 } \
23779 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
23780 { \
23781 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
23782 } \
23783 else if(compares_unordered(lhs, rhs))\
23784 {\
23785 return (unordered_result);\
23786 }\
23787 \
23788 return (default_result);
23789
23790 JSON_PRIVATE_UNLESS_TESTED:
23791 // returns true if:
23792 // - any operand is NaN and the other operand is of number type
23793 // - any operand is discarded
23794 // in legacy mode, discarded values are considered ordered if
23795 // an operation is computed as an odd number of inverses of others
23796 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
23797 {
23798 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
23799 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
23800 {
23801 return true;
23802 }
23803#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23804 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
23805#else
23806 static_cast<void>(inverse);
23807 return lhs.is_discarded() || rhs.is_discarded();
23808#endif
23809 }
23810
23811 private:
23812 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
23813 {
23814 return compares_unordered(*this, rhs, inverse);
23815 }
23816
23817 public:
23818#if JSON_HAS_THREE_WAY_COMPARISON
23821 bool operator==(const_reference rhs) const noexcept
23822 {
23823#ifdef __GNUC__
23824#pragma GCC diagnostic push
23825#pragma GCC diagnostic ignored "-Wfloat-equal"
23826#endif
23827 const_reference lhs = *this;
23828 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23829#ifdef __GNUC__
23830#pragma GCC diagnostic pop
23831#endif
23832 }
23833
23836 template<typename ScalarType>
23837 requires std::is_scalar_v<ScalarType>
23838 bool operator==(ScalarType rhs) const noexcept
23839 {
23840 return *this == basic_json(rhs);
23841 }
23842
23845 bool operator!=(const_reference rhs) const noexcept
23846 {
23847 if (compares_unordered(rhs, true))
23848 {
23849 return false;
23850 }
23851 return !operator==(rhs);
23852 }
23853
23856 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23857 {
23858 const_reference lhs = *this;
23859 // default_result is used if we cannot compare values. In that case,
23860 // we compare types.
23861 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23862 std::partial_ordering::equivalent,
23863 std::partial_ordering::unordered,
23864 lhs_type <=> rhs_type) // *NOPAD*
23865 }
23866
23869 template<typename ScalarType>
23870 requires std::is_scalar_v<ScalarType>
23871 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23872 {
23873 return *this <=> basic_json(rhs); // *NOPAD*
23874 }
23875
23876#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23877 // all operators that are computed as an odd number of inverses of others
23878 // need to be overloaded to emulate the legacy comparison behavior
23879
23882 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23883 bool operator<=(const_reference rhs) const noexcept
23884 {
23885 if (compares_unordered(rhs, true))
23886 {
23887 return false;
23888 }
23889 return !(rhs < *this);
23890 }
23891
23894 template<typename ScalarType>
23895 requires std::is_scalar_v<ScalarType>
23896 bool operator<=(ScalarType rhs) const noexcept
23897 {
23898 return *this <= basic_json(rhs);
23899 }
23900
23903 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23904 bool operator>=(const_reference rhs) const noexcept
23905 {
23906 if (compares_unordered(rhs, true))
23907 {
23908 return false;
23909 }
23910 return !(*this < rhs);
23911 }
23912
23915 template<typename ScalarType>
23916 requires std::is_scalar_v<ScalarType>
23917 bool operator>=(ScalarType rhs) const noexcept
23918 {
23919 return *this >= basic_json(rhs);
23920 }
23921#endif
23922#else
23925 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23926 {
23927#ifdef __GNUC__
23928#pragma GCC diagnostic push
23929#pragma GCC diagnostic ignored "-Wfloat-equal"
23930#endif
23931 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23932#ifdef __GNUC__
23933#pragma GCC diagnostic pop
23934#endif
23935 }
23936
23939 template<typename ScalarType, typename std::enable_if<
23940 std::is_scalar<ScalarType>::value, int>::type = 0>
23941 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23942 {
23943 return lhs == basic_json(rhs);
23944 }
23945
23948 template<typename ScalarType, typename std::enable_if<
23949 std::is_scalar<ScalarType>::value, int>::type = 0>
23950 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23951 {
23952 return basic_json(lhs) == rhs;
23953 }
23954
23957 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23958 {
23959 if (compares_unordered(lhs, rhs, true))
23960 {
23961 return false;
23962 }
23963 return !(lhs == rhs);
23964 }
23965
23968 template<typename ScalarType, typename std::enable_if<
23969 std::is_scalar<ScalarType>::value, int>::type = 0>
23970 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23971 {
23972 return lhs != basic_json(rhs);
23973 }
23974
23977 template<typename ScalarType, typename std::enable_if<
23978 std::is_scalar<ScalarType>::value, int>::type = 0>
23979 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23980 {
23981 return basic_json(lhs) != rhs;
23982 }
23983
23986 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23987 {
23988 // default_result is used if we cannot compare values. In that case,
23989 // we compare types. Note we have to call the operator explicitly,
23990 // because MSVC has problems otherwise.
23991 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23992 }
23993
23996 template<typename ScalarType, typename std::enable_if<
23997 std::is_scalar<ScalarType>::value, int>::type = 0>
23998 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23999 {
24000 return lhs < basic_json(rhs);
24001 }
24002
24005 template<typename ScalarType, typename std::enable_if<
24006 std::is_scalar<ScalarType>::value, int>::type = 0>
24007 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
24008 {
24009 return basic_json(lhs) < rhs;
24010 }
24011
24014 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
24015 {
24016 if (compares_unordered(lhs, rhs, true))
24017 {
24018 return false;
24019 }
24020 return !(rhs < lhs);
24021 }
24022
24025 template<typename ScalarType, typename std::enable_if<
24026 std::is_scalar<ScalarType>::value, int>::type = 0>
24027 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
24028 {
24029 return lhs <= basic_json(rhs);
24030 }
24031
24034 template<typename ScalarType, typename std::enable_if<
24035 std::is_scalar<ScalarType>::value, int>::type = 0>
24036 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
24037 {
24038 return basic_json(lhs) <= rhs;
24039 }
24040
24043 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
24044 {
24045 // double inverse
24046 if (compares_unordered(lhs, rhs))
24047 {
24048 return false;
24049 }
24050 return !(lhs <= rhs);
24051 }
24052
24055 template<typename ScalarType, typename std::enable_if<
24056 std::is_scalar<ScalarType>::value, int>::type = 0>
24057 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
24058 {
24059 return lhs > basic_json(rhs);
24060 }
24061
24064 template<typename ScalarType, typename std::enable_if<
24065 std::is_scalar<ScalarType>::value, int>::type = 0>
24066 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
24067 {
24068 return basic_json(lhs) > rhs;
24069 }
24070
24073 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
24074 {
24075 if (compares_unordered(lhs, rhs, true))
24076 {
24077 return false;
24078 }
24079 return !(lhs < rhs);
24080 }
24081
24084 template<typename ScalarType, typename std::enable_if<
24085 std::is_scalar<ScalarType>::value, int>::type = 0>
24086 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
24087 {
24088 return lhs >= basic_json(rhs);
24089 }
24090
24093 template<typename ScalarType, typename std::enable_if<
24094 std::is_scalar<ScalarType>::value, int>::type = 0>
24095 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
24096 {
24097 return basic_json(lhs) >= rhs;
24098 }
24099#endif
24100
24101#undef JSON_IMPLEMENT_OPERATOR
24102
24104
24106 // serialization //
24108
24111#ifndef JSON_NO_IO
24114 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
24115 {
24116 // read width member and use it as the indentation parameter if nonzero
24117 const bool pretty_print = o.width() > 0;
24118 const auto indentation = pretty_print ? o.width() : 0;
24119
24120 // reset width to 0 for subsequent calls to this stream
24121 o.width(0);
24122
24123 // do the actual serialization
24124 serializer s(detail::output_adapter<char>(o), o.fill());
24125 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
24126 return o;
24127 }
24128
24135 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
24136 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
24137 {
24138 return o << j;
24139 }
24140#endif // JSON_NO_IO
24142
24144 // deserialization //
24146
24149
24152 template<typename InputType>
24153 JSON_HEDLEY_WARN_UNUSED_RESULT
24154 static basic_json parse(InputType&& i,
24155 parser_callback_t cb = nullptr,
24156 const bool allow_exceptions = true,
24157 const bool ignore_comments = false,
24158 const bool ignore_trailing_commas = false)
24159 {
24160 basic_json result;
24161 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]
24162 return result;
24163 }
24164
24167 template<typename IteratorType>
24168 JSON_HEDLEY_WARN_UNUSED_RESULT
24169 static basic_json parse(IteratorType first,
24170 IteratorType last,
24171 parser_callback_t cb = nullptr,
24172 const bool allow_exceptions = true,
24173 const bool ignore_comments = false,
24174 const bool ignore_trailing_commas = false)
24175 {
24176 basic_json result;
24177 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]
24178 return result;
24179 }
24180
24181 JSON_HEDLEY_WARN_UNUSED_RESULT
24182 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
24183 static basic_json parse(detail::span_input_adapter&& i,
24184 parser_callback_t cb = nullptr,
24185 const bool allow_exceptions = true,
24186 const bool ignore_comments = false,
24187 const bool ignore_trailing_commas = false)
24188 {
24189 basic_json result;
24190 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
24191 return result;
24192 }
24193
24196 template<typename InputType>
24197 static bool accept(InputType&& i,
24198 const bool ignore_comments = false,
24199 const bool ignore_trailing_commas = false)
24200 {
24201 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24202 }
24203
24206 template<typename IteratorType>
24207 static bool accept(IteratorType first, IteratorType last,
24208 const bool ignore_comments = false,
24209 const bool ignore_trailing_commas = false)
24210 {
24211 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24212 }
24213
24214 JSON_HEDLEY_WARN_UNUSED_RESULT
24215 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
24216 static bool accept(detail::span_input_adapter&& i,
24217 const bool ignore_comments = false,
24218 const bool ignore_trailing_commas = false)
24219 {
24220 return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24221 }
24222
24225 template <typename InputType, typename SAX>
24226 JSON_HEDLEY_NON_NULL(2)
24227 static bool sax_parse(InputType&& i, SAX* sax,
24228 input_format_t format = input_format_t::json,
24229 const bool strict = true,
24230 const bool ignore_comments = false,
24231 const bool ignore_trailing_commas = false)
24232 {
24233 auto ia = detail::input_adapter(std::forward<InputType>(i));
24234 return format == input_format_t::json
24235 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24236 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24237 }
24238
24241 template<class IteratorType, class SAX>
24242 JSON_HEDLEY_NON_NULL(3)
24243 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
24244 input_format_t format = input_format_t::json,
24245 const bool strict = true,
24246 const bool ignore_comments = false,
24247 const bool ignore_trailing_commas = false)
24248 {
24249 auto ia = detail::input_adapter(std::move(first), std::move(last));
24250 return format == input_format_t::json
24251 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24252 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24253 }
24254
24260 template <typename SAX>
24261 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
24262 JSON_HEDLEY_NON_NULL(2)
24263 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
24264 input_format_t format = input_format_t::json,
24265 const bool strict = true,
24266 const bool ignore_comments = false,
24267 const bool ignore_trailing_commas = false)
24268 {
24269 auto ia = i.get();
24270 return format == input_format_t::json
24271 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24272 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24273 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24274 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24275 }
24276#ifndef JSON_NO_IO
24283 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
24284 friend std::istream& operator<<(basic_json& j, std::istream& i)
24285 {
24286 return operator>>(i, j);
24287 }
24288
24291 friend std::istream& operator>>(std::istream& i, basic_json& j)
24292 {
24293 parser(detail::input_adapter(i)).parse(false, j);
24294 return i;
24295 }
24296#endif // JSON_NO_IO
24298
24300 // convenience functions //
24302
24305 JSON_HEDLEY_RETURNS_NON_NULL
24306 const char* type_name() const noexcept
24307 {
24308 switch (m_data.m_type)
24309 {
24310 case value_t::null:
24311 return "null";
24312 case value_t::object:
24313 return "object";
24314 case value_t::array:
24315 return "array";
24316 case value_t::string:
24317 return "string";
24318 case value_t::boolean:
24319 return "boolean";
24320 case value_t::binary:
24321 return "binary";
24322 case value_t::discarded:
24323 return "discarded";
24324 case value_t::number_integer:
24325 case value_t::number_unsigned:
24326 case value_t::number_float:
24327 return "number";
24328 default:
24329 return "invalid";
24330 }
24331 }
24332
24333 JSON_PRIVATE_UNLESS_TESTED:
24335 // member variables //
24337
24338 struct data
24339 {
24341 value_t m_type = value_t::null;
24342
24344 json_value m_value = {};
24345
24346 data(const value_t v)
24347 : m_type(v), m_value(v)
24348 {
24349 }
24350
24351 data(size_type cnt, const basic_json& val)
24352 : m_type(value_t::array)
24353 {
24354 m_value.array = create<array_t>(cnt, val);
24355 }
24356
24357 data() noexcept = default;
24358 data(data&&) noexcept = default;
24359 data(const data&) noexcept = delete;
24360 data& operator=(data&&) noexcept = delete;
24361 data& operator=(const data&) noexcept = delete;
24362
24363 ~data() noexcept
24364 {
24365 m_value.destroy(m_type);
24366 }
24367 };
24368
24369 data m_data = {};
24370
24371#if JSON_DIAGNOSTICS
24373 basic_json* m_parent = nullptr;
24374#endif
24375
24376#if JSON_DIAGNOSTIC_POSITIONS
24378 std::size_t start_position = std::string::npos;
24380 std::size_t end_position = std::string::npos;
24381 public:
24382 constexpr std::size_t start_pos() const noexcept
24383 {
24384 return start_position;
24385 }
24386
24387 constexpr std::size_t end_pos() const noexcept
24388 {
24389 return end_position;
24390 }
24391#endif
24392
24394 // binary serialization/deserialization //
24396
24399
24400 public:
24403 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
24404 {
24405 std::vector<std::uint8_t> result;
24406 to_cbor(j, result);
24407 return result;
24408 }
24409
24412 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
24413 {
24414 binary_writer<std::uint8_t>(o).write_cbor(j);
24415 }
24416
24419 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
24420 {
24421 binary_writer<char>(o).write_cbor(j);
24422 }
24423
24426 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
24427 {
24428 std::vector<std::uint8_t> result;
24429 to_msgpack(j, result);
24430 return result;
24431 }
24432
24435 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
24436 {
24437 binary_writer<std::uint8_t>(o).write_msgpack(j);
24438 }
24439
24442 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
24443 {
24444 binary_writer<char>(o).write_msgpack(j);
24445 }
24446
24449 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
24450 const bool use_size = false,
24451 const bool use_type = false)
24452 {
24453 std::vector<std::uint8_t> result;
24454 to_ubjson(j, result, use_size, use_type);
24455 return result;
24456 }
24457
24460 static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
24461 const bool use_size = false, const bool use_type = false)
24462 {
24463 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
24464 }
24465
24468 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
24469 const bool use_size = false, const bool use_type = false)
24470 {
24471 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
24472 }
24473
24476 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
24477 const bool use_size = false,
24478 const bool use_type = false,
24479 const bjdata_version_t version = bjdata_version_t::draft2)
24480 {
24481 std::vector<std::uint8_t> result;
24482 to_bjdata(j, result, use_size, use_type, version);
24483 return result;
24484 }
24485
24488 static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
24489 const bool use_size = false, const bool use_type = false,
24490 const bjdata_version_t version = bjdata_version_t::draft2)
24491 {
24492 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true, version);
24493 }
24494
24497 static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
24498 const bool use_size = false, const bool use_type = false,
24499 const bjdata_version_t version = bjdata_version_t::draft2)
24500 {
24501 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true, version);
24502 }
24503
24506 static std::vector<std::uint8_t> to_bson(const basic_json& j)
24507 {
24508 std::vector<std::uint8_t> result;
24509 to_bson(j, result);
24510 return result;
24511 }
24512
24515 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
24516 {
24517 binary_writer<std::uint8_t>(o).write_bson(j);
24518 }
24519
24522 static void to_bson(const basic_json& j, detail::output_adapter<char> o)
24523 {
24524 binary_writer<char>(o).write_bson(j);
24525 }
24526
24529 template<typename InputType>
24530 JSON_HEDLEY_WARN_UNUSED_RESULT
24531 static basic_json from_cbor(InputType&& i,
24532 const bool strict = true,
24533 const bool allow_exceptions = true,
24534 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24535 {
24536 basic_json result;
24537 auto ia = detail::input_adapter(std::forward<InputType>(i));
24538 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24539 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]
24540 return res ? result : basic_json(value_t::discarded);
24541 }
24542
24545 template<typename IteratorType>
24546 JSON_HEDLEY_WARN_UNUSED_RESULT
24547 static basic_json from_cbor(IteratorType first, IteratorType last,
24548 const bool strict = true,
24549 const bool allow_exceptions = true,
24550 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24551 {
24552 basic_json result;
24553 auto ia = detail::input_adapter(std::move(first), std::move(last));
24554 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24555 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]
24556 return res ? result : basic_json(value_t::discarded);
24557 }
24558
24559 template<typename T>
24560 JSON_HEDLEY_WARN_UNUSED_RESULT
24561 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24562 static basic_json from_cbor(const T* ptr, std::size_t len,
24563 const bool strict = true,
24564 const bool allow_exceptions = true,
24565 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24566 {
24567 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
24568 }
24569
24570 JSON_HEDLEY_WARN_UNUSED_RESULT
24571 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24572 static basic_json from_cbor(detail::span_input_adapter&& i,
24573 const bool strict = true,
24574 const bool allow_exceptions = true,
24575 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24576 {
24577 basic_json result;
24578 auto ia = i.get();
24579 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24580 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24581 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]
24582 return res ? result : basic_json(value_t::discarded);
24583 }
24584
24587 template<typename InputType>
24588 JSON_HEDLEY_WARN_UNUSED_RESULT
24589 static basic_json from_msgpack(InputType&& i,
24590 const bool strict = true,
24591 const bool allow_exceptions = true)
24592 {
24593 basic_json result;
24594 auto ia = detail::input_adapter(std::forward<InputType>(i));
24595 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24596 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]
24597 return res ? result : basic_json(value_t::discarded);
24598 }
24599
24602 template<typename IteratorType>
24603 JSON_HEDLEY_WARN_UNUSED_RESULT
24604 static basic_json from_msgpack(IteratorType first, IteratorType last,
24605 const bool strict = true,
24606 const bool allow_exceptions = true)
24607 {
24608 basic_json result;
24609 auto ia = detail::input_adapter(std::move(first), std::move(last));
24610 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24611 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]
24612 return res ? result : basic_json(value_t::discarded);
24613 }
24614
24615 template<typename T>
24616 JSON_HEDLEY_WARN_UNUSED_RESULT
24617 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24618 static basic_json from_msgpack(const T* ptr, std::size_t len,
24619 const bool strict = true,
24620 const bool allow_exceptions = true)
24621 {
24622 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
24623 }
24624
24625 JSON_HEDLEY_WARN_UNUSED_RESULT
24626 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24627 static basic_json from_msgpack(detail::span_input_adapter&& i,
24628 const bool strict = true,
24629 const bool allow_exceptions = true)
24630 {
24631 basic_json result;
24632 auto ia = i.get();
24633 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24634 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24635 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]
24636 return res ? result : basic_json(value_t::discarded);
24637 }
24638
24641 template<typename InputType>
24642 JSON_HEDLEY_WARN_UNUSED_RESULT
24643 static basic_json from_ubjson(InputType&& i,
24644 const bool strict = true,
24645 const bool allow_exceptions = true)
24646 {
24647 basic_json result;
24648 auto ia = detail::input_adapter(std::forward<InputType>(i));
24649 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24650 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]
24651 return res ? result : basic_json(value_t::discarded);
24652 }
24653
24656 template<typename IteratorType>
24657 JSON_HEDLEY_WARN_UNUSED_RESULT
24658 static basic_json from_ubjson(IteratorType first, IteratorType last,
24659 const bool strict = true,
24660 const bool allow_exceptions = true)
24661 {
24662 basic_json result;
24663 auto ia = detail::input_adapter(std::move(first), std::move(last));
24664 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24665 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]
24666 return res ? result : basic_json(value_t::discarded);
24667 }
24668
24669 template<typename T>
24670 JSON_HEDLEY_WARN_UNUSED_RESULT
24671 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24672 static basic_json from_ubjson(const T* ptr, std::size_t len,
24673 const bool strict = true,
24674 const bool allow_exceptions = true)
24675 {
24676 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24677 }
24678
24679 JSON_HEDLEY_WARN_UNUSED_RESULT
24680 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24681 static basic_json from_ubjson(detail::span_input_adapter&& i,
24682 const bool strict = true,
24683 const bool allow_exceptions = true)
24684 {
24685 basic_json result;
24686 auto ia = i.get();
24687 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24688 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24689 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]
24690 return res ? result : basic_json(value_t::discarded);
24691 }
24692
24695 template<typename InputType>
24696 JSON_HEDLEY_WARN_UNUSED_RESULT
24697 static basic_json from_bjdata(InputType&& i,
24698 const bool strict = true,
24699 const bool allow_exceptions = true)
24700 {
24701 basic_json result;
24702 auto ia = detail::input_adapter(std::forward<InputType>(i));
24703 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24704 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]
24705 return res ? result : basic_json(value_t::discarded);
24706 }
24707
24710 template<typename IteratorType>
24711 JSON_HEDLEY_WARN_UNUSED_RESULT
24712 static basic_json from_bjdata(IteratorType first, IteratorType last,
24713 const bool strict = true,
24714 const bool allow_exceptions = true)
24715 {
24716 basic_json result;
24717 auto ia = detail::input_adapter(std::move(first), std::move(last));
24718 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24719 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]
24720 return res ? result : basic_json(value_t::discarded);
24721 }
24722
24725 template<typename InputType>
24726 JSON_HEDLEY_WARN_UNUSED_RESULT
24727 static basic_json from_bson(InputType&& i,
24728 const bool strict = true,
24729 const bool allow_exceptions = true)
24730 {
24731 basic_json result;
24732 auto ia = detail::input_adapter(std::forward<InputType>(i));
24733 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24734 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]
24735 return res ? result : basic_json(value_t::discarded);
24736 }
24737
24740 template<typename IteratorType>
24741 JSON_HEDLEY_WARN_UNUSED_RESULT
24742 static basic_json from_bson(IteratorType first, IteratorType last,
24743 const bool strict = true,
24744 const bool allow_exceptions = true)
24745 {
24746 basic_json result;
24747 auto ia = detail::input_adapter(std::move(first), std::move(last));
24748 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24749 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]
24750 return res ? result : basic_json(value_t::discarded);
24751 }
24752
24753 template<typename T>
24754 JSON_HEDLEY_WARN_UNUSED_RESULT
24755 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24756 static basic_json from_bson(const T* ptr, std::size_t len,
24757 const bool strict = true,
24758 const bool allow_exceptions = true)
24759 {
24760 return from_bson(ptr, ptr + len, strict, allow_exceptions);
24761 }
24762
24763 JSON_HEDLEY_WARN_UNUSED_RESULT
24764 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24765 static basic_json from_bson(detail::span_input_adapter&& i,
24766 const bool strict = true,
24767 const bool allow_exceptions = true)
24768 {
24769 basic_json result;
24770 auto ia = i.get();
24771 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24772 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24773 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]
24774 return res ? result : basic_json(value_t::discarded);
24775 }
24777
24779 // JSON Pointer support //
24781
24784
24788 {
24789 return ptr.get_unchecked(this);
24790 }
24791
24792 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24793 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24794 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24795 {
24796 return ptr.get_unchecked(this);
24797 }
24798
24802 {
24803 return ptr.get_unchecked(this);
24804 }
24805
24806 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24807 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24808 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24809 {
24810 return ptr.get_unchecked(this);
24811 }
24812
24816 {
24817 return ptr.get_checked(this);
24818 }
24819
24820 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24821 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24822 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24823 {
24824 return ptr.get_checked(this);
24825 }
24826
24830 {
24831 return ptr.get_checked(this);
24832 }
24833
24834 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24835 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24836 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24837 {
24838 return ptr.get_checked(this);
24839 }
24840
24844 {
24845 basic_json result(value_t::object);
24846 json_pointer::flatten("", *this, result);
24847 return result;
24848 }
24849
24853 {
24854 return json_pointer::unflatten(*this);
24855 }
24856
24858
24860 // JSON Patch functions //
24862
24865
24868 void patch_inplace(const basic_json& json_patch)
24869 {
24870 basic_json& result = *this;
24871 // the valid JSON Patch operations
24872 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24873
24874 const auto get_op = [](const string_t& op)
24875 {
24876 if (op == "add")
24877 {
24878 return patch_operations::add;
24879 }
24880 if (op == "remove")
24881 {
24882 return patch_operations::remove;
24883 }
24884 if (op == "replace")
24885 {
24886 return patch_operations::replace;
24887 }
24888 if (op == "move")
24889 {
24890 return patch_operations::move;
24891 }
24892 if (op == "copy")
24893 {
24894 return patch_operations::copy;
24895 }
24896 if (op == "test")
24897 {
24898 return patch_operations::test;
24899 }
24900
24901 return patch_operations::invalid;
24902 };
24903
24904 // wrapper for "add" operation; add value at ptr
24905 const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
24906 {
24907 // adding to the root of the target document means replacing it
24908 if (ptr.empty())
24909 {
24910 result = val;
24911 return;
24912 }
24913
24914 // make sure the top element of the pointer exists
24915 json_pointer const top_pointer = ptr.top();
24916 if (top_pointer != ptr)
24917 {
24918 result.at(top_pointer);
24919 }
24920
24921 // get reference to the parent of the JSON pointer ptr
24922 const auto last_path = ptr.back();
24923 ptr.pop_back();
24924 // parent must exist when performing patch add per RFC6902 specs
24925 basic_json& parent = result.at(ptr);
24926
24927 switch (parent.m_data.m_type)
24928 {
24929 case value_t::null:
24930 case value_t::object:
24931 {
24932 // use operator[] to add value
24933 parent[last_path] = val;
24934 break;
24935 }
24936
24937 case value_t::array:
24938 {
24939 if (last_path == "-")
24940 {
24941 // special case: append to back
24942 parent.push_back(val);
24943 }
24944 else
24945 {
24946 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24947 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24948 {
24949 // avoid undefined behavior
24950 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24951 }
24952
24953 // default case: insert add offset
24954 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24955 }
24956 break;
24957 }
24958
24959 // if there exists a parent, it cannot be primitive
24960 case value_t::string: // LCOV_EXCL_LINE
24961 case value_t::boolean: // LCOV_EXCL_LINE
24962 case value_t::number_integer: // LCOV_EXCL_LINE
24963 case value_t::number_unsigned: // LCOV_EXCL_LINE
24964 case value_t::number_float: // LCOV_EXCL_LINE
24965 case value_t::binary: // LCOV_EXCL_LINE
24966 case value_t::discarded: // LCOV_EXCL_LINE
24967 default: // LCOV_EXCL_LINE
24968 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24969 }
24970 };
24971
24972 // wrapper for "remove" operation; remove value at ptr
24973 const auto operation_remove = [this, & result](json_pointer & ptr)
24974 {
24975 // get reference to the parent of the JSON pointer ptr
24976 const auto last_path = ptr.back();
24977 ptr.pop_back();
24978 basic_json& parent = result.at(ptr);
24979
24980 // remove child
24981 if (parent.is_object())
24982 {
24983 // perform range check
24984 auto it = parent.find(last_path);
24985 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24986 {
24987 parent.erase(it);
24988 }
24989 else
24990 {
24991 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24992 }
24993 }
24994 else if (parent.is_array())
24995 {
24996 // note erase performs range check
24997 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24998 }
24999 };
25000
25001 // type check: top level value must be an array
25002 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
25003 {
25004 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
25005 }
25006
25007 // iterate and apply the operations
25008 for (const auto& val : json_patch)
25009 {
25010 // wrapper to get a value for an operation
25011 const auto get_value = [&val](const string_t& op,
25012 const string_t& member,
25013 bool string_type) -> basic_json &
25014 {
25015 // find value
25016 auto it = val.m_data.m_value.object->find(member);
25017
25018 // context-sensitive error message
25019 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
25020
25021 // check if the desired value is present
25022 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
25023 {
25024 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
25025 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
25026 }
25027
25028 // check if the result is of type string
25029 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
25030 {
25031 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
25032 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
25033 }
25034
25035 // no error: return value
25036 return it->second;
25037 };
25038
25039 // type check: every element of the array must be an object
25040 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
25041 {
25042 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
25043 }
25044
25045 // collect mandatory members
25046 const auto op = get_value("op", "op", true).template get<string_t>();
25047 const auto path = get_value(op, "path", true).template get<string_t>();
25048 json_pointer ptr(path);
25049
25050 switch (get_op(op))
25051 {
25052 case patch_operations::add:
25053 {
25054 operation_add(ptr, get_value("add", "value", false));
25055 break;
25056 }
25057
25058 case patch_operations::remove:
25059 {
25060 operation_remove(ptr);
25061 break;
25062 }
25063
25064 case patch_operations::replace:
25065 {
25066 // the "path" location must exist - use at()
25067 result.at(ptr) = get_value("replace", "value", false);
25068 break;
25069 }
25070
25071 case patch_operations::move:
25072 {
25073 const auto from_path = get_value("move", "from", true).template get<string_t>();
25074 json_pointer from_ptr(from_path);
25075
25076 // the "from" location must exist - use at()
25077 basic_json const v = result.at(from_ptr);
25078
25079 // The move operation is functionally identical to a
25080 // "remove" operation on the "from" location, followed
25081 // immediately by an "add" operation at the target
25082 // location with the value that was just removed.
25083 operation_remove(from_ptr);
25084 operation_add(ptr, v);
25085 break;
25086 }
25087
25088 case patch_operations::copy:
25089 {
25090 const auto from_path = get_value("copy", "from", true).template get<string_t>();
25091 const json_pointer from_ptr(from_path);
25092
25093 // the "from" location must exist - use at()
25094 basic_json const v = result.at(from_ptr);
25095
25096 // The copy is functionally identical to an "add"
25097 // operation at the target location using the value
25098 // specified in the "from" member.
25099 operation_add(ptr, v);
25100 break;
25101 }
25102
25103 case patch_operations::test:
25104 {
25105 bool success = false;
25106 JSON_TRY
25107 {
25108 // check if "value" matches the one at "path"
25109 // the "path" location must exist - use at()
25110 success = (result.at(ptr) == get_value("test", "value", false));
25111 }
25112 JSON_INTERNAL_CATCH (out_of_range&)
25113 {
25114 // ignore out of range errors: success remains false
25115 }
25116
25117 // throw an exception if the test fails
25118 if (JSON_HEDLEY_UNLIKELY(!success))
25119 {
25120 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
25121 }
25122
25123 break;
25124 }
25125
25126 case patch_operations::invalid:
25127 default:
25128 {
25129 // op must be "add", "remove", "replace", "move", "copy", or
25130 // "test"
25131 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
25132 }
25133 }
25134 }
25135 }
25136
25139 basic_json patch(const basic_json& json_patch) const
25140 {
25141 basic_json result = *this;
25142 result.patch_inplace(json_patch);
25143 return result;
25144 }
25145
25148 JSON_HEDLEY_WARN_UNUSED_RESULT
25149 static basic_json diff(const basic_json& source, const basic_json& target,
25150 const string_t& path = "")
25151 {
25152 // the patch
25153 basic_json result(value_t::array);
25154
25155 // if the values are the same, return an empty patch
25156 if (source == target)
25157 {
25158 return result;
25159 }
25160
25161 if (source.type() != target.type())
25162 {
25163 // different types: replace value
25164 result.push_back(
25165 {
25166 {"op", "replace"}, {"path", path}, {"value", target}
25167 });
25168 return result;
25169 }
25170
25171 switch (source.type())
25172 {
25173 case value_t::array:
25174 {
25175 // first pass: traverse common elements
25176 std::size_t i = 0;
25177 while (i < source.size() && i < target.size())
25178 {
25179 // recursive call to compare array values at index i
25180 auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
25181 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25182 ++i;
25183 }
25184
25185 // We now reached the end of at least one array
25186 // in a second pass, traverse the remaining elements
25187
25188 // remove my remaining elements
25189 const auto end_index = static_cast<difference_type>(result.size());
25190 while (i < source.size())
25191 {
25192 // add operations in reverse order to avoid invalid
25193 // indices
25194 result.insert(result.begin() + end_index, object(
25195 {
25196 {"op", "remove"},
25197 {"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
25198 }));
25199 ++i;
25200 }
25201
25202 // add other remaining elements
25203 while (i < target.size())
25204 {
25205 result.push_back(
25206 {
25207 {"op", "add"},
25208 {"path", detail::concat<string_t>(path, "/-")},
25209 {"value", target[i]}
25210 });
25211 ++i;
25212 }
25213
25214 break;
25215 }
25216
25217 case value_t::object:
25218 {
25219 // first pass: traverse this object's elements
25220 for (auto it = source.cbegin(); it != source.cend(); ++it)
25221 {
25222 // escape the key name to be used in a JSON patch
25223 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25224
25225 if (target.find(it.key()) != target.end())
25226 {
25227 // recursive call to compare object values at key it
25228 auto temp_diff = diff(it.value(), target[it.key()], path_key);
25229 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25230 }
25231 else
25232 {
25233 // found a key that is not in o -> remove it
25234 result.push_back(object(
25235 {
25236 {"op", "remove"}, {"path", path_key}
25237 }));
25238 }
25239 }
25240
25241 // second pass: traverse other object's elements
25242 for (auto it = target.cbegin(); it != target.cend(); ++it)
25243 {
25244 if (source.find(it.key()) == source.end())
25245 {
25246 // found a key that is not in this -> add it
25247 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25248 result.push_back(
25249 {
25250 {"op", "add"}, {"path", path_key},
25251 {"value", it.value()}
25252 });
25253 }
25254 }
25255
25256 break;
25257 }
25258
25259 case value_t::null:
25260 case value_t::string:
25261 case value_t::boolean:
25262 case value_t::number_integer:
25263 case value_t::number_unsigned:
25264 case value_t::number_float:
25265 case value_t::binary:
25266 case value_t::discarded:
25267 default:
25268 {
25269 // both primitive types: replace value
25270 result.push_back(
25271 {
25272 {"op", "replace"}, {"path", path}, {"value", target}
25273 });
25274 break;
25275 }
25276 }
25277
25278 return result;
25279 }
25281
25283 // JSON Merge Patch functions //
25285
25288
25291 void merge_patch(const basic_json& apply_patch)
25292 {
25293 if (apply_patch.is_object())
25294 {
25295 if (!is_object())
25296 {
25297 *this = object();
25298 }
25299 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
25300 {
25301 if (it.value().is_null())
25302 {
25303 erase(it.key());
25304 }
25305 else
25306 {
25307 operator[](it.key()).merge_patch(it.value());
25308 }
25309 }
25310 }
25311 else
25312 {
25313 *this = apply_patch;
25314 }
25315 }
25316
25318};
25319
25322NLOHMANN_BASIC_JSON_TPL_DECLARATION
25323std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
25324{
25325 return j.dump();
25326}
25327
25328inline namespace literals
25329{
25330inline namespace json_literals
25331{
25332
25335JSON_HEDLEY_NON_NULL(1)
25336#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25337 inline nlohmann::json operator ""_json(const char* s, std::size_t n)
25338#else
25339 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
25340#endif
25341{
25342 return nlohmann::json::parse(s, s + n);
25343}
25344
25347JSON_HEDLEY_NON_NULL(1)
25348#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25349 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
25350#else
25351 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
25352#endif
25353{
25354 return nlohmann::json::json_pointer(std::string(s, n));
25355}
25356
25357} // namespace json_literals
25358} // namespace literals
25359NLOHMANN_JSON_NAMESPACE_END
25360
25362// nonmember support //
25364
25365namespace std // NOLINT(cert-dcl58-cpp)
25366{
25367
25370NLOHMANN_BASIC_JSON_TPL_DECLARATION
25371struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
25372{
25373 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
25374 {
25375 return nlohmann::detail::hash(j);
25376 }
25377};
25378
25379// specialization for std::less<value_t>
25380template<>
25381struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
25382{
25387 bool operator()(::nlohmann::detail::value_t lhs,
25388 ::nlohmann::detail::value_t rhs) const noexcept
25389 {
25390#if JSON_HAS_THREE_WAY_COMPARISON
25391 return std::is_lt(lhs <=> rhs); // *NOPAD*
25392#else
25393 return ::nlohmann::detail::operator<(lhs, rhs);
25394#endif
25395 }
25396};
25397
25398// C++20 prohibit function specialization in the std namespace.
25399#ifndef JSON_HAS_CPP_20
25400
25403NLOHMANN_BASIC_JSON_TPL_DECLARATION
25404inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
25405 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
25406 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
25407{
25408 j1.swap(j2);
25409}
25410
25411#endif
25412
25413} // namespace std
25414
25415#if JSON_USE_GLOBAL_UDLS
25416 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25417 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25418 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25419 #else
25420 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25421 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25422 #endif
25423#endif
25424
25425// #include <nlohmann/detail/macro_unscope.hpp>
25426// __ _____ _____ _____
25427// __| | __| | | | JSON for Modern C++
25428// | | |__ | | | | | | version 3.12.0
25429// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25430//
25431// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25432// SPDX-License-Identifier: MIT
25433
25434
25435
25436// restore clang diagnostic settings
25437#if defined(__clang__)
25438 #pragma clang diagnostic pop
25439#endif
25440
25441// clean up
25442#undef JSON_ASSERT
25443#undef JSON_INTERNAL_CATCH
25444#undef JSON_THROW
25445#undef JSON_PRIVATE_UNLESS_TESTED
25446#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
25447#undef NLOHMANN_BASIC_JSON_TPL
25448#undef JSON_EXPLICIT
25449#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
25450#undef JSON_INLINE_VARIABLE
25451#undef JSON_NO_UNIQUE_ADDRESS
25452#undef JSON_DISABLE_ENUM_SERIALIZATION
25453#undef JSON_USE_GLOBAL_UDLS
25454
25455#ifndef JSON_TEST_KEEP_MACROS
25456 #undef JSON_CATCH
25457 #undef JSON_TRY
25458 #undef JSON_HAS_CPP_11
25459 #undef JSON_HAS_CPP_14
25460 #undef JSON_HAS_CPP_17
25461 #undef JSON_HAS_CPP_20
25462 #undef JSON_HAS_CPP_23
25463 #undef JSON_HAS_CPP_26
25464 #undef JSON_HAS_FILESYSTEM
25465 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
25466 #undef JSON_HAS_THREE_WAY_COMPARISON
25467 #undef JSON_HAS_RANGES
25468 #undef JSON_HAS_STATIC_RTTI
25469 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
25470#endif
25471
25472// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
25473// __ _____ _____ _____
25474// __| | __| | | | JSON for Modern C++
25475// | | |__ | | | | | | version 3.12.0
25476// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25477//
25478// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25479// SPDX-License-Identifier: MIT
25480
25481
25482
25483#undef JSON_HEDLEY_ALWAYS_INLINE
25484#undef JSON_HEDLEY_ARM_VERSION
25485#undef JSON_HEDLEY_ARM_VERSION_CHECK
25486#undef JSON_HEDLEY_ARRAY_PARAM
25487#undef JSON_HEDLEY_ASSUME
25488#undef JSON_HEDLEY_BEGIN_C_DECLS
25489#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
25490#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
25491#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
25492#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
25493#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
25494#undef JSON_HEDLEY_CLANG_HAS_FEATURE
25495#undef JSON_HEDLEY_CLANG_HAS_WARNING
25496#undef JSON_HEDLEY_COMPCERT_VERSION
25497#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
25498#undef JSON_HEDLEY_CONCAT
25499#undef JSON_HEDLEY_CONCAT3
25500#undef JSON_HEDLEY_CONCAT3_EX
25501#undef JSON_HEDLEY_CONCAT_EX
25502#undef JSON_HEDLEY_CONST
25503#undef JSON_HEDLEY_CONSTEXPR
25504#undef JSON_HEDLEY_CONST_CAST
25505#undef JSON_HEDLEY_CPP_CAST
25506#undef JSON_HEDLEY_CRAY_VERSION
25507#undef JSON_HEDLEY_CRAY_VERSION_CHECK
25508#undef JSON_HEDLEY_C_DECL
25509#undef JSON_HEDLEY_DEPRECATED
25510#undef JSON_HEDLEY_DEPRECATED_FOR
25511#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
25512#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
25513#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
25514#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
25515#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
25516#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
25517#undef JSON_HEDLEY_DIAGNOSTIC_POP
25518#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
25519#undef JSON_HEDLEY_DMC_VERSION
25520#undef JSON_HEDLEY_DMC_VERSION_CHECK
25521#undef JSON_HEDLEY_EMPTY_BASES
25522#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
25523#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
25524#undef JSON_HEDLEY_END_C_DECLS
25525#undef JSON_HEDLEY_FLAGS
25526#undef JSON_HEDLEY_FLAGS_CAST
25527#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
25528#undef JSON_HEDLEY_GCC_HAS_BUILTIN
25529#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
25530#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
25531#undef JSON_HEDLEY_GCC_HAS_EXTENSION
25532#undef JSON_HEDLEY_GCC_HAS_FEATURE
25533#undef JSON_HEDLEY_GCC_HAS_WARNING
25534#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
25535#undef JSON_HEDLEY_GCC_VERSION
25536#undef JSON_HEDLEY_GCC_VERSION_CHECK
25537#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
25538#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
25539#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
25540#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
25541#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
25542#undef JSON_HEDLEY_GNUC_HAS_FEATURE
25543#undef JSON_HEDLEY_GNUC_HAS_WARNING
25544#undef JSON_HEDLEY_GNUC_VERSION
25545#undef JSON_HEDLEY_GNUC_VERSION_CHECK
25546#undef JSON_HEDLEY_HAS_ATTRIBUTE
25547#undef JSON_HEDLEY_HAS_BUILTIN
25548#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
25549#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
25550#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
25551#undef JSON_HEDLEY_HAS_EXTENSION
25552#undef JSON_HEDLEY_HAS_FEATURE
25553#undef JSON_HEDLEY_HAS_WARNING
25554#undef JSON_HEDLEY_IAR_VERSION
25555#undef JSON_HEDLEY_IAR_VERSION_CHECK
25556#undef JSON_HEDLEY_IBM_VERSION
25557#undef JSON_HEDLEY_IBM_VERSION_CHECK
25558#undef JSON_HEDLEY_IMPORT
25559#undef JSON_HEDLEY_INLINE
25560#undef JSON_HEDLEY_INTEL_CL_VERSION
25561#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
25562#undef JSON_HEDLEY_INTEL_VERSION
25563#undef JSON_HEDLEY_INTEL_VERSION_CHECK
25564#undef JSON_HEDLEY_IS_CONSTANT
25565#undef JSON_HEDLEY_IS_CONSTEXPR_
25566#undef JSON_HEDLEY_LIKELY
25567#undef JSON_HEDLEY_MALLOC
25568#undef JSON_HEDLEY_MCST_LCC_VERSION
25569#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
25570#undef JSON_HEDLEY_MESSAGE
25571#undef JSON_HEDLEY_MSVC_VERSION
25572#undef JSON_HEDLEY_MSVC_VERSION_CHECK
25573#undef JSON_HEDLEY_NEVER_INLINE
25574#undef JSON_HEDLEY_NON_NULL
25575#undef JSON_HEDLEY_NO_ESCAPE
25576#undef JSON_HEDLEY_NO_RETURN
25577#undef JSON_HEDLEY_NO_THROW
25578#undef JSON_HEDLEY_NULL
25579#undef JSON_HEDLEY_PELLES_VERSION
25580#undef JSON_HEDLEY_PELLES_VERSION_CHECK
25581#undef JSON_HEDLEY_PGI_VERSION
25582#undef JSON_HEDLEY_PGI_VERSION_CHECK
25583#undef JSON_HEDLEY_PREDICT
25584#undef JSON_HEDLEY_PRINTF_FORMAT
25585#undef JSON_HEDLEY_PRIVATE
25586#undef JSON_HEDLEY_PUBLIC
25587#undef JSON_HEDLEY_PURE
25588#undef JSON_HEDLEY_REINTERPRET_CAST
25589#undef JSON_HEDLEY_REQUIRE
25590#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
25591#undef JSON_HEDLEY_REQUIRE_MSG
25592#undef JSON_HEDLEY_RESTRICT
25593#undef JSON_HEDLEY_RETURNS_NON_NULL
25594#undef JSON_HEDLEY_SENTINEL
25595#undef JSON_HEDLEY_STATIC_ASSERT
25596#undef JSON_HEDLEY_STATIC_CAST
25597#undef JSON_HEDLEY_STRINGIFY
25598#undef JSON_HEDLEY_STRINGIFY_EX
25599#undef JSON_HEDLEY_SUNPRO_VERSION
25600#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
25601#undef JSON_HEDLEY_TINYC_VERSION
25602#undef JSON_HEDLEY_TINYC_VERSION_CHECK
25603#undef JSON_HEDLEY_TI_ARMCL_VERSION
25604#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
25605#undef JSON_HEDLEY_TI_CL2000_VERSION
25606#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
25607#undef JSON_HEDLEY_TI_CL430_VERSION
25608#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
25609#undef JSON_HEDLEY_TI_CL6X_VERSION
25610#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
25611#undef JSON_HEDLEY_TI_CL7X_VERSION
25612#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
25613#undef JSON_HEDLEY_TI_CLPRU_VERSION
25614#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
25615#undef JSON_HEDLEY_TI_VERSION
25616#undef JSON_HEDLEY_TI_VERSION_CHECK
25617#undef JSON_HEDLEY_UNAVAILABLE
25618#undef JSON_HEDLEY_UNLIKELY
25619#undef JSON_HEDLEY_UNPREDICTABLE
25620#undef JSON_HEDLEY_UNREACHABLE
25621#undef JSON_HEDLEY_UNREACHABLE_RETURN
25622#undef JSON_HEDLEY_VERSION
25623#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
25624#undef JSON_HEDLEY_VERSION_DECODE_MINOR
25625#undef JSON_HEDLEY_VERSION_DECODE_REVISION
25626#undef JSON_HEDLEY_VERSION_ENCODE
25627#undef JSON_HEDLEY_WARNING
25628#undef JSON_HEDLEY_WARN_UNUSED_RESULT
25629#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
25630#undef JSON_HEDLEY_FALL_THROUGH
25631
25632
25633
25634#endif // INCLUDE_NLOHMANN_JSON_HPP_
namespace for Niels Lohmann
Definition json.hpp:20208
constexpr bool is_string() const noexcept
return whether value is a string
Definition json.hpp:21507
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:22742
reference operator[](KeyType &&key)
access specified object element
Definition json.hpp:22308
size_type size() const noexcept
returns the number of elements
Definition json.hpp:23083
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:24547
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:21880
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22940
reference back()
access the last element
Definition json.hpp:22546
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:20947
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22956
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition json.hpp:25139
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
Definition json.hpp:24306
const_reference front() const
access the first element
Definition json.hpp:22539
constexpr bool is_array() const noexcept
return whether value is an array
Definition json.hpp:21500
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:23601
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22489
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22859
iter_impl< const basic_json > const_iterator
a const iterator for a basic_json container
Definition json.hpp:20342
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition json.hpp:20286
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition json.hpp:21472
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition json.hpp:20346
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:24742
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24787
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition json.hpp:20337
std::size_t size_type
a type to represent container sizes
Definition json.hpp:20329
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.hpp:21444
const_reference operator[](KeyType &&key) const
access specified object element
Definition json.hpp:22332
void swap(binary_t &other)
exchanges the values
Definition json.hpp:23678
ReferenceType get_ref()
get a reference value (implicit)
Definition json.hpp:21970
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.hpp:23122
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:23547
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:21981
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:21521
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.hpp:23338
void push_back(basic_json &&val)
add an object to an array
Definition json.hpp:23226
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition json.hpp:22277
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:23028
const_reference back() const
access the last element
Definition json.hpp:22555
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:22637
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:23283
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:23618
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:24643
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:21089
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition json.hpp:23450
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:24727
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:20352
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
Definition json.hpp:20477
reference at(KeyType &&key)
access specified object element with bounds checking
Definition json.hpp:22140
iterator end() noexcept
returns an iterator to one past the last element
Definition json.hpp:22931
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:21479
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:23554
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition json.hpp:24506
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22963
void push_back(initializer_list_t init)
add an object to an object
Definition json.hpp:23322
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
Definition json.hpp:20914
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.hpp:21130
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:24442
iterator begin() noexcept
returns an iterator to the first element
Definition json.hpp:22906
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition json.hpp:22387
const_iterator cend() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22947
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:24697
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24829
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition json.hpp:21100
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:20935
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:24531
basic_json flatten() const
return flattened JSON value
Definition json.hpp:24843
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:24658
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition json.hpp:22753
const binary_t & get_binary() const
get a binary value
Definition json.hpp:22052
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition json.hpp:23470
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition json.hpp:24868
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22440
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24801
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition json.hpp:20453
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition json.hpp:22876
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:24412
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:24522
iterator find(const typename object_t::key_type &key)
find an element in a JSON object
Definition json.hpp:22789
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:21078
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:24476
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition json.hpp:22178
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.hpp:20360
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:21137
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition json.hpp:22803
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.hpp:24403
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:22567
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition json.hpp:23423
NumberFloatType number_float_t
a type for a number (floating-point)
Definition json.hpp:20473
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:22362
AllocatorType< basic_json > allocator_type
the allocator type
Definition json.hpp:20332
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition json.hpp:20335
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:21408
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.hpp:25291
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:21934
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:24488
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:22074
iterator find(KeyType &&key)
find an element in a JSON object
Definition json.hpp:22819
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition json.hpp:21486
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.hpp:22970
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:24449
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24815
BooleanType boolean_t
a type for a boolean
Definition json.hpp:20461
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:25149
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:20440
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:23314
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition json.hpp:22922
reference operator[](typename object_t::key_type key)
access specified object element
Definition json.hpp:22255
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:21692
~basic_json() noexcept
destructor
Definition json.hpp:21390
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition json.hpp:22991
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:21019
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.hpp:23694
binary_t & get_binary()
get a binary value
Definition json.hpp:22040
const_iterator begin() const noexcept
returns an iterator to the first element
Definition json.hpp:22915
constexpr bool is_number() const noexcept
return whether value is a number
Definition json.hpp:21465
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition json.hpp:23521
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:24589
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:21921
reference operator[](size_type idx)
access specified array element
Definition json.hpp:22196
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:21361
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:24468
NumberIntegerType number_integer_t
a type for a number (integer)
Definition json.hpp:20465
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:21681
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:22158
constexpr bool is_binary() const noexcept
return whether value is a binary array
Definition json.hpp:21514
void swap(object_t &other)
exchanges the values
Definition json.hpp:23646
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.hpp:24852
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition json.hpp:23501
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:24497
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:21111
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:23021
bool empty() const noexcept
checks whether the container is empty.
Definition json.hpp:23044
void swap(array_t &other)
exchanges the values
Definition json.hpp:23630
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:22760
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:23251
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.hpp:22883
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.hpp:21430
reference emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:23347
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22463
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.hpp:21122
StringType string_t
a type for a string
Definition json.hpp:20457
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:20449
void push_back(const basic_json &val)
add an object to an array
Definition json.hpp:23259
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:22413
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:22120
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:24712
json_value m_value
the value of the current element
Definition json.hpp:24344
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.hpp:22984
json_sax< basic_json > json_sax_t
SAX interface type, see nlohmann::json_sax
Definition json.hpp:20290
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition json.hpp:21458
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:22849
reference front()
access the first element
Definition json.hpp:22532
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:21437
constexpr bool is_null() const noexcept
return whether value is null
Definition json.hpp:21451
void clear() noexcept
clears the contents
Definition json.hpp:23165
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:24460
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:21335
iter_impl< basic_json > iterator
an iterator for a basic_json container
Definition json.hpp:20340
basic_json(const value_t v)
create an empty value with a given type
Definition json.hpp:20927
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:22242
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition json.hpp:20327
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition json.hpp:23443
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition json.hpp:22977
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition json.hpp:20469
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition json.hpp:24291
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:24426
void swap(string_t &other)
exchanges the values
Definition json.hpp:23662
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.hpp:20961
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition json.hpp:20344
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:22097
detail::actual_object_comparator_t< basic_json > object_comparator_t
object key comparator type
Definition json.hpp:20481
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:21262
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:23291
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:23372
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:24419
constexpr bool is_object() const noexcept
return whether value is an object
Definition json.hpp:21493
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:24435
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:24604
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition json.hpp:23404
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:21149
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition json.hpp:22867
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:24515
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition json.hpp:22835
::nlohmann::json_pointer< StringType > json_pointer
JSON Pointer, see nlohmann::json_pointer
Definition json.hpp:20276
an internal type for a backed binary type
Definition json.hpp:6244
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.hpp:6250
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6272
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6260
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.hpp:6299
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.hpp:6265
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.hpp:6306
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.hpp:6255
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.hpp:6291
void clear_subtype() noexcept
clears the binary subtype
Definition json.hpp:6313
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:9897
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.hpp:9913
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:9934
general exception of the basic_json class
Definition json.hpp:4545
const int id
the id of the exception
Definition json.hpp:4554
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:4548
exception indicating errors with iterators
Definition json.hpp:4714
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition json.hpp:13687
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:14270
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:13824
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:14215
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:13814
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:14157
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:14197
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:14261
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:14067
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:14370
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.hpp:14108
iter_impl operator++(int) &
post-increment (it++)
Definition json.hpp:14005
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:14224
reference operator[](difference_type n) const
access to successor
Definition json.hpp:14332
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition json.hpp:13717
pointer operator->() const
dereference the iterator
Definition json.hpp:13963
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
Definition json.hpp:14395
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:14303
std::bidirectional_iterator_tag iterator_category
Definition json.hpp:13712
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:14281
reference value() const
return the value of an iterator
Definition json.hpp:14386
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:14206
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:13721
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:14016
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition json.hpp:13715
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:13919
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:14292
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.hpp:13799
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition json.hpp:14148
iter_impl operator--(int) &
post-decrement (it–)
Definition json.hpp:14056
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:13726
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.hpp:13789
void set_end() noexcept
set the iterator past the last value
Definition json.hpp:13880
Definition json.hpp:5506
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.hpp:5571
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.hpp:5577
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:5554
const iteration_proxy_value & operator*() const
dereference operator (needed for range-based for)
Definition json.hpp:5548
IteratorType::reference value() const
return value of the iterator
Definition json.hpp:5619
const string_type & key() const
return key of the iterator
Definition json.hpp:5583
proxy class for the items() function
Definition json.hpp:5627
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.hpp:5652
iteration_proxy_value< IteratorType > begin() const noexcept
return iterator begin (needed for range-based for)
Definition json.hpp:5646
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:5636
Definition json.hpp:15600
a template for a reverse iterator class
Definition json.hpp:14449
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition json.hpp:14465
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition json.hpp:14477
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.hpp:14471
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.hpp:14489
reference operator[](difference_type n) const
access to successor
Definition json.hpp:14513
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.hpp:14519
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.hpp:14507
typename Base::reference reference
the reference type for the pointed-to element
Definition json.hpp:14455
reference value() const
return the value of an iterator
Definition json.hpp:14526
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.hpp:14462
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.hpp:14483
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.hpp:14453
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.hpp:14501
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.hpp:14458
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.hpp:14495
Definition json.hpp:9612
Definition json.hpp:9175
SAX implementation to create a JSON value from SAX events
Definition json.hpp:8869
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.hpp:8883
exception indicating other library errors
Definition json.hpp:4766
exception indicating access out of the defined range
Definition json.hpp:4749
exception indicating a parse error
Definition json.hpp:4661
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:4673
const std::size_t byte
byte index of the parse error
Definition json.hpp:4698
Definition json.hpp:18867
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:18882
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition json.hpp:19799
string_t indent_string
the indentation string
Definition json.hpp:19796
const char indent_char
the indentation character
Definition json.hpp:19794
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:18922
exception indicating executing a member function with a wrong type
Definition json.hpp:4732
JSON Pointer defines a string syntax for identifying a specific value within a JSON document
Definition json.hpp:14621
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:14716
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:14723
json_pointer(const string_t &s="")
create JSON pointer
Definition json.hpp:14647
bool empty() const noexcept
return whether pointer points to the root document
Definition json.hpp:14782
void pop_back()
remove last reference token
Definition json.hpp:14744
string_t to_string() const
return a string representation of the JSON pointer
Definition json.hpp:14653
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition json.hpp:14701
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14775
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition json.hpp:14683
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:14708
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition json.hpp:14730
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition json.hpp:14693
const string_t & back() const
return last reference token
Definition json.hpp:14756
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition json.hpp:14674
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14768
nlohmann::json json
nlohmann::json 타입을 json으로 별칭 정의
Definition config_manager.cpp:17
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:25404
bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15516
bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15541
basic_json< nlohmann::ordered_map > ordered_json
specialization that maintains the insertion order of object keys
Definition json.hpp:3568
basic_json<> json
default specialization
Definition json.hpp:3559
detail namespace with internal helper functions
Definition json.hpp:265
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.hpp:3106
bool little_endianness(int num=1) noexcept
determine system byte order
Definition json.hpp:9883
cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:9870
@ store
store tags as binary type
@ error
throw a parse_error exception in case of a tag
value_t
the JSON type enumeration
Definition json.hpp:3008
@ 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)
void unescape(StringType &s)
string unescaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3140
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:3037
error_handler_t
how to treat decoding errors
Definition json.hpp:18859
@ strict
throw a type_error exception in case of invalid UTF-8
@ replace
replace invalid UTF-8 sequences with U+FFFD
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3125
namespace for Niels Lohmann
Definition json.hpp:6186
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:6210
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:6200
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:6190
Definition json.hpp:3725
Definition json.hpp:3742
Definition json.hpp:3821
Definition json.hpp:297
Definition json.hpp:5737
Definition json.hpp:3664
Definition json.hpp:3720
Definition json.hpp:3689
Definition json.hpp:3704
Definition json.hpp:3258
an iterator value
Definition json.hpp:13620
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition json.hpp:13624
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition json.hpp:13626
Definition json.hpp:3613
Definition json.hpp:3600
Definition json.hpp:4342
Definition json.hpp:4138
Definition json.hpp:4021
Definition json.hpp:4092
Definition json.hpp:3942
Definition json.hpp:3979
Definition json.hpp:4095
Definition json.hpp:4108
Definition json.hpp:3915
Definition json.hpp:4065
Definition json.hpp:3975
Definition json.hpp:3986
Definition json.hpp:4111
Definition json.hpp:3853
Definition json.hpp:3834
Definition json.hpp:313
Definition json.hpp:3672
Definition json.hpp:3868
Definition json.hpp:4117
Definition json.hpp:3623
Definition json.hpp:4199
Definition json.hpp:4195
Definition json.hpp:3887
Definition json.hpp:9802
Definition json.hpp:9771
Definition json.hpp:4128
Definition json.hpp:4364
Definition json.hpp:3428
Definition json.hpp:3409
Default base class of the basic_json class.
Definition json.hpp:14568
Definition json.hpp:268
Definition json.hpp:3828
Definition json.hpp:283
struct to capture the start position of the current token
Definition json.hpp:3171
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:3175
std::size_t lines_read
the number of lines read
Definition json.hpp:3177
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:3173
Definition json.hpp:3341
Definition json.hpp:3347
Definition json.hpp:6153
Definition json.hpp:3278
Definition json.hpp:3297
Definition json.hpp:4290
Definition json.hpp:4244
SAX interface
Definition json.hpp:8734
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
virtual bool end_array()=0
the end of an array was read
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
virtual bool null()=0
a null value was read
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
a minimal map-like container that preserves insertion order
Definition json.hpp:19841
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:25387