Timer Console
Loading...
Searching...
No Matches
json.hpp
Go to the documentation of this file.
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.11.3
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9/****************************************************************************\
10 * Note on documentation: The source files contain links to the online *
11 * documentation of the public API at https://json.nlohmann.me. This URL *
12 * contains the most recent documentation and should also be applicable to *
13 * previous versions; documentation for deprecated functions is not *
14 * removed, but marked deprecated. See "Generate documentation" section in *
15 * file docs/README.md. *
16\****************************************************************************/
17
18#ifndef INCLUDE_NLOHMANN_JSON_HPP_
19#define INCLUDE_NLOHMANN_JSON_HPP_
20
21#include <algorithm> // all_of, find, for_each
22#include <cstddef> // nullptr_t, ptrdiff_t, size_t
23#include <functional> // hash, less
24#include <initializer_list> // initializer_list
25#ifndef JSON_NO_IO
26 #include <iosfwd> // istream, ostream
27#endif // JSON_NO_IO
28#include <iterator> // random_access_iterator_tag
29#include <memory> // unique_ptr
30#include <string> // string, stoi, to_string
31#include <utility> // declval, forward, move, pair, swap
32#include <vector> // vector
33
34// #include <nlohmann/adl_serializer.hpp>
35// __ _____ _____ _____
36// __| | __| | | | JSON for Modern C++
37// | | |__ | | | | | | version 3.11.3
38// |_____|_____|_____|_|___| https://github.com/nlohmann/json
39//
40// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
41// SPDX-License-Identifier: MIT
42
43
44
45#include <utility>
46
47// #include <nlohmann/detail/abi_macros.hpp>
48// __ _____ _____ _____
49// __| | __| | | | JSON for Modern C++
50// | | |__ | | | | | | version 3.11.3
51// |_____|_____|_____|_|___| https://github.com/nlohmann/json
52//
53// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
54// SPDX-License-Identifier: MIT
55
56
57
58// This file contains all macro definitions affecting or depending on the ABI
59
60#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
61 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
62 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3
63 #warning "Already included a different version of the library!"
64 #endif
65 #endif
66#endif
67
68#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
69#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
70#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum)
71
72#ifndef JSON_DIAGNOSTICS
73 #define JSON_DIAGNOSTICS 0
74#endif
75
76#ifndef JSON_DIAGNOSTIC_POSITIONS
77 #define JSON_DIAGNOSTIC_POSITIONS 0
78#endif
79
80#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
81 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
82#endif
83
84#if JSON_DIAGNOSTICS
85 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
86#else
87 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
88#endif
89
90#if JSON_DIAGNOSTIC_POSITIONS
91 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp
92#else
93 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS
94#endif
95
96#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
97 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
98#else
99 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
100#endif
101
102#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
103 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
104#endif
105
106// Construct the namespace ABI tags component
107#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c
108#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \
109 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c)
110
111#define NLOHMANN_JSON_ABI_TAGS \
112 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
113 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
114 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \
115 NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS)
116
117// Construct the namespace version component
118#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
119 _v ## major ## _ ## minor ## _ ## patch
120#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
121 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
122
123#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
124#define NLOHMANN_JSON_NAMESPACE_VERSION
125#else
126#define NLOHMANN_JSON_NAMESPACE_VERSION \
127 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
128 NLOHMANN_JSON_VERSION_MINOR, \
129 NLOHMANN_JSON_VERSION_PATCH)
130#endif
131
132// Combine namespace components
133#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
134#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
135 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
136
137#ifndef NLOHMANN_JSON_NAMESPACE
138#define NLOHMANN_JSON_NAMESPACE \
139 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
140 NLOHMANN_JSON_ABI_TAGS, \
141 NLOHMANN_JSON_NAMESPACE_VERSION)
142#endif
143
144#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
145#define NLOHMANN_JSON_NAMESPACE_BEGIN \
146 namespace nlohmann \
147 { \
148 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
149 NLOHMANN_JSON_ABI_TAGS, \
150 NLOHMANN_JSON_NAMESPACE_VERSION) \
151 {
152#endif
153
154#ifndef NLOHMANN_JSON_NAMESPACE_END
155#define NLOHMANN_JSON_NAMESPACE_END \
156 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
157 } // namespace nlohmann
158#endif
159
160// #include <nlohmann/detail/conversions/from_json.hpp>
161// __ _____ _____ _____
162// __| | __| | | | JSON for Modern C++
163// | | |__ | | | | | | version 3.11.3
164// |_____|_____|_____|_|___| https://github.com/nlohmann/json
165//
166// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
167// SPDX-License-Identifier: MIT
168
169
170
171#include <algorithm> // transform
172#include <array> // array
173#include <forward_list> // forward_list
174#include <iterator> // inserter, front_inserter, end
175#include <map> // map
176#ifdef JSON_HAS_CPP_17
177 #include <optional> // optional
178#endif
179#include <string> // string
180#include <tuple> // tuple, make_tuple
181#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
182#include <unordered_map> // unordered_map
183#include <utility> // pair, declval
184#include <valarray> // valarray
185
186// #include <nlohmann/detail/exceptions.hpp>
187// __ _____ _____ _____
188// __| | __| | | | JSON for Modern C++
189// | | |__ | | | | | | version 3.11.3
190// |_____|_____|_____|_|___| https://github.com/nlohmann/json
191//
192// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
193// SPDX-License-Identifier: MIT
194
195
196
197#include <cstddef> // nullptr_t
198#include <exception> // exception
199#if JSON_DIAGNOSTICS
200 #include <numeric> // accumulate
201#endif
202#include <stdexcept> // runtime_error
203#include <string> // to_string
204#include <vector> // vector
205
206// #include <nlohmann/detail/value_t.hpp>
207// __ _____ _____ _____
208// __| | __| | | | JSON for Modern C++
209// | | |__ | | | | | | version 3.11.3
210// |_____|_____|_____|_|___| https://github.com/nlohmann/json
211//
212// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
213// SPDX-License-Identifier: MIT
214
215
216
217#include <array> // array
218#include <cstddef> // size_t
219#include <cstdint> // uint8_t
220#include <string> // string
221
222// #include <nlohmann/detail/macro_scope.hpp>
223// __ _____ _____ _____
224// __| | __| | | | JSON for Modern C++
225// | | |__ | | | | | | version 3.11.3
226// |_____|_____|_____|_|___| https://github.com/nlohmann/json
227//
228// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
229// SPDX-License-Identifier: MIT
230
231
232
233#include <utility> // declval, pair
234// #include <nlohmann/detail/meta/detected.hpp>
235// __ _____ _____ _____
236// __| | __| | | | JSON for Modern C++
237// | | |__ | | | | | | version 3.11.3
238// |_____|_____|_____|_|___| https://github.com/nlohmann/json
239//
240// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
241// SPDX-License-Identifier: MIT
242
243
244
245#include <type_traits>
246
247// #include <nlohmann/detail/meta/void_t.hpp>
248// __ _____ _____ _____
249// __| | __| | | | JSON for Modern C++
250// | | |__ | | | | | | version 3.11.3
251// |_____|_____|_____|_|___| https://github.com/nlohmann/json
252//
253// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
254// SPDX-License-Identifier: MIT
255
256
257
258// #include <nlohmann/detail/abi_macros.hpp>
259
260
262namespace detail
263{
264
265template<typename ...Ts> struct make_void
266{
267 using type = void;
268};
269template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
270
271} // namespace detail
273
274
276namespace detail
277{
278
279// https://en.cppreference.com/w/cpp/experimental/is_detected
281{
282 nonesuch() = delete;
283 ~nonesuch() = delete;
284 nonesuch(nonesuch const&) = delete;
285 nonesuch(nonesuch const&&) = delete;
286 void operator=(nonesuch const&) = delete;
287 void operator=(nonesuch&&) = delete;
288};
289
290template<class Default,
291 class AlwaysVoid,
292 template<class...> class Op,
293 class... Args>
295{
296 using value_t = std::false_type;
297 using type = Default;
298};
299
300template<class Default, template<class...> class Op, class... Args>
301struct detector<Default, void_t<Op<Args...>>, Op, Args...>
302{
303 using value_t = std::true_type;
304 using type = Op<Args...>;
305};
306
307template<template<class...> class Op, class... Args>
308using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
309
310template<template<class...> class Op, class... Args>
311struct is_detected_lazy : is_detected<Op, Args...> { };
312
313template<template<class...> class Op, class... Args>
314using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
315
316template<class Default, template<class...> class Op, class... Args>
317using detected_or = detector<Default, void, Op, Args...>;
318
319template<class Default, template<class...> class Op, class... Args>
320using detected_or_t = typename detected_or<Default, Op, Args...>::type;
321
322template<class Expected, template<class...> class Op, class... Args>
323using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
324
325template<class To, template<class...> class Op, class... Args>
327 std::is_convertible<detected_t<Op, Args...>, To>;
328
329} // namespace detail
331
332// #include <nlohmann/thirdparty/hedley/hedley.hpp>
333
334
335// __ _____ _____ _____
336// __| | __| | | | JSON for Modern C++
337// | | |__ | | | | | | version 3.11.3
338// |_____|_____|_____|_|___| https://github.com/nlohmann/json
339//
340// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
341// SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson <evan@nemerson.com>
342// SPDX-License-Identifier: MIT
343
344/* Hedley - https://nemequ.github.io/hedley
345 * Created by Evan Nemerson <evan@nemerson.com>
346 */
347
348#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
349#if defined(JSON_HEDLEY_VERSION)
350 #undef JSON_HEDLEY_VERSION
351#endif
352#define JSON_HEDLEY_VERSION 15
353
354#if defined(JSON_HEDLEY_STRINGIFY_EX)
355 #undef JSON_HEDLEY_STRINGIFY_EX
356#endif
357#define JSON_HEDLEY_STRINGIFY_EX(x) #x
358
359#if defined(JSON_HEDLEY_STRINGIFY)
360 #undef JSON_HEDLEY_STRINGIFY
361#endif
362#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
363
364#if defined(JSON_HEDLEY_CONCAT_EX)
365 #undef JSON_HEDLEY_CONCAT_EX
366#endif
367#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
368
369#if defined(JSON_HEDLEY_CONCAT)
370 #undef JSON_HEDLEY_CONCAT
371#endif
372#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
373
374#if defined(JSON_HEDLEY_CONCAT3_EX)
375 #undef JSON_HEDLEY_CONCAT3_EX
376#endif
377#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
378
379#if defined(JSON_HEDLEY_CONCAT3)
380 #undef JSON_HEDLEY_CONCAT3
381#endif
382#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
383
384#if defined(JSON_HEDLEY_VERSION_ENCODE)
385 #undef JSON_HEDLEY_VERSION_ENCODE
386#endif
387#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
388
389#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
390 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
391#endif
392#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
393
394#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
395 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
396#endif
397#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
398
399#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
400 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
401#endif
402#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
403
404#if defined(JSON_HEDLEY_GNUC_VERSION)
405 #undef JSON_HEDLEY_GNUC_VERSION
406#endif
407#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
408 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
409#elif defined(__GNUC__)
410 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
411#endif
412
413#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
414 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
415#endif
416#if defined(JSON_HEDLEY_GNUC_VERSION)
417 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
418#else
419 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
420#endif
421
422#if defined(JSON_HEDLEY_MSVC_VERSION)
423 #undef JSON_HEDLEY_MSVC_VERSION
424#endif
425#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
426 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
427#elif defined(_MSC_FULL_VER) && !defined(__ICL)
428 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
429#elif defined(_MSC_VER) && !defined(__ICL)
430 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
431#endif
432
433#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
434 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
435#endif
436#if !defined(JSON_HEDLEY_MSVC_VERSION)
437 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
438#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
439 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
440#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
441 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
442#else
443 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
444#endif
445
446#if defined(JSON_HEDLEY_INTEL_VERSION)
447 #undef JSON_HEDLEY_INTEL_VERSION
448#endif
449#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
450 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
451#elif defined(__INTEL_COMPILER) && !defined(__ICL)
452 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
453#endif
454
455#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
456 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
457#endif
458#if defined(JSON_HEDLEY_INTEL_VERSION)
459 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
460#else
461 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
462#endif
463
464#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
465 #undef JSON_HEDLEY_INTEL_CL_VERSION
466#endif
467#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
468 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
469#endif
470
471#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
472 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
473#endif
474#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
475 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
476#else
477 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
478#endif
479
480#if defined(JSON_HEDLEY_PGI_VERSION)
481 #undef JSON_HEDLEY_PGI_VERSION
482#endif
483#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
484 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
485#endif
486
487#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
488 #undef JSON_HEDLEY_PGI_VERSION_CHECK
489#endif
490#if defined(JSON_HEDLEY_PGI_VERSION)
491 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
492#else
493 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
494#endif
495
496#if defined(JSON_HEDLEY_SUNPRO_VERSION)
497 #undef JSON_HEDLEY_SUNPRO_VERSION
498#endif
499#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
500 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
501#elif defined(__SUNPRO_C)
502 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
503#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
504 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
505#elif defined(__SUNPRO_CC)
506 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
507#endif
508
509#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
510 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
511#endif
512#if defined(JSON_HEDLEY_SUNPRO_VERSION)
513 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
514#else
515 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
516#endif
517
518#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
519 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
520#endif
521#if defined(__EMSCRIPTEN__)
522 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
523#endif
524
525#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
526 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
527#endif
528#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
529 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
530#else
531 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
532#endif
533
534#if defined(JSON_HEDLEY_ARM_VERSION)
535 #undef JSON_HEDLEY_ARM_VERSION
536#endif
537#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
538 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
539#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
540 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
541#endif
542
543#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
544 #undef JSON_HEDLEY_ARM_VERSION_CHECK
545#endif
546#if defined(JSON_HEDLEY_ARM_VERSION)
547 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
548#else
549 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
550#endif
551
552#if defined(JSON_HEDLEY_IBM_VERSION)
553 #undef JSON_HEDLEY_IBM_VERSION
554#endif
555#if defined(__ibmxl__)
556 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
557#elif defined(__xlC__) && defined(__xlC_ver__)
558 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
559#elif defined(__xlC__)
560 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
561#endif
562
563#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
564 #undef JSON_HEDLEY_IBM_VERSION_CHECK
565#endif
566#if defined(JSON_HEDLEY_IBM_VERSION)
567 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
568#else
569 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
570#endif
571
572#if defined(JSON_HEDLEY_TI_VERSION)
573 #undef JSON_HEDLEY_TI_VERSION
574#endif
575#if \
576 defined(__TI_COMPILER_VERSION__) && \
577 ( \
578 defined(__TMS470__) || defined(__TI_ARM__) || \
579 defined(__MSP430__) || \
580 defined(__TMS320C2000__) \
581 )
582#if (__TI_COMPILER_VERSION__ >= 16000000)
583 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
584#endif
585#endif
586
587#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
588 #undef JSON_HEDLEY_TI_VERSION_CHECK
589#endif
590#if defined(JSON_HEDLEY_TI_VERSION)
591 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
592#else
593 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
594#endif
595
596#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
597 #undef JSON_HEDLEY_TI_CL2000_VERSION
598#endif
599#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
600 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
601#endif
602
603#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
604 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
605#endif
606#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
607 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
608#else
609 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
610#endif
611
612#if defined(JSON_HEDLEY_TI_CL430_VERSION)
613 #undef JSON_HEDLEY_TI_CL430_VERSION
614#endif
615#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
616 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
617#endif
618
619#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
620 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
621#endif
622#if defined(JSON_HEDLEY_TI_CL430_VERSION)
623 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
624#else
625 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
626#endif
627
628#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
629 #undef JSON_HEDLEY_TI_ARMCL_VERSION
630#endif
631#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
632 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
633#endif
634
635#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
636 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
637#endif
638#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
639 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
640#else
641 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
642#endif
643
644#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
645 #undef JSON_HEDLEY_TI_CL6X_VERSION
646#endif
647#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
648 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
649#endif
650
651#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
652 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
653#endif
654#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
655 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
656#else
657 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
658#endif
659
660#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
661 #undef JSON_HEDLEY_TI_CL7X_VERSION
662#endif
663#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
664 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
665#endif
666
667#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
668 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
669#endif
670#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
671 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
672#else
673 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
674#endif
675
676#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
677 #undef JSON_HEDLEY_TI_CLPRU_VERSION
678#endif
679#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
680 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
681#endif
682
683#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
684 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
685#endif
686#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
687 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
688#else
689 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
690#endif
691
692#if defined(JSON_HEDLEY_CRAY_VERSION)
693 #undef JSON_HEDLEY_CRAY_VERSION
694#endif
695#if defined(_CRAYC)
696 #if defined(_RELEASE_PATCHLEVEL)
697 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
698 #else
699 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
700 #endif
701#endif
702
703#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
704 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
705#endif
706#if defined(JSON_HEDLEY_CRAY_VERSION)
707 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
708#else
709 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
710#endif
711
712#if defined(JSON_HEDLEY_IAR_VERSION)
713 #undef JSON_HEDLEY_IAR_VERSION
714#endif
715#if defined(__IAR_SYSTEMS_ICC__)
716 #if __VER__ > 1000
717 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
718 #else
719 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
720 #endif
721#endif
722
723#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
724 #undef JSON_HEDLEY_IAR_VERSION_CHECK
725#endif
726#if defined(JSON_HEDLEY_IAR_VERSION)
727 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
728#else
729 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
730#endif
731
732#if defined(JSON_HEDLEY_TINYC_VERSION)
733 #undef JSON_HEDLEY_TINYC_VERSION
734#endif
735#if defined(__TINYC__)
736 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
737#endif
738
739#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
740 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
741#endif
742#if defined(JSON_HEDLEY_TINYC_VERSION)
743 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
744#else
745 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
746#endif
747
748#if defined(JSON_HEDLEY_DMC_VERSION)
749 #undef JSON_HEDLEY_DMC_VERSION
750#endif
751#if defined(__DMC__)
752 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
753#endif
754
755#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
756 #undef JSON_HEDLEY_DMC_VERSION_CHECK
757#endif
758#if defined(JSON_HEDLEY_DMC_VERSION)
759 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
760#else
761 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
762#endif
763
764#if defined(JSON_HEDLEY_COMPCERT_VERSION)
765 #undef JSON_HEDLEY_COMPCERT_VERSION
766#endif
767#if defined(__COMPCERT_VERSION__)
768 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
769#endif
770
771#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
772 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
773#endif
774#if defined(JSON_HEDLEY_COMPCERT_VERSION)
775 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
776#else
777 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
778#endif
779
780#if defined(JSON_HEDLEY_PELLES_VERSION)
781 #undef JSON_HEDLEY_PELLES_VERSION
782#endif
783#if defined(__POCC__)
784 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
785#endif
786
787#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
788 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
789#endif
790#if defined(JSON_HEDLEY_PELLES_VERSION)
791 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
792#else
793 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
794#endif
795
796#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
797 #undef JSON_HEDLEY_MCST_LCC_VERSION
798#endif
799#if defined(__LCC__) && defined(__LCC_MINOR__)
800 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
801#endif
802
803#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
804 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
805#endif
806#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
807 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
808#else
809 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
810#endif
811
812#if defined(JSON_HEDLEY_GCC_VERSION)
813 #undef JSON_HEDLEY_GCC_VERSION
814#endif
815#if \
816 defined(JSON_HEDLEY_GNUC_VERSION) && \
817 !defined(__clang__) && \
818 !defined(JSON_HEDLEY_INTEL_VERSION) && \
819 !defined(JSON_HEDLEY_PGI_VERSION) && \
820 !defined(JSON_HEDLEY_ARM_VERSION) && \
821 !defined(JSON_HEDLEY_CRAY_VERSION) && \
822 !defined(JSON_HEDLEY_TI_VERSION) && \
823 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
824 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
825 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
826 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
827 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
828 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
829 !defined(__COMPCERT__) && \
830 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
831 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
832#endif
833
834#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
835 #undef JSON_HEDLEY_GCC_VERSION_CHECK
836#endif
837#if defined(JSON_HEDLEY_GCC_VERSION)
838 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
839#else
840 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
841#endif
842
843#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
844 #undef JSON_HEDLEY_HAS_ATTRIBUTE
845#endif
846#if \
847 defined(__has_attribute) && \
848 ( \
849 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
850 )
851# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
852#else
853# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
854#endif
855
856#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
857 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
858#endif
859#if defined(__has_attribute)
860 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
861#else
862 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
863#endif
864
865#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
866 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
867#endif
868#if defined(__has_attribute)
869 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
870#else
871 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
872#endif
873
874#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
875 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
876#endif
877#if \
878 defined(__has_cpp_attribute) && \
879 defined(__cplusplus) && \
880 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
881 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
882#else
883 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
884#endif
885
886#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
887 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
888#endif
889#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
890 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
891#elif \
892 !defined(JSON_HEDLEY_PGI_VERSION) && \
893 !defined(JSON_HEDLEY_IAR_VERSION) && \
894 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
895 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
896 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
897#else
898 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
899#endif
900
901#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
902 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
903#endif
904#if defined(__has_cpp_attribute) && defined(__cplusplus)
905 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
906#else
907 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
908#endif
909
910#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
911 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
912#endif
913#if defined(__has_cpp_attribute) && defined(__cplusplus)
914 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
915#else
916 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
917#endif
918
919#if defined(JSON_HEDLEY_HAS_BUILTIN)
920 #undef JSON_HEDLEY_HAS_BUILTIN
921#endif
922#if defined(__has_builtin)
923 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
924#else
925 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
926#endif
927
928#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
929 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
930#endif
931#if defined(__has_builtin)
932 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
933#else
934 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
935#endif
936
937#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
938 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
939#endif
940#if defined(__has_builtin)
941 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
942#else
943 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
944#endif
945
946#if defined(JSON_HEDLEY_HAS_FEATURE)
947 #undef JSON_HEDLEY_HAS_FEATURE
948#endif
949#if defined(__has_feature)
950 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
951#else
952 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
953#endif
954
955#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
956 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
957#endif
958#if defined(__has_feature)
959 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
960#else
961 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
962#endif
963
964#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
965 #undef JSON_HEDLEY_GCC_HAS_FEATURE
966#endif
967#if defined(__has_feature)
968 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
969#else
970 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
971#endif
972
973#if defined(JSON_HEDLEY_HAS_EXTENSION)
974 #undef JSON_HEDLEY_HAS_EXTENSION
975#endif
976#if defined(__has_extension)
977 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
978#else
979 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
980#endif
981
982#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
983 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
984#endif
985#if defined(__has_extension)
986 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
987#else
988 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
989#endif
990
991#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
992 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
993#endif
994#if defined(__has_extension)
995 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
996#else
997 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
998#endif
999
1000#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
1001 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
1002#endif
1003#if defined(__has_declspec_attribute)
1004 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
1005#else
1006 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
1007#endif
1008
1009#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1010 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1011#endif
1012#if defined(__has_declspec_attribute)
1013 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1014#else
1015 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1016#endif
1017
1018#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1019 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1020#endif
1021#if defined(__has_declspec_attribute)
1022 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1023#else
1024 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1025#endif
1026
1027#if defined(JSON_HEDLEY_HAS_WARNING)
1028 #undef JSON_HEDLEY_HAS_WARNING
1029#endif
1030#if defined(__has_warning)
1031 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1032#else
1033 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1034#endif
1035
1036#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1037 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1038#endif
1039#if defined(__has_warning)
1040 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1041#else
1042 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1043#endif
1044
1045#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1046 #undef JSON_HEDLEY_GCC_HAS_WARNING
1047#endif
1048#if defined(__has_warning)
1049 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1050#else
1051 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1052#endif
1053
1054#if \
1055 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1056 defined(__clang__) || \
1057 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1058 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1059 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1060 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1061 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1062 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1063 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1064 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1065 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1066 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1067 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1068 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1069 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1070 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1071 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1072 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1073 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1074#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1075 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1076#else
1077 #define JSON_HEDLEY_PRAGMA(value)
1078#endif
1079
1080#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1081 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1082#endif
1083#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1084 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1085#endif
1086#if defined(__clang__)
1087 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1088 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1089#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1090 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1091 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1092#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1093 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1094 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1095#elif \
1096 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1097 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1098 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1099 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1100#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1101 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1102 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1103#elif \
1104 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1105 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1106 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1107 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1108 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1109 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1110 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1111 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1112#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1113 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1114 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1115#else
1116 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1117 #define JSON_HEDLEY_DIAGNOSTIC_POP
1118#endif
1119
1120/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1121 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1122#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1123 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1124#endif
1125#if defined(__cplusplus)
1126# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1127# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1128# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1129# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1130 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1131 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1132 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1133 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1134 xpr \
1135 JSON_HEDLEY_DIAGNOSTIC_POP
1136# else
1137# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1138 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1139 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1140 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1141 xpr \
1142 JSON_HEDLEY_DIAGNOSTIC_POP
1143# endif
1144# else
1145# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1146 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1147 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1148 xpr \
1149 JSON_HEDLEY_DIAGNOSTIC_POP
1150# endif
1151# endif
1152#endif
1153#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1154 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1155#endif
1156
1157#if defined(JSON_HEDLEY_CONST_CAST)
1158 #undef JSON_HEDLEY_CONST_CAST
1159#endif
1160#if defined(__cplusplus)
1161# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1162#elif \
1163 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1164 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1165 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1166# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1167 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1168 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1169 ((T) (expr)); \
1170 JSON_HEDLEY_DIAGNOSTIC_POP \
1171 }))
1172#else
1173# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1174#endif
1175
1176#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1177 #undef JSON_HEDLEY_REINTERPRET_CAST
1178#endif
1179#if defined(__cplusplus)
1180 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1181#else
1182 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1183#endif
1184
1185#if defined(JSON_HEDLEY_STATIC_CAST)
1186 #undef JSON_HEDLEY_STATIC_CAST
1187#endif
1188#if defined(__cplusplus)
1189 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1190#else
1191 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1192#endif
1193
1194#if defined(JSON_HEDLEY_CPP_CAST)
1195 #undef JSON_HEDLEY_CPP_CAST
1196#endif
1197#if defined(__cplusplus)
1198# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1199# define JSON_HEDLEY_CPP_CAST(T, expr) \
1200 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1201 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1202 ((T) (expr)) \
1203 JSON_HEDLEY_DIAGNOSTIC_POP
1204# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1205# define JSON_HEDLEY_CPP_CAST(T, expr) \
1206 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1207 _Pragma("diag_suppress=Pe137") \
1208 JSON_HEDLEY_DIAGNOSTIC_POP
1209# else
1210# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1211# endif
1212#else
1213# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1214#endif
1215
1216#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1217 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1218#endif
1219#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1220 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1221#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1222 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1223#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1224 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1225#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1226 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1227#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1228 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1229#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1230 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1231#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1232 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1233#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1234 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1235#elif \
1236 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1237 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1238 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1239 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1240 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1241 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1242 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1243 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1244 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1245 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1246 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1247 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1248#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1249 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1250#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1251 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1252#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1253 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1254#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1255 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1256#else
1257 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1258#endif
1259
1260#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1261 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1262#endif
1263#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1264 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1265#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1266 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1267#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1268 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1269#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1270 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1271#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1272 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1273#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1274 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1275#elif \
1276 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1277 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1278 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1279 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1280 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1281#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1282 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1283#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1284 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1285#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1286 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1287#else
1288 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1289#endif
1290
1291#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1292 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1293#endif
1294#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1295 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1296#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1297 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1298#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1299 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1300#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1301 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1302#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1303 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1304#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1305 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1306#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1307 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1308#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1309 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1310#elif \
1311 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1312 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1313 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1314 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1315#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1316 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1317#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1318 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1319#else
1320 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1321#endif
1322
1323#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1324 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1325#endif
1326#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1327 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1328#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1329 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1330#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1331 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1332#else
1333 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1334#endif
1335
1336#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1337 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1338#endif
1339#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1340 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1341#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1342 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1343#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1344 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1345#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1346 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1347#else
1348 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1349#endif
1350
1351#if defined(JSON_HEDLEY_DEPRECATED)
1352 #undef JSON_HEDLEY_DEPRECATED
1353#endif
1354#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1355 #undef JSON_HEDLEY_DEPRECATED_FOR
1356#endif
1357#if \
1358 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1359 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1360 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1361 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1362#elif \
1363 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1364 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1365 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1366 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1367 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1368 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1369 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1370 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1371 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1372 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1373 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1374 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1375 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1376 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1377#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1378 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1379 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1380#elif \
1381 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1382 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1383 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1384 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1385 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1386 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1387 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1388 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1389 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1390 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1391 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1392 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1393 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1394 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1395 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1396 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1397 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1398 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1399#elif \
1400 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1401 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1402 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1403 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1404 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1405#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1406 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1407 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1408#else
1409 #define JSON_HEDLEY_DEPRECATED(since)
1410 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1411#endif
1412
1413#if defined(JSON_HEDLEY_UNAVAILABLE)
1414 #undef JSON_HEDLEY_UNAVAILABLE
1415#endif
1416#if \
1417 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1418 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1419 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1420 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1421 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1422#else
1423 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1424#endif
1425
1426#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1427 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1428#endif
1429#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1430 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1431#endif
1432#if \
1433 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1434 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1435 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1436 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1437 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1438 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1439 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1440 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1441 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1442 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1443 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1444 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1445 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1446 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1447 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1448 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1449 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1450 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1451 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1452#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1453 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1454 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1455#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1456 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1457 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1458#elif defined(_Check_return_) /* SAL */
1459 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1460 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1461#else
1462 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1463 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1464#endif
1465
1466#if defined(JSON_HEDLEY_SENTINEL)
1467 #undef JSON_HEDLEY_SENTINEL
1468#endif
1469#if \
1470 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1471 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1472 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1473 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1474 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1475 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1476#else
1477 #define JSON_HEDLEY_SENTINEL(position)
1478#endif
1479
1480#if defined(JSON_HEDLEY_NO_RETURN)
1481 #undef JSON_HEDLEY_NO_RETURN
1482#endif
1483#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1484 #define JSON_HEDLEY_NO_RETURN __noreturn
1485#elif \
1486 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1487 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1488 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1489#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1490 #define JSON_HEDLEY_NO_RETURN _Noreturn
1491#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1492 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1493#elif \
1494 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1495 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1496 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1497 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1498 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1499 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1500 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1501 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1502 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1503 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1504 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1505 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1506 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1507 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1508 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1509 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1510 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1511 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1512#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1513 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1514#elif \
1515 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1516 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1517 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1518#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1519 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1520#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1521 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1522#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1523 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1524#else
1525 #define JSON_HEDLEY_NO_RETURN
1526#endif
1527
1528#if defined(JSON_HEDLEY_NO_ESCAPE)
1529 #undef JSON_HEDLEY_NO_ESCAPE
1530#endif
1531#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1532 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1533#else
1534 #define JSON_HEDLEY_NO_ESCAPE
1535#endif
1536
1537#if defined(JSON_HEDLEY_UNREACHABLE)
1538 #undef JSON_HEDLEY_UNREACHABLE
1539#endif
1540#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1541 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1542#endif
1543#if defined(JSON_HEDLEY_ASSUME)
1544 #undef JSON_HEDLEY_ASSUME
1545#endif
1546#if \
1547 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1548 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1549 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1550 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1551#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1552 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1553#elif \
1554 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1555 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1556 #if defined(__cplusplus)
1557 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1558 #else
1559 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1560 #endif
1561#endif
1562#if \
1563 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1564 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1565 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1566 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1567 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1568 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1569 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1570 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1571#elif defined(JSON_HEDLEY_ASSUME)
1572 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1573#endif
1574#if !defined(JSON_HEDLEY_ASSUME)
1575 #if defined(JSON_HEDLEY_UNREACHABLE)
1576 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1577 #else
1578 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1579 #endif
1580#endif
1581#if defined(JSON_HEDLEY_UNREACHABLE)
1582 #if \
1583 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1584 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1585 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1586 #else
1587 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1588 #endif
1589#else
1590 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1591#endif
1592#if !defined(JSON_HEDLEY_UNREACHABLE)
1593 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1594#endif
1595
1597#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1598 #pragma clang diagnostic ignored "-Wpedantic"
1599#endif
1600#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1601 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1602#endif
1603#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1604 #if defined(__clang__)
1605 #pragma clang diagnostic ignored "-Wvariadic-macros"
1606 #elif defined(JSON_HEDLEY_GCC_VERSION)
1607 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1608 #endif
1609#endif
1610#if defined(JSON_HEDLEY_NON_NULL)
1611 #undef JSON_HEDLEY_NON_NULL
1612#endif
1613#if \
1614 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1615 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1616 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1617 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1618 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1619#else
1620 #define JSON_HEDLEY_NON_NULL(...)
1621#endif
1623
1624#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1625 #undef JSON_HEDLEY_PRINTF_FORMAT
1626#endif
1627#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1628 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1629#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1630 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1631#elif \
1632 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1633 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1634 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1635 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1636 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1637 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1638 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1639 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1640 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1641 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1642 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1643 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1644 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1645 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1646 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1647 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1648 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1649 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1650#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1651 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1652#else
1653 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1654#endif
1655
1656#if defined(JSON_HEDLEY_CONSTEXPR)
1657 #undef JSON_HEDLEY_CONSTEXPR
1658#endif
1659#if defined(__cplusplus)
1660 #if __cplusplus >= 201103L
1661 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1662 #endif
1663#endif
1664#if !defined(JSON_HEDLEY_CONSTEXPR)
1665 #define JSON_HEDLEY_CONSTEXPR
1666#endif
1667
1668#if defined(JSON_HEDLEY_PREDICT)
1669 #undef JSON_HEDLEY_PREDICT
1670#endif
1671#if defined(JSON_HEDLEY_LIKELY)
1672 #undef JSON_HEDLEY_LIKELY
1673#endif
1674#if defined(JSON_HEDLEY_UNLIKELY)
1675 #undef JSON_HEDLEY_UNLIKELY
1676#endif
1677#if defined(JSON_HEDLEY_UNPREDICTABLE)
1678 #undef JSON_HEDLEY_UNPREDICTABLE
1679#endif
1680#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1681 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1682#endif
1683#if \
1684 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1685 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1686 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1687# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1688# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1689# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1690# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1691# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1692#elif \
1693 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1694 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1695 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1696 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1697 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1698 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1699 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1700 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1701 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1702 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1703 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1704 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1705 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1706 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1707 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1708 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1709# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1710 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1711# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1712 (__extension__ ({ \
1713 double hedley_probability_ = (probability); \
1714 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1715 }))
1716# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1717 (__extension__ ({ \
1718 double hedley_probability_ = (probability); \
1719 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1720 }))
1721# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1722# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1723#else
1724# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1725# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1726# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1727# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1728# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1729#endif
1730#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1731 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1732#endif
1733
1734#if defined(JSON_HEDLEY_MALLOC)
1735 #undef JSON_HEDLEY_MALLOC
1736#endif
1737#if \
1738 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1739 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1740 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1741 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1742 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1743 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1744 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1745 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1746 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1747 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1748 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1749 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1750 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1751 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1752 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1753 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1754 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1755 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1756 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1757#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1758 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1759#elif \
1760 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1761 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1762 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1763#else
1764 #define JSON_HEDLEY_MALLOC
1765#endif
1766
1767#if defined(JSON_HEDLEY_PURE)
1768 #undef JSON_HEDLEY_PURE
1769#endif
1770#if \
1771 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1772 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1773 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1774 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1775 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1776 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1777 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1778 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1779 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1780 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1781 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1782 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1783 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1784 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1785 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1786 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1787 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1788 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1789 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1790# define JSON_HEDLEY_PURE __attribute__((__pure__))
1791#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1792# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1793#elif defined(__cplusplus) && \
1794 ( \
1795 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1796 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1797 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1798 )
1799# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1800#else
1801# define JSON_HEDLEY_PURE
1802#endif
1803
1804#if defined(JSON_HEDLEY_CONST)
1805 #undef JSON_HEDLEY_CONST
1806#endif
1807#if \
1808 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1809 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1810 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1811 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1812 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1813 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1814 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1815 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1816 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1817 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1818 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1819 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1820 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1821 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1822 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1823 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1824 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1825 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1826 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1827 #define JSON_HEDLEY_CONST __attribute__((__const__))
1828#elif \
1829 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1830 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1831#else
1832 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1833#endif
1834
1835#if defined(JSON_HEDLEY_RESTRICT)
1836 #undef JSON_HEDLEY_RESTRICT
1837#endif
1838#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1839 #define JSON_HEDLEY_RESTRICT restrict
1840#elif \
1841 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1842 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1843 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1844 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1845 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1846 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1847 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1848 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1849 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1850 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1851 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1852 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1853 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1854 defined(__clang__) || \
1855 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1856 #define JSON_HEDLEY_RESTRICT __restrict
1857#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1858 #define JSON_HEDLEY_RESTRICT _Restrict
1859#else
1860 #define JSON_HEDLEY_RESTRICT
1861#endif
1862
1863#if defined(JSON_HEDLEY_INLINE)
1864 #undef JSON_HEDLEY_INLINE
1865#endif
1866#if \
1867 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1868 (defined(__cplusplus) && (__cplusplus >= 199711L))
1869 #define JSON_HEDLEY_INLINE inline
1870#elif \
1871 defined(JSON_HEDLEY_GCC_VERSION) || \
1872 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1873 #define JSON_HEDLEY_INLINE __inline__
1874#elif \
1875 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1876 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1877 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1878 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1879 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1880 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1881 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1882 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1883 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1884 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1885 #define JSON_HEDLEY_INLINE __inline
1886#else
1887 #define JSON_HEDLEY_INLINE
1888#endif
1889
1890#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1891 #undef JSON_HEDLEY_ALWAYS_INLINE
1892#endif
1893#if \
1894 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1895 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1896 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1897 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1898 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1899 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1900 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1901 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1902 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1903 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1904 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1905 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1906 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1907 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1908 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1909 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1910 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1911 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1912 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1913# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1914#elif \
1915 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1916 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1917# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1918#elif defined(__cplusplus) && \
1919 ( \
1920 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1921 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1922 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1923 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1924 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1925 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1926 )
1927# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1928#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1929# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1930#else
1931# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1932#endif
1933
1934#if defined(JSON_HEDLEY_NEVER_INLINE)
1935 #undef JSON_HEDLEY_NEVER_INLINE
1936#endif
1937#if \
1938 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1939 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1940 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1941 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1942 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1943 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1944 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1945 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1946 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1947 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1948 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1949 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1950 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1951 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1952 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1953 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1954 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1955 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1956 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1957 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1958#elif \
1959 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1960 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1961 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1962#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1963 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1964#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1965 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1966#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1967 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1968#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1969 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1970#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1971 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1972#else
1973 #define JSON_HEDLEY_NEVER_INLINE
1974#endif
1975
1976#if defined(JSON_HEDLEY_PRIVATE)
1977 #undef JSON_HEDLEY_PRIVATE
1978#endif
1979#if defined(JSON_HEDLEY_PUBLIC)
1980 #undef JSON_HEDLEY_PUBLIC
1981#endif
1982#if defined(JSON_HEDLEY_IMPORT)
1983 #undef JSON_HEDLEY_IMPORT
1984#endif
1985#if defined(_WIN32) || defined(__CYGWIN__)
1986# define JSON_HEDLEY_PRIVATE
1987# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1988# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1989#else
1990# if \
1991 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1992 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1993 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1994 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1995 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1996 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1997 ( \
1998 defined(__TI_EABI__) && \
1999 ( \
2000 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
2001 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
2002 ) \
2003 ) || \
2004 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2005# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
2006# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
2007# else
2008# define JSON_HEDLEY_PRIVATE
2009# define JSON_HEDLEY_PUBLIC
2010# endif
2011# define JSON_HEDLEY_IMPORT extern
2012#endif
2013
2014#if defined(JSON_HEDLEY_NO_THROW)
2015 #undef JSON_HEDLEY_NO_THROW
2016#endif
2017#if \
2018 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2019 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2020 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2021 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2022 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2023#elif \
2024 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2025 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2026 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2027 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2028#else
2029 #define JSON_HEDLEY_NO_THROW
2030#endif
2031
2032#if defined(JSON_HEDLEY_FALL_THROUGH)
2033 #undef JSON_HEDLEY_FALL_THROUGH
2034#endif
2035#if \
2036 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2037 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2038 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2039 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2040#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2041 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2042#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2043 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2044#elif defined(__fallthrough) /* SAL */
2045 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2046#else
2047 #define JSON_HEDLEY_FALL_THROUGH
2048#endif
2049
2050#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2051 #undef JSON_HEDLEY_RETURNS_NON_NULL
2052#endif
2053#if \
2054 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2055 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2056 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2057 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2058#elif defined(_Ret_notnull_) /* SAL */
2059 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2060#else
2061 #define JSON_HEDLEY_RETURNS_NON_NULL
2062#endif
2063
2064#if defined(JSON_HEDLEY_ARRAY_PARAM)
2065 #undef JSON_HEDLEY_ARRAY_PARAM
2066#endif
2067#if \
2068 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2069 !defined(__STDC_NO_VLA__) && \
2070 !defined(__cplusplus) && \
2071 !defined(JSON_HEDLEY_PGI_VERSION) && \
2072 !defined(JSON_HEDLEY_TINYC_VERSION)
2073 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2074#else
2075 #define JSON_HEDLEY_ARRAY_PARAM(name)
2076#endif
2077
2078#if defined(JSON_HEDLEY_IS_CONSTANT)
2079 #undef JSON_HEDLEY_IS_CONSTANT
2080#endif
2081#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2082 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2083#endif
2084/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2085 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2086#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2087 #undef JSON_HEDLEY_IS_CONSTEXPR_
2088#endif
2089#if \
2090 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2091 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2092 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2093 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2094 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2095 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2096 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2097 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2098 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2099 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2100 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2101#endif
2102#if !defined(__cplusplus)
2103# if \
2104 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2105 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2106 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2107 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2108 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2109 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2110 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2111#if defined(__INTPTR_TYPE__)
2112 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2113#else
2114 #include <stdint.h>
2115 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2116#endif
2117# elif \
2118 ( \
2119 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2120 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2121 !defined(JSON_HEDLEY_PGI_VERSION) && \
2122 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2123 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2124 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2125 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2126 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2127 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2128#if defined(__INTPTR_TYPE__)
2129 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2130#else
2131 #include <stdint.h>
2132 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2133#endif
2134# elif \
2135 defined(JSON_HEDLEY_GCC_VERSION) || \
2136 defined(JSON_HEDLEY_INTEL_VERSION) || \
2137 defined(JSON_HEDLEY_TINYC_VERSION) || \
2138 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2139 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2140 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2141 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2142 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2143 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2144 defined(__clang__)
2145# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2146 sizeof(void) != \
2147 sizeof(*( \
2148 1 ? \
2149 ((void*) ((expr) * 0L) ) : \
2150((struct { char v[sizeof(void) * 2]; } *) 1) \
2151 ) \
2152 ) \
2153 )
2154# endif
2155#endif
2156#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2157 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2158 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2159 #endif
2160 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2161#else
2162 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2163 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2164 #endif
2165 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2166#endif
2167
2168#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2169 #undef JSON_HEDLEY_BEGIN_C_DECLS
2170#endif
2171#if defined(JSON_HEDLEY_END_C_DECLS)
2172 #undef JSON_HEDLEY_END_C_DECLS
2173#endif
2174#if defined(JSON_HEDLEY_C_DECL)
2175 #undef JSON_HEDLEY_C_DECL
2176#endif
2177#if defined(__cplusplus)
2178 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2179 #define JSON_HEDLEY_END_C_DECLS }
2180 #define JSON_HEDLEY_C_DECL extern "C"
2181#else
2182 #define JSON_HEDLEY_BEGIN_C_DECLS
2183 #define JSON_HEDLEY_END_C_DECLS
2184 #define JSON_HEDLEY_C_DECL
2185#endif
2186
2187#if defined(JSON_HEDLEY_STATIC_ASSERT)
2188 #undef JSON_HEDLEY_STATIC_ASSERT
2189#endif
2190#if \
2191 !defined(__cplusplus) && ( \
2192 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2193 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2194 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2195 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2196 defined(_Static_assert) \
2197 )
2198# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2199#elif \
2200 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2201 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2202 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2203# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2204#else
2205# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2206#endif
2207
2208#if defined(JSON_HEDLEY_NULL)
2209 #undef JSON_HEDLEY_NULL
2210#endif
2211#if defined(__cplusplus)
2212 #if __cplusplus >= 201103L
2213 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2214 #elif defined(NULL)
2215 #define JSON_HEDLEY_NULL NULL
2216 #else
2217 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2218 #endif
2219#elif defined(NULL)
2220 #define JSON_HEDLEY_NULL NULL
2221#else
2222 #define JSON_HEDLEY_NULL ((void*) 0)
2223#endif
2224
2225#if defined(JSON_HEDLEY_MESSAGE)
2226 #undef JSON_HEDLEY_MESSAGE
2227#endif
2228#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2229# define JSON_HEDLEY_MESSAGE(msg) \
2230 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2231 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2232 JSON_HEDLEY_PRAGMA(message msg) \
2233 JSON_HEDLEY_DIAGNOSTIC_POP
2234#elif \
2235 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2236 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2237# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2238#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2239# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2240#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2241# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2242#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2243# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2244#else
2245# define JSON_HEDLEY_MESSAGE(msg)
2246#endif
2247
2248#if defined(JSON_HEDLEY_WARNING)
2249 #undef JSON_HEDLEY_WARNING
2250#endif
2251#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2252# define JSON_HEDLEY_WARNING(msg) \
2253 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2254 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2255 JSON_HEDLEY_PRAGMA(clang warning msg) \
2256 JSON_HEDLEY_DIAGNOSTIC_POP
2257#elif \
2258 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2259 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2260 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2261# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2262#elif \
2263 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2264 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2265# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2266#else
2267# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2268#endif
2269
2270#if defined(JSON_HEDLEY_REQUIRE)
2271 #undef JSON_HEDLEY_REQUIRE
2272#endif
2273#if defined(JSON_HEDLEY_REQUIRE_MSG)
2274 #undef JSON_HEDLEY_REQUIRE_MSG
2275#endif
2276#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2277# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2278# define JSON_HEDLEY_REQUIRE(expr) \
2279 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2280 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2281 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2282 JSON_HEDLEY_DIAGNOSTIC_POP
2283# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2284 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2285 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2286 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2287 JSON_HEDLEY_DIAGNOSTIC_POP
2288# else
2289# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2290# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2291# endif
2292#else
2293# define JSON_HEDLEY_REQUIRE(expr)
2294# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2295#endif
2296
2297#if defined(JSON_HEDLEY_FLAGS)
2298 #undef JSON_HEDLEY_FLAGS
2299#endif
2300#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2301 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2302#else
2303 #define JSON_HEDLEY_FLAGS
2304#endif
2305
2306#if defined(JSON_HEDLEY_FLAGS_CAST)
2307 #undef JSON_HEDLEY_FLAGS_CAST
2308#endif
2309#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2310# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2311 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2312 _Pragma("warning(disable:188)") \
2313 ((T) (expr)); \
2314 JSON_HEDLEY_DIAGNOSTIC_POP \
2315 }))
2316#else
2317# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2318#endif
2319
2320#if defined(JSON_HEDLEY_EMPTY_BASES)
2321 #undef JSON_HEDLEY_EMPTY_BASES
2322#endif
2323#if \
2324 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2325 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2326 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2327#else
2328 #define JSON_HEDLEY_EMPTY_BASES
2329#endif
2330
2331/* Remaining macros are deprecated. */
2332
2333#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2334 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2335#endif
2336#if defined(__clang__)
2337 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2338#else
2339 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2340#endif
2341
2342#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2343 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2344#endif
2345#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2346
2347#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2348 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2349#endif
2350#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2351
2352#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2353 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2354#endif
2355#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2356
2357#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2358 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2359#endif
2360#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2361
2362#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2363 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2364#endif
2365#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2366
2367#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2368 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2369#endif
2370#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2371
2372#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2373 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2374#endif
2375#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2376
2377#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2378
2379
2380// This file contains all internal macro definitions (except those affecting ABI)
2381// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2382
2383// #include <nlohmann/detail/abi_macros.hpp>
2384
2385
2386// exclude unsupported compilers
2387#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2388 #if defined(__clang__)
2389 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2390 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2391 #endif
2392 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2393 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2394 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2395 #endif
2396 #endif
2397#endif
2398
2399// C++ language standard detection
2400// if the user manually specified the used c++ version this is skipped
2401#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2402 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2403 #define JSON_HAS_CPP_20
2404 #define JSON_HAS_CPP_17
2405 #define JSON_HAS_CPP_14
2406 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2407 #define JSON_HAS_CPP_17
2408 #define JSON_HAS_CPP_14
2409 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2410 #define JSON_HAS_CPP_14
2411 #endif
2412 // the cpp 11 flag is always specified because it is the minimal required version
2413 #define JSON_HAS_CPP_11
2414#endif
2415
2416#ifdef __has_include
2417 #if __has_include(<version>)
2418 #include <version>
2419 #endif
2420#endif
2421
2422#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2423 #ifdef JSON_HAS_CPP_17
2424 #if defined(__cpp_lib_filesystem)
2425 #define JSON_HAS_FILESYSTEM 1
2426 #elif defined(__cpp_lib_experimental_filesystem)
2427 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2428 #elif !defined(__has_include)
2429 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2430 #elif __has_include(<filesystem>)
2431 #define JSON_HAS_FILESYSTEM 1
2432 #elif __has_include(<experimental/filesystem>)
2433 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2434 #endif
2435
2436 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2437 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2438 #undef JSON_HAS_FILESYSTEM
2439 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2440 #endif
2441
2442 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2443 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2444 #undef JSON_HAS_FILESYSTEM
2445 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2446 #endif
2447
2448 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2449 #if defined(__clang_major__) && __clang_major__ < 7
2450 #undef JSON_HAS_FILESYSTEM
2451 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2452 #endif
2453
2454 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2455 #if defined(_MSC_VER) && _MSC_VER < 1914
2456 #undef JSON_HAS_FILESYSTEM
2457 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2458 #endif
2459
2460 // no filesystem support before iOS 13
2461 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2462 #undef JSON_HAS_FILESYSTEM
2463 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2464 #endif
2465
2466 // no filesystem support before macOS Catalina
2467 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2468 #undef JSON_HAS_FILESYSTEM
2469 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2470 #endif
2471 #endif
2472#endif
2473
2474#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2475 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2476#endif
2477
2478#ifndef JSON_HAS_FILESYSTEM
2479 #define JSON_HAS_FILESYSTEM 0
2480#endif
2481
2482#ifndef JSON_HAS_THREE_WAY_COMPARISON
2483 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2484 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2485 #define JSON_HAS_THREE_WAY_COMPARISON 1
2486 #else
2487 #define JSON_HAS_THREE_WAY_COMPARISON 0
2488 #endif
2489#endif
2490
2491#ifndef JSON_HAS_RANGES
2492 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2493 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2494 #define JSON_HAS_RANGES 0
2495 #elif defined(__cpp_lib_ranges)
2496 #define JSON_HAS_RANGES 1
2497 #else
2498 #define JSON_HAS_RANGES 0
2499 #endif
2500#endif
2501
2502#ifndef JSON_HAS_STATIC_RTTI
2503 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2504 #define JSON_HAS_STATIC_RTTI 1
2505 #else
2506 #define JSON_HAS_STATIC_RTTI 0
2507 #endif
2508#endif
2509
2510#ifdef JSON_HAS_CPP_17
2511 #define JSON_INLINE_VARIABLE inline
2512#else
2513 #define JSON_INLINE_VARIABLE
2514#endif
2515
2516#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2517 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2518#else
2519 #define JSON_NO_UNIQUE_ADDRESS
2520#endif
2521
2522// disable documentation warnings on clang
2523#if defined(__clang__)
2524 #pragma clang diagnostic push
2525 #pragma clang diagnostic ignored "-Wdocumentation"
2526 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2527#endif
2528
2529// allow disabling exceptions
2530#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2531 #define JSON_THROW(exception) throw exception
2532 #define JSON_TRY try
2533 #define JSON_CATCH(exception) catch(exception)
2534 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2535#else
2536 #include <cstdlib>
2537 #define JSON_THROW(exception) std::abort()
2538 #define JSON_TRY if(true)
2539 #define JSON_CATCH(exception) if(false)
2540 #define JSON_INTERNAL_CATCH(exception) if(false)
2541#endif
2542
2543// override exception macros
2544#if defined(JSON_THROW_USER)
2545 #undef JSON_THROW
2546 #define JSON_THROW JSON_THROW_USER
2547#endif
2548#if defined(JSON_TRY_USER)
2549 #undef JSON_TRY
2550 #define JSON_TRY JSON_TRY_USER
2551#endif
2552#if defined(JSON_CATCH_USER)
2553 #undef JSON_CATCH
2554 #define JSON_CATCH JSON_CATCH_USER
2555 #undef JSON_INTERNAL_CATCH
2556 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2557#endif
2558#if defined(JSON_INTERNAL_CATCH_USER)
2559 #undef JSON_INTERNAL_CATCH
2560 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2561#endif
2562
2563// allow overriding assert
2564#if !defined(JSON_ASSERT)
2565 #include <cassert> // assert
2566 #define JSON_ASSERT(x) assert(x)
2567#endif
2568
2569// allow to access some private functions (needed by the test suite)
2570#if defined(JSON_TESTS_PRIVATE)
2571 #define JSON_PRIVATE_UNLESS_TESTED public
2572#else
2573 #define JSON_PRIVATE_UNLESS_TESTED private
2574#endif
2575
2581#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2582 template<typename BasicJsonType> \
2583 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2584 { \
2585 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2586 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2587 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2588 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2589 auto it = std::find_if(std::begin(m), std::end(m), \
2590 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2591 { \
2592 return ej_pair.first == e; \
2593 }); \
2594 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2595 } \
2596 template<typename BasicJsonType> \
2597 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2598 { \
2599 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2600 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2601 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2602 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2603 auto it = std::find_if(std::begin(m), std::end(m), \
2604 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2605 { \
2606 return ej_pair.second == j; \
2607 }); \
2608 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2609 }
2610
2611// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2612// may be removed in the future once the class is split.
2613
2614#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2615 template<template<typename, typename, typename...> class ObjectType, \
2616 template<typename, typename...> class ArrayType, \
2617 class StringType, class BooleanType, class NumberIntegerType, \
2618 class NumberUnsignedType, class NumberFloatType, \
2619 template<typename> class AllocatorType, \
2620 template<typename, typename = void> class JSONSerializer, \
2621 class BinaryType, \
2622 class CustomBaseClass>
2623
2624#define NLOHMANN_BASIC_JSON_TPL \
2625 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2626 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2627 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2628
2629// Macros to simplify conversion from/to types
2630
2631#define NLOHMANN_JSON_EXPAND( x ) x
2632#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
2633#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2634 NLOHMANN_JSON_PASTE64, \
2635 NLOHMANN_JSON_PASTE63, \
2636 NLOHMANN_JSON_PASTE62, \
2637 NLOHMANN_JSON_PASTE61, \
2638 NLOHMANN_JSON_PASTE60, \
2639 NLOHMANN_JSON_PASTE59, \
2640 NLOHMANN_JSON_PASTE58, \
2641 NLOHMANN_JSON_PASTE57, \
2642 NLOHMANN_JSON_PASTE56, \
2643 NLOHMANN_JSON_PASTE55, \
2644 NLOHMANN_JSON_PASTE54, \
2645 NLOHMANN_JSON_PASTE53, \
2646 NLOHMANN_JSON_PASTE52, \
2647 NLOHMANN_JSON_PASTE51, \
2648 NLOHMANN_JSON_PASTE50, \
2649 NLOHMANN_JSON_PASTE49, \
2650 NLOHMANN_JSON_PASTE48, \
2651 NLOHMANN_JSON_PASTE47, \
2652 NLOHMANN_JSON_PASTE46, \
2653 NLOHMANN_JSON_PASTE45, \
2654 NLOHMANN_JSON_PASTE44, \
2655 NLOHMANN_JSON_PASTE43, \
2656 NLOHMANN_JSON_PASTE42, \
2657 NLOHMANN_JSON_PASTE41, \
2658 NLOHMANN_JSON_PASTE40, \
2659 NLOHMANN_JSON_PASTE39, \
2660 NLOHMANN_JSON_PASTE38, \
2661 NLOHMANN_JSON_PASTE37, \
2662 NLOHMANN_JSON_PASTE36, \
2663 NLOHMANN_JSON_PASTE35, \
2664 NLOHMANN_JSON_PASTE34, \
2665 NLOHMANN_JSON_PASTE33, \
2666 NLOHMANN_JSON_PASTE32, \
2667 NLOHMANN_JSON_PASTE31, \
2668 NLOHMANN_JSON_PASTE30, \
2669 NLOHMANN_JSON_PASTE29, \
2670 NLOHMANN_JSON_PASTE28, \
2671 NLOHMANN_JSON_PASTE27, \
2672 NLOHMANN_JSON_PASTE26, \
2673 NLOHMANN_JSON_PASTE25, \
2674 NLOHMANN_JSON_PASTE24, \
2675 NLOHMANN_JSON_PASTE23, \
2676 NLOHMANN_JSON_PASTE22, \
2677 NLOHMANN_JSON_PASTE21, \
2678 NLOHMANN_JSON_PASTE20, \
2679 NLOHMANN_JSON_PASTE19, \
2680 NLOHMANN_JSON_PASTE18, \
2681 NLOHMANN_JSON_PASTE17, \
2682 NLOHMANN_JSON_PASTE16, \
2683 NLOHMANN_JSON_PASTE15, \
2684 NLOHMANN_JSON_PASTE14, \
2685 NLOHMANN_JSON_PASTE13, \
2686 NLOHMANN_JSON_PASTE12, \
2687 NLOHMANN_JSON_PASTE11, \
2688 NLOHMANN_JSON_PASTE10, \
2689 NLOHMANN_JSON_PASTE9, \
2690 NLOHMANN_JSON_PASTE8, \
2691 NLOHMANN_JSON_PASTE7, \
2692 NLOHMANN_JSON_PASTE6, \
2693 NLOHMANN_JSON_PASTE5, \
2694 NLOHMANN_JSON_PASTE4, \
2695 NLOHMANN_JSON_PASTE3, \
2696 NLOHMANN_JSON_PASTE2, \
2697 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2698#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2699#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2700#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2701#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2702#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2703#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)
2704#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)
2705#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)
2706#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)
2707#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)
2708#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)
2709#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)
2710#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)
2711#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)
2712#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)
2713#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)
2714#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)
2715#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)
2716#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)
2717#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)
2718#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)
2719#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)
2720#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)
2721#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)
2722#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)
2723#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)
2724#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)
2725#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)
2726#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)
2727#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)
2728#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)
2729#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)
2730#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)
2731#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)
2732#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)
2733#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)
2734#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)
2735#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)
2736#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)
2737#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)
2738#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)
2739#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)
2740#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)
2741#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)
2742#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)
2743#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)
2744#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)
2745#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)
2746#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)
2747#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)
2748#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)
2749#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)
2750#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)
2751#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)
2752#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)
2753#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)
2754#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)
2755#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)
2756#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)
2757#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)
2758#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)
2759#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)
2760#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)
2761
2762#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2763#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2764#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;
2765
2772#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2773 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2774 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2775 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2776 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2777
2784#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2785 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2786 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2787 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2788 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__)) }
2789
2796#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2797 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2798 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2799
2806#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2807 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2808 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2809 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2810 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2811
2818#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2819 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2820 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2821 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2822 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__)) }
2823
2830#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2831 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2832 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2833
2840#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \
2841 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2842 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__)) } \
2843 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2844 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__)) }
2845
2852#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2853 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2854 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__)) } \
2855 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2856 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__)) }
2857
2864#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2865 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2866 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__)) }
2867
2874#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \
2875 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2876 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__)) } \
2877 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2878 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__)) }
2879
2886#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2887 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2888 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__)) } \
2889 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2890 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__)) }
2891
2898#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2899 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2900 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__)) }
2901
2902// inspired from https://stackoverflow.com/a/26745591
2903// allows to call any std function as if (e.g. with begin):
2904// using std::begin; begin(x);
2905//
2906// it allows using the detected idiom to retrieve the return type
2907// of such an expression
2908#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2909 namespace detail { \
2910 using std::std_name; \
2911 \
2912 template<typename... T> \
2913 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2914 } \
2915 \
2916 namespace detail2 { \
2917 struct std_name##_tag \
2918 { \
2919 }; \
2920 \
2921 template<typename... T> \
2922 std_name##_tag std_name(T&&...); \
2923 \
2924 template<typename... T> \
2925 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2926 \
2927 template<typename... T> \
2928 struct would_call_std_##std_name \
2929 { \
2930 static constexpr auto const value = ::nlohmann::detail:: \
2931 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2932 }; \
2933 } /* namespace detail2 */ \
2934 \
2935 template<typename... T> \
2936 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2937 { \
2938 }
2939
2940#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2941 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2942#endif
2943
2944#if JSON_USE_IMPLICIT_CONVERSIONS
2945 #define JSON_EXPLICIT
2946#else
2947 #define JSON_EXPLICIT explicit
2948#endif
2949
2950#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2951 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2952#endif
2953
2954#ifndef JSON_USE_GLOBAL_UDLS
2955 #define JSON_USE_GLOBAL_UDLS 1
2956#endif
2957
2958#if JSON_HAS_THREE_WAY_COMPARISON
2959 #include <compare> // partial_ordering
2960#endif
2961
2963namespace detail
2964{
2965
2967// JSON type enumeration //
2969
3007
3021#if JSON_HAS_THREE_WAY_COMPARISON
3022 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
3023#else
3024 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3025#endif
3026{
3027 static constexpr std::array<std::uint8_t, 9> order = {{
3028 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
3029 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
3030 6 /* binary */
3031 }
3032 };
3033
3034 const auto l_index = static_cast<std::size_t>(lhs);
3035 const auto r_index = static_cast<std::size_t>(rhs);
3036#if JSON_HAS_THREE_WAY_COMPARISON
3037 if (l_index < order.size() && r_index < order.size())
3038 {
3039 return order[l_index] <=> order[r_index]; // *NOPAD*
3040 }
3041 return std::partial_ordering::unordered;
3042#else
3043 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
3044#endif
3045}
3046
3047// GCC selects the built-in operator< over an operator rewritten from
3048// a user-defined spaceship operator
3049// Clang, MSVC, and ICC select the rewritten candidate
3050// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
3051#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
3052inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3053{
3054 return std::is_lt(lhs <=> rhs); // *NOPAD*
3055}
3056#endif
3057
3058} // namespace detail
3060
3061// #include <nlohmann/detail/string_escape.hpp>
3062// __ _____ _____ _____
3063// __| | __| | | | JSON for Modern C++
3064// | | |__ | | | | | | version 3.11.3
3065// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3066//
3067// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3068// SPDX-License-Identifier: MIT
3069
3070
3071
3072// #include <nlohmann/detail/abi_macros.hpp>
3073
3074
3076namespace detail
3077{
3078
3092template<typename StringType>
3093inline void replace_substring(StringType& s, const StringType& f,
3094 const StringType& t)
3095{
3096 JSON_ASSERT(!f.empty());
3097 for (auto pos = s.find(f); // find first occurrence of f
3098 pos != StringType::npos; // make sure f was found
3099 s.replace(pos, f.size(), t), // replace with t, and
3100 pos = s.find(f, pos + t.size())) // find next occurrence of f
3101 {}
3102}
3103
3111template<typename StringType>
3112inline StringType escape(StringType s)
3113{
3114 replace_substring(s, StringType{"~"}, StringType{"~0"});
3115 replace_substring(s, StringType{"/"}, StringType{"~1"});
3116 return s;
3117}
3118
3126template<typename StringType>
3127static void unescape(StringType& s)
3128{
3129 replace_substring(s, StringType{"~1"}, StringType{"/"});
3130 replace_substring(s, StringType{"~0"}, StringType{"~"});
3131}
3132
3133} // namespace detail
3135
3136// #include <nlohmann/detail/input/position_t.hpp>
3137// __ _____ _____ _____
3138// __| | __| | | | JSON for Modern C++
3139// | | |__ | | | | | | version 3.11.3
3140// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3141//
3142// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3143// SPDX-License-Identifier: MIT
3144
3145
3146
3147#include <cstddef> // size_t
3148
3149// #include <nlohmann/detail/abi_macros.hpp>
3150
3151
3153namespace detail
3154{
3155
3158{
3160 std::size_t chars_read_total = 0;
3164 std::size_t lines_read = 0;
3165
3167 constexpr operator size_t() const
3168 {
3169 return chars_read_total;
3170 }
3171};
3172
3173} // namespace detail
3175
3176// #include <nlohmann/detail/macro_scope.hpp>
3177
3178// #include <nlohmann/detail/meta/cpp_future.hpp>
3179// __ _____ _____ _____
3180// __| | __| | | | JSON for Modern C++
3181// | | |__ | | | | | | version 3.11.3
3182// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3183//
3184// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3185// SPDX-FileCopyrightText: 2018 The Abseil Authors
3186// SPDX-License-Identifier: MIT
3187
3188
3189
3190#include <array> // array
3191#include <cstddef> // size_t
3192#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3193#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3194
3195// #include <nlohmann/detail/macro_scope.hpp>
3196
3197
3199namespace detail
3200{
3201
3202template<typename T>
3203using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3204
3205#ifdef JSON_HAS_CPP_14
3206
3207// the following utilities are natively available in C++14
3208using std::enable_if_t;
3209using std::index_sequence;
3210using std::make_index_sequence;
3211using std::index_sequence_for;
3212
3213#else
3214
3215// alias templates to reduce boilerplate
3216template<bool B, typename T = void>
3217using enable_if_t = typename std::enable_if<B, T>::type;
3218
3219// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3220// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3221
3223
3224// integer_sequence
3225//
3226// Class template representing a compile-time integer sequence. An instantiation
3227// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3228// type through its template arguments (which is a common need when
3229// working with C++11 variadic templates). `absl::integer_sequence` is designed
3230// to be a drop-in replacement for C++14's `std::integer_sequence`.
3231//
3232// Example:
3233//
3234// template< class T, T... Ints >
3235// void user_function(integer_sequence<T, Ints...>);
3236//
3237// int main()
3238// {
3239// // user_function's `T` will be deduced to `int` and `Ints...`
3240// // will be deduced to `0, 1, 2, 3, 4`.
3241// user_function(make_integer_sequence<int, 5>());
3242// }
3243template <typename T, T... Ints>
3245{
3246 using value_type = T;
3247 static constexpr std::size_t size() noexcept
3248 {
3249 return sizeof...(Ints);
3250 }
3251};
3252
3253// index_sequence
3254//
3255// A helper template for an `integer_sequence` of `size_t`,
3256// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3257// `std::index_sequence`.
3258template <size_t... Ints>
3259using index_sequence = integer_sequence<size_t, Ints...>;
3260
3262{
3263
3264template <typename Seq, size_t SeqSize, size_t Rem>
3265struct Extend;
3266
3267// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3268template <typename T, T... Ints, size_t SeqSize>
3269struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3270{
3271 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3272};
3273
3274template <typename T, T... Ints, size_t SeqSize>
3275struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3276{
3277 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3278};
3279
3280// Recursion helper for 'make_integer_sequence<T, N>'.
3281// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3282template <typename T, size_t N>
3283struct Gen
3284{
3285 using type =
3286 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3287};
3288
3289template <typename T>
3290struct Gen<T, 0>
3291{
3293};
3294
3295} // namespace utility_internal
3296
3297// Compile-time sequences of integers
3298
3299// make_integer_sequence
3300//
3301// This template alias is equivalent to
3302// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3303// replacement for C++14's `std::make_integer_sequence`.
3304template <typename T, T N>
3306
3307// make_index_sequence
3308//
3309// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3310// and is designed to be a drop-in replacement for C++14's
3311// `std::make_index_sequence`.
3312template <size_t N>
3314
3315// index_sequence_for
3316//
3317// Converts a typename pack into an index sequence of the same length, and
3318// is designed to be a drop-in replacement for C++14's
3319// `std::index_sequence_for()`
3320template <typename... Ts>
3322
3324
3325#endif
3326
3327// dispatch utility (taken from ranges-v3)
3328template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3329template<> struct priority_tag<0> {};
3330
3331// taken from ranges-v3
3332template<typename T>
3334{
3335 static JSON_INLINE_VARIABLE constexpr T value{};
3336};
3337
3338#ifndef JSON_HAS_CPP_17
3339 template<typename T>
3341#endif
3342
3343template<typename T, typename... Args>
3344constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3345{
3346 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3347}
3348
3349} // namespace detail
3351
3352// #include <nlohmann/detail/meta/type_traits.hpp>
3353// __ _____ _____ _____
3354// __| | __| | | | JSON for Modern C++
3355// | | |__ | | | | | | version 3.11.3
3356// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3357//
3358// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3359// SPDX-License-Identifier: MIT
3360
3361
3362
3363#include <limits> // numeric_limits
3364#include <string> // char_traits
3365#include <tuple> // tuple
3366#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3367#include <utility> // declval
3368
3369// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3370// __ _____ _____ _____
3371// __| | __| | | | JSON for Modern C++
3372// | | |__ | | | | | | version 3.11.3
3373// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3374//
3375// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3376// SPDX-License-Identifier: MIT
3377
3378
3379
3380#include <iterator> // random_access_iterator_tag
3381
3382// #include <nlohmann/detail/abi_macros.hpp>
3383
3384// #include <nlohmann/detail/meta/void_t.hpp>
3385
3386// #include <nlohmann/detail/meta/cpp_future.hpp>
3387
3388
3390namespace detail
3391{
3392
3393template<typename It, typename = void>
3395
3396template<typename It>
3398 It,
3399 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3400 typename It::reference, typename It::iterator_category >>
3401{
3402 using difference_type = typename It::difference_type;
3403 using value_type = typename It::value_type;
3404 using pointer = typename It::pointer;
3405 using reference = typename It::reference;
3406 using iterator_category = typename It::iterator_category;
3407};
3408
3409// This is required as some compilers implement std::iterator_traits in a way that
3410// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3411template<typename T, typename = void>
3413{
3414};
3415
3416template<typename T>
3417struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3418 : iterator_types<T>
3419{
3420};
3421
3422template<typename T>
3424{
3425 using iterator_category = std::random_access_iterator_tag;
3426 using value_type = T;
3427 using difference_type = ptrdiff_t;
3428 using pointer = T*;
3429 using reference = T&;
3430};
3431
3432} // namespace detail
3434
3435// #include <nlohmann/detail/macro_scope.hpp>
3436
3437// #include <nlohmann/detail/meta/call_std/begin.hpp>
3438// __ _____ _____ _____
3439// __| | __| | | | JSON for Modern C++
3440// | | |__ | | | | | | version 3.11.3
3441// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3442//
3443// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3444// SPDX-License-Identifier: MIT
3445
3446
3447
3448// #include <nlohmann/detail/macro_scope.hpp>
3449
3450
3452
3454
3456
3457// #include <nlohmann/detail/meta/call_std/end.hpp>
3458// __ _____ _____ _____
3459// __| | __| | | | JSON for Modern C++
3460// | | |__ | | | | | | version 3.11.3
3461// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3462//
3463// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3464// SPDX-License-Identifier: MIT
3465
3466
3467
3468// #include <nlohmann/detail/macro_scope.hpp>
3469
3470
3472
3474
3476
3477// #include <nlohmann/detail/meta/cpp_future.hpp>
3478
3479// #include <nlohmann/detail/meta/detected.hpp>
3480
3481// #include <nlohmann/json_fwd.hpp>
3482// __ _____ _____ _____
3483// __| | __| | | | JSON for Modern C++
3484// | | |__ | | | | | | version 3.11.3
3485// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3486//
3487// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3488// SPDX-License-Identifier: MIT
3489
3490#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3491 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3492
3493 #include <cstdint> // int64_t, uint64_t
3494 #include <map> // map
3495 #include <memory> // allocator
3496 #include <string> // string
3497 #include <vector> // vector
3498
3499 // #include <nlohmann/detail/abi_macros.hpp>
3500
3501
3508
3516 template<typename T = void, typename SFINAE = void>
3517 struct adl_serializer;
3518
3521 template<template<typename U, typename V, typename... Args> class ObjectType =
3522 std::map,
3523 template<typename U, typename... Args> class ArrayType = std::vector,
3524 class StringType = std::string, class BooleanType = bool,
3525 class NumberIntegerType = std::int64_t,
3526 class NumberUnsignedType = std::uint64_t,
3527 class NumberFloatType = double,
3528 template<typename U> class AllocatorType = std::allocator,
3529 template<typename T, typename SFINAE = void> class JSONSerializer =
3531 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3532 class CustomBaseClass = void>
3533 class basic_json;
3534
3537 template<typename RefStringType>
3538 class json_pointer;
3539
3545
3548 template<class Key, class T, class IgnoredLess, class Allocator>
3549 struct ordered_map;
3550
3554
3556
3557#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3558
3559
3569namespace detail
3570{
3571
3573// helpers //
3575
3576// Note to maintainers:
3577//
3578// Every trait in this file expects a non CV-qualified type.
3579// The only exceptions are in the 'aliases for detected' section
3580// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3581//
3582// In this case, T has to be properly CV-qualified to constraint the function arguments
3583// (e.g. to_json(BasicJsonType&, const T&))
3584
3585template<typename> struct is_basic_json : std::false_type {};
3586
3588struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3589
3590// used by exceptions create() member functions
3591// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3592// false_type otherwise
3593template<typename BasicJsonContext>
3595 std::integral_constant < bool,
3596 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3597 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3598{};
3599
3601// json_ref helpers //
3603
3604template<typename>
3605class json_ref;
3606
3607template<typename>
3608struct is_json_ref : std::false_type {};
3609
3610template<typename T>
3611struct is_json_ref<json_ref<T>> : std::true_type {};
3612
3614// aliases for detected //
3616
3617template<typename T>
3618using mapped_type_t = typename T::mapped_type;
3619
3620template<typename T>
3621using key_type_t = typename T::key_type;
3622
3623template<typename T>
3624using value_type_t = typename T::value_type;
3625
3626template<typename T>
3627using difference_type_t = typename T::difference_type;
3628
3629template<typename T>
3630using pointer_t = typename T::pointer;
3631
3632template<typename T>
3633using reference_t = typename T::reference;
3634
3635template<typename T>
3636using iterator_category_t = typename T::iterator_category;
3637
3638template<typename T, typename... Args>
3639using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3640
3641template<typename T, typename... Args>
3642using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3643
3644template<typename T, typename U>
3645using get_template_function = decltype(std::declval<T>().template get<U>());
3646
3647// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3648template<typename BasicJsonType, typename T, typename = void>
3649struct has_from_json : std::false_type {};
3650
3651// trait checking if j.get<T> is valid
3652// use this trait instead of std::is_constructible or std::is_convertible,
3653// both rely on, or make use of implicit conversions, and thus fail when T
3654// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3655template <typename BasicJsonType, typename T>
3660
3661template<typename BasicJsonType, typename T>
3662struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3663{
3664 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3665
3666 static constexpr bool value =
3668 const BasicJsonType&, T&>::value;
3669};
3670
3671// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3672// this overload is used for non-default-constructible user-defined-types
3673template<typename BasicJsonType, typename T, typename = void>
3674struct has_non_default_from_json : std::false_type {};
3675
3676template<typename BasicJsonType, typename T>
3677struct has_non_default_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 =
3683 const BasicJsonType&>::value;
3684};
3685
3686// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3687// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3688template<typename BasicJsonType, typename T, typename = void>
3689struct has_to_json : std::false_type {};
3690
3691template<typename BasicJsonType, typename T>
3692struct has_to_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<void, to_json_function, serializer, BasicJsonType&,
3698 T>::value;
3699};
3700
3701template<typename T>
3702using detect_key_compare = typename T::key_compare;
3703
3704template<typename T>
3705struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3706
3707// obtains the actual object key comparator
3708template<typename BasicJsonType>
3710{
3711 using object_t = typename BasicJsonType::object_t;
3712 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3713 using type = typename std::conditional < has_key_compare<object_t>::value,
3714 typename object_t::key_compare, object_comparator_t>::type;
3715};
3716
3717template<typename BasicJsonType>
3719
3721// char_traits //
3723
3724// Primary template of char_traits calls std char_traits
3725template<typename T>
3726struct char_traits : std::char_traits<T>
3727{};
3728
3729// Explicitly define char traits for unsigned char since it is not standard
3730template<>
3731struct char_traits<unsigned char> : std::char_traits<char>
3732{
3733 using char_type = unsigned char;
3734 using int_type = uint64_t;
3735
3736 // Redefine to_int_type function
3737 static int_type to_int_type(char_type c) noexcept
3738 {
3739 return static_cast<int_type>(c);
3740 }
3741
3743 {
3744 return static_cast<char_type>(i);
3745 }
3746
3747 static constexpr int_type eof() noexcept
3748 {
3749 return static_cast<int_type>(std::char_traits<char>::eof());
3750 }
3751};
3752
3753// Explicitly define char traits for signed char since it is not standard
3754template<>
3755struct char_traits<signed char> : std::char_traits<char>
3756{
3757 using char_type = signed char;
3758 using int_type = uint64_t;
3759
3760 // Redefine to_int_type function
3761 static int_type to_int_type(char_type c) noexcept
3762 {
3763 return static_cast<int_type>(c);
3764 }
3765
3767 {
3768 return static_cast<char_type>(i);
3769 }
3770
3771 static constexpr int_type eof() noexcept
3772 {
3773 return static_cast<int_type>(std::char_traits<char>::eof());
3774 }
3775};
3776
3778// is_ functions //
3780
3781// https://en.cppreference.com/w/cpp/types/conjunction
3782template<class...> struct conjunction : std::true_type { };
3783template<class B> struct conjunction<B> : B { };
3784template<class B, class... Bn>
3785struct conjunction<B, Bn...>
3786: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3787
3788// https://en.cppreference.com/w/cpp/types/negation
3789template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3790
3791// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3792// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3793// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3794template <typename T>
3795struct is_default_constructible : std::is_default_constructible<T> {};
3796
3797template <typename T1, typename T2>
3798struct is_default_constructible<std::pair<T1, T2>>
3799 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3800
3801template <typename T1, typename T2>
3802struct is_default_constructible<const std::pair<T1, T2>>
3803 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3804
3805template <typename... Ts>
3806struct is_default_constructible<std::tuple<Ts...>>
3807 : conjunction<is_default_constructible<Ts>...> {};
3808
3809template <typename... Ts>
3810struct is_default_constructible<const std::tuple<Ts...>>
3811 : conjunction<is_default_constructible<Ts>...> {};
3812
3813template <typename T, typename... Args>
3814struct is_constructible : std::is_constructible<T, Args...> {};
3815
3816template <typename T1, typename T2>
3817struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3818
3819template <typename T1, typename T2>
3820struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3821
3822template <typename... Ts>
3823struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3824
3825template <typename... Ts>
3826struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3827
3828template<typename T, typename = void>
3829struct is_iterator_traits : std::false_type {};
3830
3831template<typename T>
3845
3846template<typename T>
3848{
3849 private:
3850 using t_ref = typename std::add_lvalue_reference<T>::type;
3851
3854
3855 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3856 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3857 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3858 static constexpr auto is_iterator_begin =
3860
3861 public:
3862 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3863};
3864
3865template<typename R>
3866using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3867
3868template<typename T>
3870
3871// The following implementation of is_complete_type is taken from
3872// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3873// and is written by Xiang Fan who agreed to using it in this library.
3874
3875template<typename T, typename = void>
3876struct is_complete_type : std::false_type {};
3877
3878template<typename T>
3879struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3880
3881template<typename BasicJsonType, typename CompatibleObjectType,
3882 typename = void>
3883struct is_compatible_object_type_impl : std::false_type {};
3884
3885template<typename BasicJsonType, typename CompatibleObjectType>
3887 BasicJsonType, CompatibleObjectType,
3888 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3889 is_detected<key_type_t, CompatibleObjectType>::value >>
3890{
3891 using object_t = typename BasicJsonType::object_t;
3892
3893 // macOS's is_constructible does not play well with nonesuch...
3894 static constexpr bool value =
3895 is_constructible<typename object_t::key_type,
3896 typename CompatibleObjectType::key_type>::value &&
3897 is_constructible<typename object_t::mapped_type,
3898 typename CompatibleObjectType::mapped_type>::value;
3899};
3900
3901template<typename BasicJsonType, typename CompatibleObjectType>
3903 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3904
3905template<typename BasicJsonType, typename ConstructibleObjectType,
3906 typename = void>
3907struct is_constructible_object_type_impl : std::false_type {};
3908
3909template<typename BasicJsonType, typename ConstructibleObjectType>
3911 BasicJsonType, ConstructibleObjectType,
3912 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3913 is_detected<key_type_t, ConstructibleObjectType>::value >>
3914{
3915 using object_t = typename BasicJsonType::object_t;
3916
3917 static constexpr bool value =
3919 (std::is_move_assignable<ConstructibleObjectType>::value ||
3920 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3921 (is_constructible<typename ConstructibleObjectType::key_type,
3922 typename object_t::key_type>::value &&
3923 std::is_same <
3924 typename object_t::mapped_type,
3925 typename ConstructibleObjectType::mapped_type >::value)) ||
3926 (has_from_json<BasicJsonType,
3927 typename ConstructibleObjectType::mapped_type>::value ||
3929 BasicJsonType,
3930 typename ConstructibleObjectType::mapped_type >::value);
3931};
3932
3933template<typename BasicJsonType, typename ConstructibleObjectType>
3935 : is_constructible_object_type_impl<BasicJsonType,
3936 ConstructibleObjectType> {};
3937
3938template<typename BasicJsonType, typename CompatibleStringType>
3944
3945template<typename BasicJsonType, typename ConstructibleStringType>
3947{
3948 // launder type through decltype() to fix compilation failure on ICPC
3949#ifdef __INTEL_COMPILER
3950 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3951#else
3952 using laundered_type = ConstructibleStringType;
3953#endif
3954
3955 static constexpr auto value =
3956 conjunction <
3958 is_detected_exact<typename BasicJsonType::string_t::value_type,
3960};
3961
3962template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3963struct is_compatible_array_type_impl : std::false_type {};
3964
3965template<typename BasicJsonType, typename CompatibleArrayType>
3967 BasicJsonType, CompatibleArrayType,
3968 enable_if_t <
3969 is_detected<iterator_t, CompatibleArrayType>::value&&
3970 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3971// special case for types like std::filesystem::path whose iterator's value_type are themselves
3972// c.f. https://github.com/nlohmann/json/pull/3073
3973 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3974{
3975 static constexpr bool value =
3976 is_constructible<BasicJsonType,
3978};
3979
3980template<typename BasicJsonType, typename CompatibleArrayType>
3982 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3983
3984template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3985struct is_constructible_array_type_impl : std::false_type {};
3986
3987template<typename BasicJsonType, typename ConstructibleArrayType>
3989 BasicJsonType, ConstructibleArrayType,
3990 enable_if_t<std::is_same<ConstructibleArrayType,
3991 typename BasicJsonType::value_type>::value >>
3992 : std::true_type {};
3993
3994template<typename BasicJsonType, typename ConstructibleArrayType>
3996 BasicJsonType, ConstructibleArrayType,
3997 enable_if_t < !std::is_same<ConstructibleArrayType,
3998 typename BasicJsonType::value_type>::value&&
3999 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4000 is_default_constructible<ConstructibleArrayType>::value&&
4001(std::is_move_assignable<ConstructibleArrayType>::value ||
4002 std::is_copy_assignable<ConstructibleArrayType>::value)&&
4003is_detected<iterator_t, ConstructibleArrayType>::value&&
4004is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
4005is_detected<range_value_t, ConstructibleArrayType>::value&&
4006// special case for types like std::filesystem::path whose iterator's value_type are themselves
4007// c.f. https://github.com/nlohmann/json/pull/3073
4008!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
4010detected_t<range_value_t, ConstructibleArrayType >>::value >>
4011{
4013
4014 static constexpr bool value =
4015 std::is_same<value_type,
4016 typename BasicJsonType::array_t::value_type>::value ||
4017 has_from_json<BasicJsonType,
4020 BasicJsonType,
4022};
4023
4024template<typename BasicJsonType, typename ConstructibleArrayType>
4026 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
4027
4028template<typename RealIntegerType, typename CompatibleNumberIntegerType,
4029 typename = void>
4030struct is_compatible_integer_type_impl : std::false_type {};
4031
4032template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4034 RealIntegerType, CompatibleNumberIntegerType,
4035 enable_if_t < std::is_integral<RealIntegerType>::value&&
4036 std::is_integral<CompatibleNumberIntegerType>::value&&
4037 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
4038{
4039 // is there an assert somewhere on overflows?
4040 using RealLimits = std::numeric_limits<RealIntegerType>;
4041 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
4042
4043 static constexpr auto value =
4044 is_constructible<RealIntegerType,
4045 CompatibleNumberIntegerType>::value &&
4046 CompatibleLimits::is_integer &&
4047 RealLimits::is_signed == CompatibleLimits::is_signed;
4048};
4049
4050template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4052 : is_compatible_integer_type_impl<RealIntegerType,
4053 CompatibleNumberIntegerType> {};
4054
4055template<typename BasicJsonType, typename CompatibleType, typename = void>
4056struct is_compatible_type_impl: std::false_type {};
4057
4058template<typename BasicJsonType, typename CompatibleType>
4060 BasicJsonType, CompatibleType,
4061 enable_if_t<is_complete_type<CompatibleType>::value >>
4062{
4063 static constexpr bool value =
4065};
4066
4067template<typename BasicJsonType, typename CompatibleType>
4069 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
4070
4071template<typename T1, typename T2>
4072struct is_constructible_tuple : std::false_type {};
4073
4074template<typename T1, typename... Args>
4075struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
4076
4077template<typename BasicJsonType, typename T>
4078struct is_json_iterator_of : std::false_type {};
4079
4080template<typename BasicJsonType>
4081struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
4082
4083template<typename BasicJsonType>
4084struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
4085{};
4086
4087// checks if a given type T is a template specialization of Primary
4088template<template <typename...> class Primary, typename T>
4089struct is_specialization_of : std::false_type {};
4090
4091template<template <typename...> class Primary, typename... Args>
4092struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
4093
4094template<typename T>
4096
4097// checks if A and B are comparable using Compare functor
4098template<typename Compare, typename A, typename B, typename = void>
4099struct is_comparable : std::false_type {};
4100
4101template<typename Compare, typename A, typename B>
4102struct is_comparable<Compare, A, B, void_t<
4103decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
4104decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
4105>> : std::true_type {};
4106
4107template<typename T>
4108using detect_is_transparent = typename T::is_transparent;
4109
4110// type trait to check if KeyType can be used as object key (without a BasicJsonType)
4111// see is_usable_as_basic_json_key_type below
4112template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4113 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4114using is_usable_as_key_type = typename std::conditional <
4116 && !(ExcludeObjectKeyType && std::is_same<KeyType,
4117 ObjectKeyType>::value)
4118 && (!RequireTransparentComparator
4119 || is_detected <detect_is_transparent, Comparator>::value)
4121 std::true_type,
4122 std::false_type >::type;
4123
4124// type trait to check if KeyType can be used as object key
4125// true if:
4126// - KeyType is comparable with BasicJsonType::object_t::key_type
4127// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4128// - the comparator is transparent or RequireTransparentComparator is false
4129// - KeyType is not a JSON iterator or json_pointer
4130template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4131 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4132using is_usable_as_basic_json_key_type = typename std::conditional <
4133 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4134 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4135 RequireTransparentComparator, ExcludeObjectKeyType>::value
4137 std::true_type,
4138 std::false_type >::type;
4139
4140template<typename ObjectType, typename KeyType>
4141using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4142
4143// type trait to check if object_t has an erase() member functions accepting KeyType
4144template<typename BasicJsonType, typename KeyType>
4145using has_erase_with_key_type = typename std::conditional <
4146 is_detected <
4148 typename BasicJsonType::object_t, KeyType >::value,
4149 std::true_type,
4150 std::false_type >::type;
4151
4152// a naive helper to check if a type is an ordered_map (exploits the fact that
4153// ordered_map inherits capacity() from std::vector)
4154template <typename T>
4156{
4157 using one = char;
4158
4159 struct two
4160 {
4161 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4162 };
4163
4164 template <typename C> static one test( decltype(&C::capacity) ) ;
4165 template <typename C> static two test(...);
4166
4167 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4168};
4169
4170// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4171template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4173{
4174 return static_cast<T>(value);
4175}
4176
4177template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4179{
4180 return value;
4181}
4182
4183template<typename... Types>
4185
4186template<typename... Types>
4188
4189template<typename... Types>
4191
4192// there's a disjunction trait in another PR; replace when merged
4193template<typename... Types>
4194using same_sign = std::integral_constant < bool,
4195 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4196
4197template<typename OfType, typename T>
4198using never_out_of_range = std::integral_constant < bool,
4199 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4200 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4201
4202template<typename OfType, typename T,
4203 bool OfTypeSigned = std::is_signed<OfType>::value,
4204 bool TSigned = std::is_signed<T>::value>
4206
4207template<typename OfType, typename T>
4208struct value_in_range_of_impl2<OfType, T, false, false>
4209{
4210 static constexpr bool test(T val)
4211 {
4212 using CommonType = typename std::common_type<OfType, T>::type;
4213 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4214 }
4215};
4216
4217template<typename OfType, typename T>
4218struct value_in_range_of_impl2<OfType, T, true, false>
4219{
4220 static constexpr bool test(T val)
4221 {
4222 using CommonType = typename std::common_type<OfType, T>::type;
4223 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4224 }
4225};
4226
4227template<typename OfType, typename T>
4228struct value_in_range_of_impl2<OfType, T, false, true>
4229{
4230 static constexpr bool test(T val)
4231 {
4232 using CommonType = typename std::common_type<OfType, T>::type;
4233 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4234 }
4235};
4236
4237template<typename OfType, typename T>
4238struct value_in_range_of_impl2<OfType, T, true, true>
4239{
4240 static constexpr bool test(T val)
4241 {
4242 using CommonType = typename std::common_type<OfType, T>::type;
4243 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4244 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4245 }
4246};
4247
4248template<typename OfType, typename T,
4249 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4252
4253template<typename OfType, typename T>
4254struct value_in_range_of_impl1<OfType, T, false>
4255{
4256 static constexpr bool test(T val)
4257 {
4259 }
4260};
4261
4262template<typename OfType, typename T>
4263struct value_in_range_of_impl1<OfType, T, true>
4264{
4265 static constexpr bool test(T /*val*/)
4266 {
4267 return true;
4268 }
4269};
4270
4271template<typename OfType, typename T>
4272constexpr bool value_in_range_of(T val)
4273{
4275}
4276
4277template<bool Value>
4278using bool_constant = std::integral_constant<bool, Value>;
4279
4281// is_c_string
4283
4284namespace impl
4285{
4286
4287template<typename T>
4288constexpr bool is_c_string()
4289{
4290 using TUnExt = typename std::remove_extent<T>::type;
4291 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4292 using TUnPtr = typename std::remove_pointer<T>::type;
4293 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4294 return
4295 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4296 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4297}
4298
4299} // namespace impl
4300
4301// checks whether T is a [cv] char */[cv] char[] C string
4302template<typename T>
4303struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4304
4305template<typename T>
4307
4309// is_transparent
4311
4312namespace impl
4313{
4314
4315template<typename T>
4316constexpr bool is_transparent()
4317{
4319}
4320
4321} // namespace impl
4322
4323// checks whether T has a member named is_transparent
4324template<typename T>
4325struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4326
4328
4329} // namespace detail
4331
4332// #include <nlohmann/detail/string_concat.hpp>
4333// __ _____ _____ _____
4334// __| | __| | | | JSON for Modern C++
4335// | | |__ | | | | | | version 3.11.3
4336// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4337//
4338// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4339// SPDX-License-Identifier: MIT
4340
4341
4342
4343#include <cstring> // strlen
4344#include <string> // string
4345#include <utility> // forward
4346
4347// #include <nlohmann/detail/meta/cpp_future.hpp>
4348
4349// #include <nlohmann/detail/meta/detected.hpp>
4350
4351
4353namespace detail
4354{
4355
4356inline std::size_t concat_length()
4357{
4358 return 0;
4359}
4360
4361template<typename... Args>
4362inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4363
4364template<typename StringType, typename... Args>
4365inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4366
4367template<typename... Args>
4368inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4369{
4370 return 1 + concat_length(rest...);
4371}
4372
4373template<typename... Args>
4374inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4375{
4376 // cppcheck-suppress ignoredReturnValue
4377 return ::strlen(cstr) + concat_length(rest...);
4378}
4379
4380template<typename StringType, typename... Args>
4381inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4382{
4383 return str.size() + concat_length(rest...);
4384}
4385
4386template<typename OutStringType>
4387inline void concat_into(OutStringType& /*out*/)
4388{}
4389
4390template<typename StringType, typename Arg>
4391using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4392
4393template<typename StringType, typename Arg>
4395
4396template<typename StringType, typename Arg>
4397using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4398
4399template<typename StringType, typename Arg>
4401
4402template<typename StringType, typename Arg>
4403using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4404
4405template<typename StringType, typename Arg>
4407
4408template<typename StringType, typename Arg>
4409using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4410
4411template<typename StringType, typename Arg>
4413
4414template < typename OutStringType, typename Arg, typename... Args,
4415 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4417inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4418
4419template < typename OutStringType, typename Arg, typename... Args,
4420 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4423inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4424
4425template < typename OutStringType, typename Arg, typename... Args,
4426 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4430inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4431
4432template<typename OutStringType, typename Arg, typename... Args,
4434inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4435{
4436 out.append(std::forward<Arg>(arg));
4437 concat_into(out, std::forward<Args>(rest)...);
4438}
4439
4440template < typename OutStringType, typename Arg, typename... Args,
4441 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4442 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4443inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4444{
4445 out += std::forward<Arg>(arg);
4446 concat_into(out, std::forward<Args>(rest)...);
4447}
4448
4449template < typename OutStringType, typename Arg, typename... Args,
4450 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4453inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4454{
4455 out.append(arg.begin(), arg.end());
4456 concat_into(out, std::forward<Args>(rest)...);
4457}
4458
4459template < typename OutStringType, typename Arg, typename... Args,
4460 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4461 && !detect_string_can_append_op<OutStringType, Arg>::value
4462 && !detect_string_can_append_iter<OutStringType, Arg>::value
4463 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4464inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4465{
4466 out.append(arg.data(), arg.size());
4467 concat_into(out, std::forward<Args>(rest)...);
4468}
4469
4470template<typename OutStringType = std::string, typename... Args>
4471inline OutStringType concat(Args && ... args)
4472{
4473 OutStringType str;
4474 str.reserve(concat_length(args...));
4475 concat_into(str, std::forward<Args>(args)...);
4476 return str;
4477}
4478
4479} // namespace detail
4481
4482
4483// With -Wweak-vtables, Clang will complain about the exception classes as they
4484// have no out-of-line virtual method definitions and their vtable will be
4485// emitted in every translation unit. This issue cannot be fixed with a
4486// header-only library as there is no implementation file to move these
4487// functions to. As a result, we suppress this warning here to avoid client
4488// code to stumble over this. See https://github.com/nlohmann/json/issues/4087
4489// for a discussion.
4490#if defined(__clang__)
4491 #pragma clang diagnostic push
4492 #pragma clang diagnostic ignored "-Wweak-vtables"
4493#endif
4494
4496namespace detail
4497{
4498
4500// exceptions //
4502
4505class exception : public std::exception
4506{
4507 public:
4509 const char* what() const noexcept override
4510 {
4511 return m.what();
4512 }
4513
4515 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4516
4517 protected:
4519 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4520
4521 static std::string name(const std::string& ename, int id_)
4522 {
4523 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4524 }
4525
4526 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4527 {
4528 return "";
4529 }
4530
4531 template<typename BasicJsonType>
4532 static std::string diagnostics(const BasicJsonType* leaf_element)
4533 {
4534#if JSON_DIAGNOSTICS
4535 std::vector<std::string> tokens;
4536 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4537 {
4538 switch (current->m_parent->type())
4539 {
4540 case value_t::array:
4541 {
4542 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4543 {
4544 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4545 {
4546 tokens.emplace_back(std::to_string(i));
4547 break;
4548 }
4549 }
4550 break;
4551 }
4552
4553 case value_t::object:
4554 {
4555 for (const auto& element : *current->m_parent->m_data.m_value.object)
4556 {
4557 if (&element.second == current)
4558 {
4559 tokens.emplace_back(element.first.c_str());
4560 break;
4561 }
4562 }
4563 break;
4564 }
4565
4566 case value_t::null: // LCOV_EXCL_LINE
4567 case value_t::string: // LCOV_EXCL_LINE
4568 case value_t::boolean: // LCOV_EXCL_LINE
4569 case value_t::number_integer: // LCOV_EXCL_LINE
4570 case value_t::number_unsigned: // LCOV_EXCL_LINE
4571 case value_t::number_float: // LCOV_EXCL_LINE
4572 case value_t::binary: // LCOV_EXCL_LINE
4573 case value_t::discarded: // LCOV_EXCL_LINE
4574 default: // LCOV_EXCL_LINE
4575 break; // LCOV_EXCL_LINE
4576 }
4577 }
4578
4579 if (tokens.empty())
4580 {
4581 return "";
4582 }
4583
4584 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4585 [](const std::string & a, const std::string & b)
4586 {
4587 return concat(a, '/', detail::escape(b));
4588 });
4589
4590 return concat('(', str, ") ", get_byte_positions(leaf_element));
4591#else
4592 return get_byte_positions(leaf_element);
4593#endif
4594 }
4595
4596 private:
4598 std::runtime_error m;
4599#if JSON_DIAGNOSTIC_POSITIONS
4600 template<typename BasicJsonType>
4601 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4602 {
4603 if ((leaf_element->start_pos() != std::string::npos) && (leaf_element->end_pos() != std::string::npos))
4604 {
4605 return concat("(bytes ", std::to_string(leaf_element->start_pos()), "-", std::to_string(leaf_element->end_pos()), ") ");
4606 }
4607 return "";
4608 }
4609#else
4610 template<typename BasicJsonType>
4611 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4612 {
4613 static_cast<void>(leaf_element);
4614 return "";
4615 }
4616#endif
4617};
4618
4622{
4623 public:
4633 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4634 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4635 {
4636 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4637 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4638 return {id_, pos.chars_read_total, w.c_str()};
4639 }
4640
4641 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4642 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4643 {
4644 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4645 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4646 ": ", exception::diagnostics(context), what_arg);
4647 return {id_, byte_, w.c_str()};
4648 }
4649
4659 const std::size_t byte;
4660
4661 private:
4662 parse_error(int id_, std::size_t byte_, const char* what_arg)
4663 : exception(id_, what_arg), byte(byte_) {}
4664
4665 static std::string position_string(const position_t& pos)
4666 {
4667 return concat(" at line ", std::to_string(pos.lines_read + 1),
4668 ", column ", std::to_string(pos.chars_read_current_line));
4669 }
4670};
4671
4675{
4676 public:
4677 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4678 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4679 {
4680 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4681 return {id_, w.c_str()};
4682 }
4683
4684 private:
4686 invalid_iterator(int id_, const char* what_arg)
4687 : exception(id_, what_arg) {}
4688};
4689
4692class type_error : public exception
4693{
4694 public:
4695 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4696 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4697 {
4698 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4699 return {id_, w.c_str()};
4700 }
4701
4702 private:
4704 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4705};
4706
4710{
4711 public:
4712 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4713 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4714 {
4715 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4716 return {id_, w.c_str()};
4717 }
4718
4719 private:
4721 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4722};
4723
4727{
4728 public:
4729 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4730 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4731 {
4732 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4733 return {id_, w.c_str()};
4734 }
4735
4736 private:
4738 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4739};
4740
4741} // namespace detail
4743
4744#if defined(__clang__)
4745 #pragma clang diagnostic pop
4746#endif
4747
4748// #include <nlohmann/detail/macro_scope.hpp>
4749
4750// #include <nlohmann/detail/meta/cpp_future.hpp>
4751
4752// #include <nlohmann/detail/meta/identity_tag.hpp>
4753// __ _____ _____ _____
4754// __| | __| | | | JSON for Modern C++
4755// | | |__ | | | | | | version 3.11.3
4756// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4757//
4758// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4759// SPDX-License-Identifier: MIT
4760
4761
4762
4763// #include <nlohmann/detail/abi_macros.hpp>
4764
4765
4767namespace detail
4768{
4769
4770// dispatching helper struct
4771template <class T> struct identity_tag {};
4772
4773} // namespace detail
4775
4776// #include <nlohmann/detail/meta/std_fs.hpp>
4777// __ _____ _____ _____
4778// __| | __| | | | JSON for Modern C++
4779// | | |__ | | | | | | version 3.11.3
4780// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4781//
4782// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4783// SPDX-License-Identifier: MIT
4784
4785
4786
4787// #include <nlohmann/detail/macro_scope.hpp>
4788
4789
4790#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4791#include <experimental/filesystem>
4793namespace detail
4794{
4795namespace std_fs = std::experimental::filesystem;
4796} // namespace detail
4798#elif JSON_HAS_FILESYSTEM
4799#include <filesystem> // NOLINT(build/c++17)
4801namespace detail
4802{
4803namespace std_fs = std::filesystem;
4804} // namespace detail
4806#endif
4807
4808// #include <nlohmann/detail/meta/type_traits.hpp>
4809
4810// #include <nlohmann/detail/string_concat.hpp>
4811
4812// #include <nlohmann/detail/value_t.hpp>
4813
4814
4816namespace detail
4817{
4818
4819template<typename BasicJsonType>
4820inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4821{
4822 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4823 {
4824 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4825 }
4826 n = nullptr;
4827}
4828
4829#ifdef JSON_HAS_CPP_17
4830#ifndef JSON_USE_IMPLICIT_CONVERSIONS
4831template<typename BasicJsonType, typename T>
4832void from_json(const BasicJsonType& j, std::optional<T>& opt)
4833{
4834 if (j.is_null())
4835 {
4836 opt = std::nullopt;
4837 }
4838 else
4839 {
4840 opt.emplace(j.template get<T>());
4841 }
4842}
4843
4844#endif // JSON_USE_IMPLICIT_CONVERSIONS
4845#endif // JSON_HAS_CPP_17
4846
4847// overloads for basic_json template parameters
4848template < typename BasicJsonType, typename ArithmeticType,
4849 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4850 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4851 int > = 0 >
4852void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4853{
4854 switch (static_cast<value_t>(j))
4855 {
4857 {
4858 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4859 break;
4860 }
4862 {
4863 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4864 break;
4865 }
4867 {
4868 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4869 break;
4870 }
4871
4872 case value_t::null:
4873 case value_t::object:
4874 case value_t::array:
4875 case value_t::string:
4876 case value_t::boolean:
4877 case value_t::binary:
4878 case value_t::discarded:
4879 default:
4880 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4881 }
4882}
4883
4884template<typename BasicJsonType>
4885inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4886{
4887 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4888 {
4889 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4890 }
4891 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4892}
4893
4894template<typename BasicJsonType>
4895inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4896{
4897 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4898 {
4899 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4900 }
4901 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4902}
4903
4904template <
4905 typename BasicJsonType, typename StringType,
4906 enable_if_t <
4907 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4908 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4909 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4910 && !is_json_ref<StringType>::value, int > = 0 >
4911inline void from_json(const BasicJsonType& j, StringType& s)
4912{
4913 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4914 {
4915 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4916 }
4917
4918 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4919}
4920
4921template<typename BasicJsonType>
4922inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4923{
4924 get_arithmetic_value(j, val);
4925}
4926
4927template<typename BasicJsonType>
4928inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4929{
4930 get_arithmetic_value(j, val);
4931}
4932
4933template<typename BasicJsonType>
4934inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4935{
4936 get_arithmetic_value(j, val);
4937}
4938
4939#if !JSON_DISABLE_ENUM_SERIALIZATION
4940template<typename BasicJsonType, typename EnumType,
4941 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4942inline void from_json(const BasicJsonType& j, EnumType& e)
4943{
4944 typename std::underlying_type<EnumType>::type val;
4945 get_arithmetic_value(j, val);
4946 e = static_cast<EnumType>(val);
4947}
4948#endif // JSON_DISABLE_ENUM_SERIALIZATION
4949
4950// forward_list doesn't have an insert method
4951template<typename BasicJsonType, typename T, typename Allocator,
4952 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4953inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4954{
4955 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4956 {
4957 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4958 }
4959 l.clear();
4960 std::transform(j.rbegin(), j.rend(),
4961 std::front_inserter(l), [](const BasicJsonType & i)
4962 {
4963 return i.template get<T>();
4964 });
4965}
4966
4967// valarray doesn't have an insert method
4968template<typename BasicJsonType, typename T,
4969 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4970inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4971{
4972 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4973 {
4974 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4975 }
4976 l.resize(j.size());
4977 std::transform(j.begin(), j.end(), std::begin(l),
4978 [](const BasicJsonType & elem)
4979 {
4980 return elem.template get<T>();
4981 });
4982}
4983
4984template<typename BasicJsonType, typename T, std::size_t N>
4985auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4986-> decltype(j.template get<T>(), void())
4987{
4988 for (std::size_t i = 0; i < N; ++i)
4989 {
4990 arr[i] = j.at(i).template get<T>();
4991 }
4992}
4993
4994template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2>
4995auto from_json(const BasicJsonType& j, T (&arr)[N1][N2]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4996-> decltype(j.template get<T>(), void())
4997{
4998 for (std::size_t i1 = 0; i1 < N1; ++i1)
4999 {
5000 for (std::size_t i2 = 0; i2 < N2; ++i2)
5001 {
5002 arr[i1][i2] = j.at(i1).at(i2).template get<T>();
5003 }
5004 }
5005}
5006
5007template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3>
5008auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5009-> decltype(j.template get<T>(), void())
5010{
5011 for (std::size_t i1 = 0; i1 < N1; ++i1)
5012 {
5013 for (std::size_t i2 = 0; i2 < N2; ++i2)
5014 {
5015 for (std::size_t i3 = 0; i3 < N3; ++i3)
5016 {
5017 arr[i1][i2][i3] = j.at(i1).at(i2).at(i3).template get<T>();
5018 }
5019 }
5020 }
5021}
5022
5023template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3, std::size_t N4>
5024auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3][N4]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5025-> decltype(j.template get<T>(), void())
5026{
5027 for (std::size_t i1 = 0; i1 < N1; ++i1)
5028 {
5029 for (std::size_t i2 = 0; i2 < N2; ++i2)
5030 {
5031 for (std::size_t i3 = 0; i3 < N3; ++i3)
5032 {
5033 for (std::size_t i4 = 0; i4 < N4; ++i4)
5034 {
5035 arr[i1][i2][i3][i4] = j.at(i1).at(i2).at(i3).at(i4).template get<T>();
5036 }
5037 }
5038 }
5039 }
5040}
5041
5042template<typename BasicJsonType>
5043inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
5044{
5045 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
5046}
5047
5048template<typename BasicJsonType, typename T, std::size_t N>
5049auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
5050 priority_tag<2> /*unused*/)
5051-> decltype(j.template get<T>(), void())
5052{
5053 for (std::size_t i = 0; i < N; ++i)
5054 {
5055 arr[i] = j.at(i).template get<T>();
5056 }
5057}
5058
5059template<typename BasicJsonType, typename ConstructibleArrayType,
5061 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5062 int> = 0>
5063auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
5064-> decltype(
5065 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
5067 void())
5068{
5069 using std::end;
5070
5071 ConstructibleArrayType ret;
5072 ret.reserve(j.size());
5073 std::transform(j.begin(), j.end(),
5074 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
5075 {
5076 // get<BasicJsonType>() returns *this, this won't call a from_json
5077 // method when value_type is BasicJsonType
5079 });
5080 arr = std::move(ret);
5081}
5082
5083template<typename BasicJsonType, typename ConstructibleArrayType,
5085 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5086 int> = 0>
5087inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
5088 priority_tag<0> /*unused*/)
5089{
5090 using std::end;
5091
5092 ConstructibleArrayType ret;
5093 std::transform(
5094 j.begin(), j.end(), std::inserter(ret, end(ret)),
5095 [](const BasicJsonType & i)
5096 {
5097 // get<BasicJsonType>() returns *this, this won't call a from_json
5098 // method when value_type is BasicJsonType
5100 });
5101 arr = std::move(ret);
5102}
5103
5104template < typename BasicJsonType, typename ConstructibleArrayType,
5105 enable_if_t <
5106 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
5107 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
5109 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
5110 !is_basic_json<ConstructibleArrayType>::value,
5111 int > = 0 >
5112auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
5113-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
5115void())
5116{
5117 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5118 {
5119 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5120 }
5121
5123}
5124
5125template < typename BasicJsonType, typename T, std::size_t... Idx >
5126std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
5127 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
5128{
5129 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
5130}
5131
5132template < typename BasicJsonType, typename T, std::size_t N >
5133auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
5134-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
5135{
5136 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5137 {
5138 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5139 }
5140
5141 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
5142}
5143
5144template<typename BasicJsonType>
5145inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
5146{
5147 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
5148 {
5149 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
5150 }
5151
5152 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
5153}
5154
5155template<typename BasicJsonType, typename ConstructibleObjectType,
5156 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
5157inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
5158{
5159 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
5160 {
5161 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
5162 }
5163
5164 ConstructibleObjectType ret;
5165 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
5166 using value_type = typename ConstructibleObjectType::value_type;
5167 std::transform(
5168 inner_object->begin(), inner_object->end(),
5169 std::inserter(ret, ret.begin()),
5170 [](typename BasicJsonType::object_t::value_type const & p)
5171 {
5172 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
5173 });
5174 obj = std::move(ret);
5175}
5176
5177// overload for arithmetic types, not chosen for basic_json template arguments
5178// (BooleanType, etc..); note: Is it really necessary to provide explicit
5179// overloads for boolean_t etc. in case of a custom BooleanType which is not
5180// an arithmetic type?
5181template < typename BasicJsonType, typename ArithmeticType,
5182 enable_if_t <
5183 std::is_arithmetic<ArithmeticType>::value&&
5184 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
5185 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
5186 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
5187 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
5188 int > = 0 >
5189inline void from_json(const BasicJsonType& j, ArithmeticType& val)
5190{
5191 switch (static_cast<value_t>(j))
5192 {
5194 {
5195 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
5196 break;
5197 }
5199 {
5200 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5201 break;
5202 }
5204 {
5205 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5206 break;
5207 }
5208 case value_t::boolean:
5209 {
5210 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5211 break;
5212 }
5213
5214 case value_t::null:
5215 case value_t::object:
5216 case value_t::array:
5217 case value_t::string:
5218 case value_t::binary:
5219 case value_t::discarded:
5220 default:
5221 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5222 }
5223}
5224
5225template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5226std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5227{
5228 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5229}
5230
5231template<typename BasicJsonType>
5232std::tuple<> from_json_tuple_impl_base(BasicJsonType& /*unused*/, index_sequence<> /*unused*/)
5233{
5234 return {};
5235}
5236
5237template < typename BasicJsonType, class A1, class A2 >
5238std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5239{
5240 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5241 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5242}
5243
5244template<typename BasicJsonType, typename A1, typename A2>
5245inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5246{
5247 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5248}
5249
5250template<typename BasicJsonType, typename... Args>
5251std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5252{
5253 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5254}
5255
5256template<typename BasicJsonType, typename... Args>
5257inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5258{
5259 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5260}
5261
5262template<typename BasicJsonType, typename TupleRelated>
5263auto from_json(BasicJsonType&& j, TupleRelated&& t)
5264-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5265{
5266 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5267 {
5268 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5269 }
5270
5271 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5272}
5273
5274template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5275 typename = enable_if_t < !std::is_constructible <
5276 typename BasicJsonType::string_t, Key >::value >>
5277inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5278{
5279 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5280 {
5281 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5282 }
5283 m.clear();
5284 for (const auto& p : j)
5285 {
5286 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5287 {
5288 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5289 }
5290 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5291 }
5292}
5293
5294template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5295 typename = enable_if_t < !std::is_constructible <
5296 typename BasicJsonType::string_t, Key >::value >>
5297inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5298{
5299 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5300 {
5301 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5302 }
5303 m.clear();
5304 for (const auto& p : j)
5305 {
5306 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5307 {
5308 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5309 }
5310 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5311 }
5312}
5313
5314#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5315template<typename BasicJsonType>
5316inline void from_json(const BasicJsonType& j, std_fs::path& p)
5317{
5318 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5319 {
5320 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5321 }
5322 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5323}
5324#endif
5325
5327{
5328 template<typename BasicJsonType, typename T>
5329 auto operator()(const BasicJsonType& j, T&& val) const
5330 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5331 -> decltype(from_json(j, std::forward<T>(val)))
5332 {
5333 return from_json(j, std::forward<T>(val));
5334 }
5335};
5336
5337} // namespace detail
5338
5339#ifndef JSON_HAS_CPP_17
5343namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5344{
5345#endif
5346JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5348#ifndef JSON_HAS_CPP_17
5349} // namespace
5350#endif
5351
5353
5354// #include <nlohmann/detail/conversions/to_json.hpp>
5355// __ _____ _____ _____
5356// __| | __| | | | JSON for Modern C++
5357// | | |__ | | | | | | version 3.11.3
5358// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5359//
5360// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5361// SPDX-License-Identifier: MIT
5362
5363
5364
5365// #include <nlohmann/detail/macro_scope.hpp>
5366// JSON_HAS_CPP_17
5367#ifdef JSON_HAS_CPP_17
5368 #include <optional> // optional
5369#endif
5370
5371#include <algorithm> // copy
5372#include <iterator> // begin, end
5373#include <string> // string
5374#include <tuple> // tuple, get
5375#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5376#include <utility> // move, forward, declval, pair
5377#include <valarray> // valarray
5378#include <vector> // vector
5379
5380// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5381// __ _____ _____ _____
5382// __| | __| | | | JSON for Modern C++
5383// | | |__ | | | | | | version 3.11.3
5384// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5385//
5386// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5387// SPDX-License-Identifier: MIT
5388
5389
5390
5391#include <cstddef> // size_t
5392#include <iterator> // forward_iterator_tag
5393#include <tuple> // tuple_size, get, tuple_element
5394#include <utility> // move
5395
5396#if JSON_HAS_RANGES
5397 #include <ranges> // enable_borrowed_range
5398#endif
5399
5400// #include <nlohmann/detail/abi_macros.hpp>
5401
5402// #include <nlohmann/detail/meta/type_traits.hpp>
5403
5404// #include <nlohmann/detail/string_utils.hpp>
5405// __ _____ _____ _____
5406// __| | __| | | | JSON for Modern C++
5407// | | |__ | | | | | | version 3.11.3
5408// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5409//
5410// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5411// SPDX-License-Identifier: MIT
5412
5413
5414
5415#include <cstddef> // size_t
5416#include <string> // string, to_string
5417
5418// #include <nlohmann/detail/abi_macros.hpp>
5419
5420
5422namespace detail
5423{
5424
5425template<typename StringType>
5426void int_to_string(StringType& target, std::size_t value)
5427{
5428 // For ADL
5429 using std::to_string;
5430 target = to_string(value);
5431}
5432
5433template<typename StringType>
5434StringType to_string(std::size_t value)
5435{
5436 StringType result;
5437 int_to_string(result, value);
5438 return result;
5439}
5440
5441} // namespace detail
5443
5444// #include <nlohmann/detail/value_t.hpp>
5445
5446
5448namespace detail
5449{
5450
5451template<typename IteratorType> class iteration_proxy_value
5452{
5453 public:
5454 using difference_type = std::ptrdiff_t;
5458 using iterator_category = std::forward_iterator_tag;
5459 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5460
5461 private:
5463 IteratorType anchor{};
5465 std::size_t array_index = 0;
5467 mutable std::size_t array_index_last = 0;
5472
5473 public:
5474 explicit iteration_proxy_value() = default;
5475 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5476 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5477 && std::is_nothrow_default_constructible<string_type>::value)
5478 : anchor(std::move(it))
5479 , array_index(array_index_)
5480 {}
5481
5484 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5486 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5487 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5489 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5490 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5492
5494 const iteration_proxy_value& operator*() const
5495 {
5496 return *this;
5497 }
5498
5501 {
5502 ++anchor;
5503 ++array_index;
5504
5505 return *this;
5506 }
5507
5508 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5509 {
5511 ++anchor;
5512 ++array_index;
5513 return tmp;
5514 }
5515
5518 {
5519 return anchor == o.anchor;
5520 }
5521
5524 {
5525 return anchor != o.anchor;
5526 }
5527
5529 const string_type& key() const
5530 {
5531 JSON_ASSERT(anchor.m_object != nullptr);
5532
5533 switch (anchor.m_object->type())
5534 {
5535 // use integer array index as key
5536 case value_t::array:
5537 {
5539 {
5542 }
5543 return array_index_str;
5544 }
5545
5546 // use key from the object
5547 case value_t::object:
5548 return anchor.key();
5549
5550 // use an empty key for all primitive types
5551 case value_t::null:
5552 case value_t::string:
5553 case value_t::boolean:
5557 case value_t::binary:
5558 case value_t::discarded:
5559 default:
5560 return empty_str;
5561 }
5562 }
5563
5565 typename IteratorType::reference value() const
5566 {
5567 return anchor.value();
5568 }
5569};
5570
5572template<typename IteratorType> class iteration_proxy
5573{
5574 private:
5576 typename IteratorType::pointer container = nullptr;
5577
5578 public:
5579 explicit iteration_proxy() = default;
5580
5582 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5583 : container(&cont) {}
5584
5587 iteration_proxy(iteration_proxy&&) noexcept = default;
5588 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5589 ~iteration_proxy() = default;
5590
5592 iteration_proxy_value<IteratorType> begin() const noexcept
5593 {
5595 }
5596
5602};
5603
5604// Structured Bindings Support
5605// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5606// And see https://github.com/nlohmann/json/pull/1391
5607template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5608auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5609{
5610 return i.key();
5611}
5612// Structured Bindings Support
5613// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5614// And see https://github.com/nlohmann/json/pull/1391
5615template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5616auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5617{
5618 return i.value();
5619}
5620
5621} // namespace detail
5623
5624// The Addition to the STD Namespace is required to add
5625// Structured Bindings Support to the iteration_proxy_value class
5626// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5627// And see https://github.com/nlohmann/json/pull/1391
5628namespace std
5629{
5630
5631#if defined(__clang__)
5632 // Fix: https://github.com/nlohmann/json/issues/1401
5633 #pragma clang diagnostic push
5634 #pragma clang diagnostic ignored "-Wmismatched-tags"
5635#endif
5636template<typename IteratorType>
5637class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5638 : public std::integral_constant<std::size_t, 2> {};
5639
5640template<std::size_t N, typename IteratorType>
5641class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5642{
5643 public:
5644 using type = decltype(
5645 get<N>(std::declval <
5646 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5647};
5648#if defined(__clang__)
5649 #pragma clang diagnostic pop
5650#endif
5651
5652} // namespace std
5653
5654#if JSON_HAS_RANGES
5655 template <typename IteratorType>
5656 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5657#endif
5658
5659// #include <nlohmann/detail/meta/cpp_future.hpp>
5660
5661// #include <nlohmann/detail/meta/std_fs.hpp>
5662
5663// #include <nlohmann/detail/meta/type_traits.hpp>
5664
5665// #include <nlohmann/detail/value_t.hpp>
5666
5667
5669namespace detail
5670{
5671
5673// constructors //
5675
5676/*
5677 * Note all external_constructor<>::construct functions need to call
5678 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5679 * allocated value (e.g., a string). See bug issue
5680 * https://github.com/nlohmann/json/issues/2865 for more information.
5681 */
5682
5683template<value_t> struct external_constructor;
5684
5685template<>
5687{
5688 template<typename BasicJsonType>
5689 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5690 {
5691 j.m_data.m_value.destroy(j.m_data.m_type);
5692 j.m_data.m_type = value_t::boolean;
5693 j.m_data.m_value = b;
5694 j.assert_invariant();
5695 }
5696};
5697
5698template<>
5700{
5701 template<typename BasicJsonType>
5702 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5703 {
5704 j.m_data.m_value.destroy(j.m_data.m_type);
5705 j.m_data.m_type = value_t::string;
5706 j.m_data.m_value = s;
5707 j.assert_invariant();
5708 }
5709
5710 template<typename BasicJsonType>
5711 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5712 {
5713 j.m_data.m_value.destroy(j.m_data.m_type);
5714 j.m_data.m_type = value_t::string;
5715 j.m_data.m_value = std::move(s);
5716 j.assert_invariant();
5717 }
5718
5719 template < typename BasicJsonType, typename CompatibleStringType,
5720 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5721 int > = 0 >
5722 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5723 {
5724 j.m_data.m_value.destroy(j.m_data.m_type);
5725 j.m_data.m_type = value_t::string;
5726 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5727 j.assert_invariant();
5728 }
5729};
5730
5731template<>
5733{
5734 template<typename BasicJsonType>
5735 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5736 {
5737 j.m_data.m_value.destroy(j.m_data.m_type);
5738 j.m_data.m_type = value_t::binary;
5739 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5740 j.assert_invariant();
5741 }
5742
5743 template<typename BasicJsonType>
5744 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5745 {
5746 j.m_data.m_value.destroy(j.m_data.m_type);
5747 j.m_data.m_type = value_t::binary;
5748 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5749 j.assert_invariant();
5750 }
5751};
5752
5753template<>
5755{
5756 template<typename BasicJsonType>
5757 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5758 {
5759 j.m_data.m_value.destroy(j.m_data.m_type);
5760 j.m_data.m_type = value_t::number_float;
5761 j.m_data.m_value = val;
5762 j.assert_invariant();
5763 }
5764};
5765
5766template<>
5768{
5769 template<typename BasicJsonType>
5770 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5771 {
5772 j.m_data.m_value.destroy(j.m_data.m_type);
5773 j.m_data.m_type = value_t::number_unsigned;
5774 j.m_data.m_value = val;
5775 j.assert_invariant();
5776 }
5777};
5778
5779template<>
5781{
5782 template<typename BasicJsonType>
5783 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5784 {
5785 j.m_data.m_value.destroy(j.m_data.m_type);
5786 j.m_data.m_type = value_t::number_integer;
5787 j.m_data.m_value = val;
5788 j.assert_invariant();
5789 }
5790};
5791
5792template<>
5794{
5795 template<typename BasicJsonType>
5796 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5797 {
5798 j.m_data.m_value.destroy(j.m_data.m_type);
5799 j.m_data.m_type = value_t::array;
5800 j.m_data.m_value = arr;
5801 j.set_parents();
5802 j.assert_invariant();
5803 }
5804
5805 template<typename BasicJsonType>
5806 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5807 {
5808 j.m_data.m_value.destroy(j.m_data.m_type);
5809 j.m_data.m_type = value_t::array;
5810 j.m_data.m_value = std::move(arr);
5811 j.set_parents();
5812 j.assert_invariant();
5813 }
5814
5815 template < typename BasicJsonType, typename CompatibleArrayType,
5816 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5817 int > = 0 >
5818 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5819 {
5820 using std::begin;
5821 using std::end;
5822
5823 j.m_data.m_value.destroy(j.m_data.m_type);
5824 j.m_data.m_type = value_t::array;
5825 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5826 j.set_parents();
5827 j.assert_invariant();
5828 }
5829
5830 template<typename BasicJsonType>
5831 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5832 {
5833 j.m_data.m_value.destroy(j.m_data.m_type);
5834 j.m_data.m_type = value_t::array;
5835 j.m_data.m_value = value_t::array;
5836 j.m_data.m_value.array->reserve(arr.size());
5837 for (const bool x : arr)
5838 {
5839 j.m_data.m_value.array->push_back(x);
5840 j.set_parent(j.m_data.m_value.array->back());
5841 }
5842 j.assert_invariant();
5843 }
5844
5845 template<typename BasicJsonType, typename T,
5847 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5848 {
5849 j.m_data.m_value.destroy(j.m_data.m_type);
5850 j.m_data.m_type = value_t::array;
5851 j.m_data.m_value = value_t::array;
5852 j.m_data.m_value.array->resize(arr.size());
5853 if (arr.size() > 0)
5854 {
5855 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5856 }
5857 j.set_parents();
5858 j.assert_invariant();
5859 }
5860};
5861
5862template<>
5864{
5865 template<typename BasicJsonType>
5866 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5867 {
5868 j.m_data.m_value.destroy(j.m_data.m_type);
5869 j.m_data.m_type = value_t::object;
5870 j.m_data.m_value = obj;
5871 j.set_parents();
5872 j.assert_invariant();
5873 }
5874
5875 template<typename BasicJsonType>
5876 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5877 {
5878 j.m_data.m_value.destroy(j.m_data.m_type);
5879 j.m_data.m_type = value_t::object;
5880 j.m_data.m_value = std::move(obj);
5881 j.set_parents();
5882 j.assert_invariant();
5883 }
5884
5885 template < typename BasicJsonType, typename CompatibleObjectType,
5886 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5887 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5888 {
5889 using std::begin;
5890 using std::end;
5891
5892 j.m_data.m_value.destroy(j.m_data.m_type);
5893 j.m_data.m_type = value_t::object;
5894 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5895 j.set_parents();
5896 j.assert_invariant();
5897 }
5898};
5899
5901// to_json //
5903
5904#ifdef JSON_HAS_CPP_17
5905template<typename BasicJsonType, typename T,
5906 enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
5907void to_json(BasicJsonType& j, const std::optional<T>& opt)
5908{
5909 if (opt.has_value())
5910 {
5911 j = *opt;
5912 }
5913 else
5914 {
5915 j = nullptr;
5916 }
5917}
5918#endif
5919
5920template<typename BasicJsonType, typename T,
5922inline void to_json(BasicJsonType& j, T b) noexcept
5923{
5925}
5926
5927template < typename BasicJsonType, typename BoolRef,
5928 enable_if_t <
5929 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5930 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5931 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5932 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5933 typename BasicJsonType::boolean_t >::value))
5934 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5935inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5936{
5937 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5938}
5939
5940template<typename BasicJsonType, typename CompatibleString,
5941 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5942inline void to_json(BasicJsonType& j, const CompatibleString& s)
5943{
5945}
5946
5947template<typename BasicJsonType>
5948inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5949{
5951}
5952
5953template<typename BasicJsonType, typename FloatType,
5954 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5955inline void to_json(BasicJsonType& j, FloatType val) noexcept
5956{
5957 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5958}
5959
5960template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5961 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5962inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5963{
5964 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5965}
5966
5967template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5968 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5969inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5970{
5971 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5972}
5973
5974#if !JSON_DISABLE_ENUM_SERIALIZATION
5975template<typename BasicJsonType, typename EnumType,
5976 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5977inline void to_json(BasicJsonType& j, EnumType e) noexcept
5978{
5979 using underlying_type = typename std::underlying_type<EnumType>::type;
5980 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
5981 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
5982}
5983#endif // JSON_DISABLE_ENUM_SERIALIZATION
5984
5985template<typename BasicJsonType>
5986inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5987{
5989}
5990
5991template < typename BasicJsonType, typename CompatibleArrayType,
5992 enable_if_t < is_compatible_array_type<BasicJsonType,
5993 CompatibleArrayType>::value&&
5994 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
5996 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
5997 !is_basic_json<CompatibleArrayType>::value,
5998 int > = 0 >
5999inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
6000{
6002}
6003
6004template<typename BasicJsonType>
6005inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
6006{
6008}
6009
6010template<typename BasicJsonType, typename T,
6011 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
6012inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
6013{
6015}
6016
6017template<typename BasicJsonType>
6018inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
6019{
6021}
6022
6023template < typename BasicJsonType, typename CompatibleObjectType,
6024 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
6025inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
6026{
6028}
6029
6030template<typename BasicJsonType>
6031inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
6032{
6034}
6035
6036template <
6037 typename BasicJsonType, typename T, std::size_t N,
6038 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
6039 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6040 int > = 0 >
6041inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6042{
6044}
6045
6046template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
6047inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
6048{
6049 j = { p.first, p.second };
6050}
6051
6052// for https://github.com/nlohmann/json/pull/1134
6053template<typename BasicJsonType, typename T,
6055inline void to_json(BasicJsonType& j, const T& b)
6056{
6057 j = { {b.key(), b.value()} };
6058}
6059
6060template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
6061inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
6062{
6063 j = { std::get<Idx>(t)... };
6064}
6065
6066template<typename BasicJsonType, typename Tuple>
6067inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& /*unused*/, index_sequence<> /*unused*/)
6068{
6069 using array_t = typename BasicJsonType::array_t;
6070 j = array_t();
6071}
6072
6073template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
6074inline void to_json(BasicJsonType& j, const T& t)
6075{
6076 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
6077}
6078
6079#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
6080template<typename BasicJsonType>
6081inline void to_json(BasicJsonType& j, const std_fs::path& p)
6082{
6083 j = p.string();
6084}
6085#endif
6086
6088{
6089 template<typename BasicJsonType, typename T>
6090 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
6091 -> decltype(to_json(j, std::forward<T>(val)), void())
6092 {
6093 return to_json(j, std::forward<T>(val));
6094 }
6095};
6096} // namespace detail
6097
6098#ifndef JSON_HAS_CPP_17
6102namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
6103{
6104#endif
6105JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
6107#ifndef JSON_HAS_CPP_17
6108} // namespace
6109#endif
6110
6112
6113// #include <nlohmann/detail/meta/identity_tag.hpp>
6114
6115
6117
6119template<typename ValueType, typename>
6121{
6124 template<typename BasicJsonType, typename TargetType = ValueType>
6125 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
6126 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
6127 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
6128 {
6129 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
6130 }
6131
6134 template<typename BasicJsonType, typename TargetType = ValueType>
6135 static auto from_json(BasicJsonType && j) noexcept(
6136 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
6137 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
6138 {
6139 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
6140 }
6141
6144 template<typename BasicJsonType, typename TargetType = ValueType>
6145 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
6146 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
6147 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
6148 {
6149 ::nlohmann::to_json(j, std::forward<TargetType>(val));
6150 }
6151};
6152
6154
6155// #include <nlohmann/byte_container_with_subtype.hpp>
6156// __ _____ _____ _____
6157// __| | __| | | | JSON for Modern C++
6158// | | |__ | | | | | | version 3.11.3
6159// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6160//
6161// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6162// SPDX-License-Identifier: MIT
6163
6164
6165
6166#include <cstdint> // uint8_t, uint64_t
6167#include <tuple> // tie
6168#include <utility> // move
6169
6170// #include <nlohmann/detail/abi_macros.hpp>
6171
6172
6174
6177template<typename BinaryType>
6178class byte_container_with_subtype : public BinaryType
6179{
6180 public:
6181 using container_type = BinaryType;
6182 using subtype_type = std::uint64_t;
6183
6186 : container_type()
6187 {}
6188
6191 : container_type(b)
6192 {}
6193
6195 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
6196 : container_type(std::move(b))
6197 {}
6198
6201 : container_type(b)
6202 , m_subtype(subtype_)
6203 , m_has_subtype(true)
6204 {}
6205
6207 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
6208 : container_type(std::move(b))
6209 , m_subtype(subtype_)
6210 , m_has_subtype(true)
6211 {}
6212
6214 {
6215 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
6216 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
6217 }
6218
6220 {
6221 return !(rhs == *this);
6222 }
6223
6226 void set_subtype(subtype_type subtype_) noexcept
6227 {
6228 m_subtype = subtype_;
6229 m_has_subtype = true;
6230 }
6231
6234 constexpr subtype_type subtype() const noexcept
6235 {
6236 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
6237 }
6238
6241 constexpr bool has_subtype() const noexcept
6242 {
6243 return m_has_subtype;
6244 }
6245
6248 void clear_subtype() noexcept
6249 {
6250 m_subtype = 0;
6251 m_has_subtype = false;
6252 }
6253
6254 private:
6256 bool m_has_subtype = false;
6257};
6258
6260
6261// #include <nlohmann/detail/conversions/from_json.hpp>
6262
6263// #include <nlohmann/detail/conversions/to_json.hpp>
6264
6265// #include <nlohmann/detail/exceptions.hpp>
6266
6267// #include <nlohmann/detail/hash.hpp>
6268// __ _____ _____ _____
6269// __| | __| | | | JSON for Modern C++
6270// | | |__ | | | | | | version 3.11.3
6271// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6272//
6273// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6274// SPDX-License-Identifier: MIT
6275
6276
6277
6278#include <cstdint> // uint8_t
6279#include <cstddef> // size_t
6280#include <functional> // hash
6281
6282// #include <nlohmann/detail/abi_macros.hpp>
6283
6284// #include <nlohmann/detail/value_t.hpp>
6285
6286
6288namespace detail
6289{
6290
6291// boost::hash_combine
6292inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6293{
6294 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6295 return seed;
6296}
6297
6309template<typename BasicJsonType>
6310std::size_t hash(const BasicJsonType& j)
6311{
6312 using string_t = typename BasicJsonType::string_t;
6313 using number_integer_t = typename BasicJsonType::number_integer_t;
6314 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6315 using number_float_t = typename BasicJsonType::number_float_t;
6316
6317 const auto type = static_cast<std::size_t>(j.type());
6318 switch (j.type())
6319 {
6320 case BasicJsonType::value_t::null:
6321 case BasicJsonType::value_t::discarded:
6322 {
6323 return combine(type, 0);
6324 }
6325
6326 case BasicJsonType::value_t::object:
6327 {
6328 auto seed = combine(type, j.size());
6329 for (const auto& element : j.items())
6330 {
6331 const auto h = std::hash<string_t> {}(element.key());
6332 seed = combine(seed, h);
6333 seed = combine(seed, hash(element.value()));
6334 }
6335 return seed;
6336 }
6337
6338 case BasicJsonType::value_t::array:
6339 {
6340 auto seed = combine(type, j.size());
6341 for (const auto& element : j)
6342 {
6343 seed = combine(seed, hash(element));
6344 }
6345 return seed;
6346 }
6347
6348 case BasicJsonType::value_t::string:
6349 {
6350 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6351 return combine(type, h);
6352 }
6353
6354 case BasicJsonType::value_t::boolean:
6355 {
6356 const auto h = std::hash<bool> {}(j.template get<bool>());
6357 return combine(type, h);
6358 }
6359
6360 case BasicJsonType::value_t::number_integer:
6361 {
6362 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6363 return combine(type, h);
6364 }
6365
6366 case BasicJsonType::value_t::number_unsigned:
6367 {
6368 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6369 return combine(type, h);
6370 }
6371
6372 case BasicJsonType::value_t::number_float:
6373 {
6374 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6375 return combine(type, h);
6376 }
6377
6378 case BasicJsonType::value_t::binary:
6379 {
6380 auto seed = combine(type, j.get_binary().size());
6381 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6382 seed = combine(seed, h);
6383 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6384 for (const auto byte : j.get_binary())
6385 {
6386 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6387 }
6388 return seed;
6389 }
6390
6391 default: // LCOV_EXCL_LINE
6392 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6393 return 0; // LCOV_EXCL_LINE
6394 }
6395}
6396
6397} // namespace detail
6399
6400// #include <nlohmann/detail/input/binary_reader.hpp>
6401// __ _____ _____ _____
6402// __| | __| | | | JSON for Modern C++
6403// | | |__ | | | | | | version 3.11.3
6404// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6405//
6406// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6407// SPDX-License-Identifier: MIT
6408
6409
6410
6411#include <algorithm> // generate_n
6412#include <array> // array
6413#include <cmath> // ldexp
6414#include <cstddef> // size_t
6415#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6416#include <cstdio> // snprintf
6417#include <cstring> // memcpy
6418#include <iterator> // back_inserter
6419#include <limits> // numeric_limits
6420#include <string> // char_traits, string
6421#include <utility> // make_pair, move
6422#include <vector> // vector
6423#ifdef __cpp_lib_byteswap
6424 #include <bit> //byteswap
6425#endif
6426
6427// #include <nlohmann/detail/exceptions.hpp>
6428
6429// #include <nlohmann/detail/input/input_adapters.hpp>
6430// __ _____ _____ _____
6431// __| | __| | | | JSON for Modern C++
6432// | | |__ | | | | | | version 3.11.3
6433// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6434//
6435// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6436// SPDX-License-Identifier: MIT
6437
6438
6439
6440#include <array> // array
6441#include <cstddef> // size_t
6442#include <cstring> // strlen
6443#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6444#include <memory> // shared_ptr, make_shared, addressof
6445#include <numeric> // accumulate
6446#include <string> // string, char_traits
6447#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6448#include <utility> // pair, declval
6449
6450#ifndef JSON_NO_IO
6451 #include <cstdio> // FILE *
6452 #include <istream> // istream
6453#endif // JSON_NO_IO
6454
6455// #include <nlohmann/detail/exceptions.hpp>
6456
6457// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6458
6459// #include <nlohmann/detail/macro_scope.hpp>
6460
6461// #include <nlohmann/detail/meta/type_traits.hpp>
6462
6463
6465namespace detail
6466{
6467
6470
6472// input adapters //
6474
6475#ifndef JSON_NO_IO
6481{
6482 public:
6483 using char_type = char;
6484
6486 explicit file_input_adapter(std::FILE* f) noexcept
6487 : m_file(f)
6488 {
6489 JSON_ASSERT(m_file != nullptr);
6490 }
6491
6492 // make class move-only
6495 file_input_adapter& operator=(const file_input_adapter&) = delete;
6498
6499 std::char_traits<char>::int_type get_character() noexcept
6500 {
6501 return std::fgetc(m_file);
6502 }
6503
6504 // returns the number of characters successfully read
6505 template<class T>
6506 std::size_t get_elements(T* dest, std::size_t count = 1)
6507 {
6508 return fread(dest, 1, sizeof(T) * count, m_file);
6509 }
6510
6511 private:
6513 std::FILE* m_file;
6514};
6515
6526{
6527 public:
6528 using char_type = char;
6529
6531 {
6532 // clear stream flags; we use underlying streambuf I/O, do not
6533 // maintain ifstream flags, except eof
6534 if (is != nullptr)
6535 {
6536 is->clear(is->rdstate() & std::ios::eofbit);
6537 }
6538 }
6539
6540 explicit input_stream_adapter(std::istream& i)
6541 : is(&i), sb(i.rdbuf())
6542 {}
6543
6544 // delete because of pointer members
6548
6550 : is(rhs.is), sb(rhs.sb)
6551 {
6552 rhs.is = nullptr;
6553 rhs.sb = nullptr;
6554 }
6555
6556 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6557 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6558 // end up as the same value, e.g. 0xFFFFFFFF.
6559 std::char_traits<char>::int_type get_character()
6560 {
6561 auto res = sb->sbumpc();
6562 // set eof manually, as we don't use the istream interface.
6563 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6564 {
6565 is->clear(is->rdstate() | std::ios::eofbit);
6566 }
6567 return res;
6568 }
6569
6570 template<class T>
6571 std::size_t get_elements(T* dest, std::size_t count = 1)
6572 {
6573 auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
6574 if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T)))
6575 {
6576 is->clear(is->rdstate() | std::ios::eofbit);
6577 }
6578 return res;
6579 }
6580
6581 private:
6583 std::istream* is = nullptr;
6584 std::streambuf* sb = nullptr;
6585};
6586#endif // JSON_NO_IO
6587
6588// General-purpose iterator-based adapter. It might not be as fast as
6589// theoretically possible for some containers, but it is extremely versatile.
6590template<typename IteratorType>
6592{
6593 public:
6594 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6595
6596 iterator_input_adapter(IteratorType first, IteratorType last)
6597 : current(std::move(first)), end(std::move(last))
6598 {}
6599
6601 {
6603 {
6605 std::advance(current, 1);
6606 return result;
6607 }
6608
6610 }
6611
6612 // for general iterators, we cannot really do something better than falling back to processing the range one-by-one
6613 template<class T>
6614 std::size_t get_elements(T* dest, std::size_t count = 1)
6615 {
6616 auto* ptr = reinterpret_cast<char*>(dest);
6617 for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index)
6618 {
6620 {
6621 ptr[read_index] = static_cast<char>(*current);
6622 std::advance(current, 1);
6623 }
6624 else
6625 {
6626 return read_index;
6627 }
6628 }
6629 return count * sizeof(T);
6630 }
6631
6632 private:
6633 IteratorType current;
6634 IteratorType end;
6635
6636 template<typename BaseInputAdapter, size_t T>
6638
6639 bool empty() const
6640 {
6641 return current == end;
6642 }
6643};
6644
6645template<typename BaseInputAdapter, size_t T>
6647
6648template<typename BaseInputAdapter>
6649struct wide_string_input_helper<BaseInputAdapter, 4>
6650{
6651 // UTF-32
6652 static void fill_buffer(BaseInputAdapter& input,
6653 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6654 size_t& utf8_bytes_index,
6655 size_t& utf8_bytes_filled)
6656 {
6657 utf8_bytes_index = 0;
6658
6659 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6660 {
6661 utf8_bytes[0] = std::char_traits<char>::eof();
6662 utf8_bytes_filled = 1;
6663 }
6664 else
6665 {
6666 // get the current character
6667 const auto wc = input.get_character();
6668
6669 // UTF-32 to UTF-8 encoding
6670 if (wc < 0x80)
6671 {
6672 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6673 utf8_bytes_filled = 1;
6674 }
6675 else if (wc <= 0x7FF)
6676 {
6677 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6678 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6679 utf8_bytes_filled = 2;
6680 }
6681 else if (wc <= 0xFFFF)
6682 {
6683 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6684 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6685 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6686 utf8_bytes_filled = 3;
6687 }
6688 else if (wc <= 0x10FFFF)
6689 {
6690 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6691 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6692 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6693 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6694 utf8_bytes_filled = 4;
6695 }
6696 else
6697 {
6698 // unknown character
6699 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6700 utf8_bytes_filled = 1;
6701 }
6702 }
6703 }
6704};
6705
6706template<typename BaseInputAdapter>
6707struct wide_string_input_helper<BaseInputAdapter, 2>
6708{
6709 // UTF-16
6710 static void fill_buffer(BaseInputAdapter& input,
6711 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6712 size_t& utf8_bytes_index,
6713 size_t& utf8_bytes_filled)
6714 {
6715 utf8_bytes_index = 0;
6716
6717 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6718 {
6719 utf8_bytes[0] = std::char_traits<char>::eof();
6720 utf8_bytes_filled = 1;
6721 }
6722 else
6723 {
6724 // get the current character
6725 const auto wc = input.get_character();
6726
6727 // UTF-16 to UTF-8 encoding
6728 if (wc < 0x80)
6729 {
6730 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6731 utf8_bytes_filled = 1;
6732 }
6733 else if (wc <= 0x7FF)
6734 {
6735 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6736 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6737 utf8_bytes_filled = 2;
6738 }
6739 else if (0xD800 > wc || wc >= 0xE000)
6740 {
6741 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6742 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6743 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6744 utf8_bytes_filled = 3;
6745 }
6746 else
6747 {
6748 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6749 {
6750 const auto wc2 = static_cast<unsigned int>(input.get_character());
6751 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6752 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6753 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6754 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6755 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6756 utf8_bytes_filled = 4;
6757 }
6758 else
6759 {
6760 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6761 utf8_bytes_filled = 1;
6762 }
6763 }
6764 }
6765 }
6766};
6767
6768// Wraps another input adapter to convert wide character types into individual bytes.
6769template<typename BaseInputAdapter, typename WideCharType>
6771{
6772 public:
6773 using char_type = char;
6774
6775 wide_string_input_adapter(BaseInputAdapter base)
6776 : base_adapter(base) {}
6777
6778 typename std::char_traits<char>::int_type get_character() noexcept
6779 {
6780 // check if buffer needs to be filled
6782 {
6784
6787 }
6788
6789 // use buffer
6792 return utf8_bytes[utf8_bytes_index++];
6793 }
6794
6795 // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
6796 template<class T>
6797 std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
6798 {
6799 JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
6800 }
6801
6802 private:
6803 BaseInputAdapter base_adapter;
6804
6805 template<size_t T>
6810
6812 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6813
6815 std::size_t utf8_bytes_index = 0;
6817 std::size_t utf8_bytes_filled = 0;
6818};
6819
6820template<typename IteratorType, typename Enable = void>
6822{
6823 using iterator_type = IteratorType;
6824 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6826
6827 static adapter_type create(IteratorType first, IteratorType last)
6828 {
6829 return adapter_type(std::move(first), std::move(last));
6830 }
6831};
6832
6833template<typename T>
6835{
6836 using value_type = typename std::iterator_traits<T>::value_type;
6837 enum
6838 {
6839 value = sizeof(value_type) > 1
6840 };
6841};
6842
6843template<typename IteratorType>
6845{
6846 using iterator_type = IteratorType;
6847 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6850
6851 static adapter_type create(IteratorType first, IteratorType last)
6852 {
6853 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6854 }
6855};
6856
6857// General purpose iterator-based input
6858template<typename IteratorType>
6860{
6862 return factory_type::create(first, last);
6863}
6864
6865// Convenience shorthand from container to iterator
6866// Enables ADL on begin(container) and end(container)
6867// Encloses the using declarations in namespace for not to leak them to outside scope
6868
6870{
6871
6872using std::begin;
6873using std::end;
6874
6875template<typename ContainerType, typename Enable = void>
6877
6878template<typename ContainerType>
6880 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6881 {
6882 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6883
6884 static adapter_type create(const ContainerType& container)
6885{
6886 return input_adapter(begin(container), end(container));
6887}
6888 };
6889
6890} // namespace container_input_adapter_factory_impl
6891
6892template<typename ContainerType>
6897
6898// specialization for std::string
6899using string_input_adapter_type = decltype(input_adapter(std::declval<std::string>()));
6900
6901#ifndef JSON_NO_IO
6902// Special cases with fast paths
6903inline file_input_adapter input_adapter(std::FILE* file)
6904{
6905 if (file == nullptr)
6906 {
6907 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));
6908 }
6909 return file_input_adapter(file);
6910}
6911
6912inline input_stream_adapter input_adapter(std::istream& stream)
6913{
6914 return input_stream_adapter(stream);
6915}
6916
6917inline input_stream_adapter input_adapter(std::istream&& stream)
6918{
6919 return input_stream_adapter(stream);
6920}
6921#endif // JSON_NO_IO
6922
6923using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6924
6925// Null-delimited strings, and the like.
6926template < typename CharT,
6927 typename std::enable_if <
6928 std::is_pointer<CharT>::value&&
6929 !std::is_array<CharT>::value&&
6930 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6931 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6932 int >::type = 0 >
6934{
6935 if (b == nullptr)
6936 {
6937 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));
6938 }
6939 auto length = std::strlen(reinterpret_cast<const char*>(b));
6940 const auto* ptr = reinterpret_cast<const char*>(b);
6941 return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck]
6942}
6943
6944template<typename T, std::size_t N>
6945auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6946{
6947 return input_adapter(array, array + N);
6948}
6949
6950// This class only handles inputs of input_buffer_adapter type.
6951// It's required so that expressions like {ptr, len} can be implicitly cast
6952// to the correct adapter.
6954{
6955 public:
6956 template < typename CharT,
6957 typename std::enable_if <
6958 std::is_pointer<CharT>::value&&
6959 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6960 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6961 int >::type = 0 >
6962 span_input_adapter(CharT b, std::size_t l)
6963 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6964
6965 template<class IteratorType,
6966 typename std::enable_if<
6967 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6968 int>::type = 0>
6969 span_input_adapter(IteratorType first, IteratorType last)
6970 : ia(input_adapter(first, last)) {}
6971
6973 {
6974 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6975 }
6976
6977 private:
6979};
6980
6981} // namespace detail
6983
6984// #include <nlohmann/detail/input/json_sax.hpp>
6985// __ _____ _____ _____
6986// __| | __| | | | JSON for Modern C++
6987// | | |__ | | | | | | version 3.11.3
6988// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6989//
6990// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6991// SPDX-License-Identifier: MIT
6992
6993
6994
6995#include <cstddef>
6996#include <string> // string
6997#include <type_traits> // enable_if_t
6998#include <utility> // move
6999#include <vector> // vector
7000
7001// #include <nlohmann/detail/exceptions.hpp>
7002
7003// #include <nlohmann/detail/input/lexer.hpp>
7004// __ _____ _____ _____
7005// __| | __| | | | JSON for Modern C++
7006// | | |__ | | | | | | version 3.11.3
7007// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7008//
7009// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7010// SPDX-License-Identifier: MIT
7011
7012
7013
7014#include <array> // array
7015#include <clocale> // localeconv
7016#include <cstddef> // size_t
7017#include <cstdio> // snprintf
7018#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7019#include <initializer_list> // initializer_list
7020#include <string> // char_traits, string
7021#include <utility> // move
7022#include <vector> // vector
7023
7024// #include <nlohmann/detail/input/input_adapters.hpp>
7025
7026// #include <nlohmann/detail/input/position_t.hpp>
7027
7028// #include <nlohmann/detail/macro_scope.hpp>
7029
7030// #include <nlohmann/detail/meta/type_traits.hpp>
7031
7032
7034namespace detail
7035{
7036
7038// lexer //
7040
7041template<typename BasicJsonType>
7043{
7044 public:
7066
7070 static const char* token_type_name(const token_type t) noexcept
7071 {
7072 switch (t)
7073 {
7075 return "<uninitialized>";
7077 return "true literal";
7079 return "false literal";
7081 return "null literal";
7083 return "string literal";
7087 return "number literal";
7089 return "'['";
7091 return "'{'";
7093 return "']'";
7095 return "'}'";
7097 return "':'";
7099 return "','";
7101 return "<parse error>";
7103 return "end of input";
7105 return "'[', '{', or a literal";
7106 // LCOV_EXCL_START
7107 default: // catch non-enum values
7108 return "unknown token";
7109 // LCOV_EXCL_STOP
7110 }
7111 }
7112};
7113
7118template<typename BasicJsonType, typename InputAdapterType>
7119class lexer : public lexer_base<BasicJsonType>
7120{
7121 using number_integer_t = typename BasicJsonType::number_integer_t;
7122 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7123 using number_float_t = typename BasicJsonType::number_float_t;
7124 using string_t = typename BasicJsonType::string_t;
7125 using char_type = typename InputAdapterType::char_type;
7127
7128 public:
7130
7131 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7132 : ia(std::move(adapter))
7133 , ignore_comments(ignore_comments_)
7135 {}
7136
7137 // delete because of pointer members
7138 lexer(const lexer&) = delete;
7139 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7140 lexer& operator=(lexer&) = delete;
7141 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7142 ~lexer() = default;
7143
7144 private:
7146 // locales
7148
7151 static char get_decimal_point() noexcept
7152 {
7153 const auto* loc = localeconv();
7154 JSON_ASSERT(loc != nullptr);
7155 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7156 }
7157
7159 // scan functions
7161
7178 {
7179 // this function only makes sense after reading `\u`
7180 JSON_ASSERT(current == 'u');
7181 int codepoint = 0;
7182
7183 const auto factors = { 12u, 8u, 4u, 0u };
7184 for (const auto factor : factors)
7185 {
7186 get();
7187
7188 if (current >= '0' && current <= '9')
7189 {
7190 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7191 }
7192 else if (current >= 'A' && current <= 'F')
7193 {
7194 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7195 }
7196 else if (current >= 'a' && current <= 'f')
7197 {
7198 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7199 }
7200 else
7201 {
7202 return -1;
7203 }
7204 }
7205
7206 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7207 return codepoint;
7208 }
7209
7225 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7226 {
7227 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7228 add(current);
7229
7230 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7231 {
7232 get();
7233 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7234 {
7235 add(current);
7236 }
7237 else
7238 {
7239 error_message = "invalid string: ill-formed UTF-8 byte";
7240 return false;
7241 }
7242 }
7243
7244 return true;
7245 }
7246
7263 {
7264 // reset token_buffer (ignore opening quote)
7265 reset();
7266
7267 // we entered the function by reading an open quote
7268 JSON_ASSERT(current == '\"');
7269
7270 while (true)
7271 {
7272 // get next character
7273 switch (get())
7274 {
7275 // end of file while parsing string
7277 {
7278 error_message = "invalid string: missing closing quote";
7279 return token_type::parse_error;
7280 }
7281
7282 // closing quote
7283 case '\"':
7284 {
7285 return token_type::value_string;
7286 }
7287
7288 // escapes
7289 case '\\':
7290 {
7291 switch (get())
7292 {
7293 // quotation mark
7294 case '\"':
7295 add('\"');
7296 break;
7297 // reverse solidus
7298 case '\\':
7299 add('\\');
7300 break;
7301 // solidus
7302 case '/':
7303 add('/');
7304 break;
7305 // backspace
7306 case 'b':
7307 add('\b');
7308 break;
7309 // form feed
7310 case 'f':
7311 add('\f');
7312 break;
7313 // line feed
7314 case 'n':
7315 add('\n');
7316 break;
7317 // carriage return
7318 case 'r':
7319 add('\r');
7320 break;
7321 // tab
7322 case 't':
7323 add('\t');
7324 break;
7325
7326 // unicode escapes
7327 case 'u':
7328 {
7329 const int codepoint1 = get_codepoint();
7330 int codepoint = codepoint1; // start with codepoint1
7331
7332 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7333 {
7334 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7335 return token_type::parse_error;
7336 }
7337
7338 // check if code point is a high surrogate
7339 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7340 {
7341 // expect next \uxxxx entry
7342 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7343 {
7344 const int codepoint2 = get_codepoint();
7345
7346 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7347 {
7348 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7349 return token_type::parse_error;
7350 }
7351
7352 // check if codepoint2 is a low surrogate
7353 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7354 {
7355 // overwrite codepoint
7356 codepoint = static_cast<int>(
7357 // high surrogate occupies the most significant 22 bits
7358 (static_cast<unsigned int>(codepoint1) << 10u)
7359 // low surrogate occupies the least significant 15 bits
7360 + static_cast<unsigned int>(codepoint2)
7361 // there is still the 0xD800, 0xDC00 and 0x10000 noise
7362 // in the result, so we have to subtract with:
7363 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7364 - 0x35FDC00u);
7365 }
7366 else
7367 {
7368 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7369 return token_type::parse_error;
7370 }
7371 }
7372 else
7373 {
7374 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7375 return token_type::parse_error;
7376 }
7377 }
7378 else
7379 {
7380 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7381 {
7382 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7383 return token_type::parse_error;
7384 }
7385 }
7386
7387 // result of the above calculation yields a proper codepoint
7388 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7389
7390 // translate codepoint into bytes
7391 if (codepoint < 0x80)
7392 {
7393 // 1-byte characters: 0xxxxxxx (ASCII)
7394 add(static_cast<char_int_type>(codepoint));
7395 }
7396 else if (codepoint <= 0x7FF)
7397 {
7398 // 2-byte characters: 110xxxxx 10xxxxxx
7399 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7400 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7401 }
7402 else if (codepoint <= 0xFFFF)
7403 {
7404 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7405 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7406 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7407 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7408 }
7409 else
7410 {
7411 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7412 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7413 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7414 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7415 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7416 }
7417
7418 break;
7419 }
7420
7421 // other characters after escape
7422 default:
7423 error_message = "invalid string: forbidden character after backslash";
7424 return token_type::parse_error;
7425 }
7426
7427 break;
7428 }
7429
7430 // invalid control characters
7431 case 0x00:
7432 {
7433 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7434 return token_type::parse_error;
7435 }
7436
7437 case 0x01:
7438 {
7439 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7440 return token_type::parse_error;
7441 }
7442
7443 case 0x02:
7444 {
7445 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7446 return token_type::parse_error;
7447 }
7448
7449 case 0x03:
7450 {
7451 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7452 return token_type::parse_error;
7453 }
7454
7455 case 0x04:
7456 {
7457 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7458 return token_type::parse_error;
7459 }
7460
7461 case 0x05:
7462 {
7463 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7464 return token_type::parse_error;
7465 }
7466
7467 case 0x06:
7468 {
7469 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7470 return token_type::parse_error;
7471 }
7472
7473 case 0x07:
7474 {
7475 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7476 return token_type::parse_error;
7477 }
7478
7479 case 0x08:
7480 {
7481 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7482 return token_type::parse_error;
7483 }
7484
7485 case 0x09:
7486 {
7487 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7488 return token_type::parse_error;
7489 }
7490
7491 case 0x0A:
7492 {
7493 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7494 return token_type::parse_error;
7495 }
7496
7497 case 0x0B:
7498 {
7499 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7500 return token_type::parse_error;
7501 }
7502
7503 case 0x0C:
7504 {
7505 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7506 return token_type::parse_error;
7507 }
7508
7509 case 0x0D:
7510 {
7511 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7512 return token_type::parse_error;
7513 }
7514
7515 case 0x0E:
7516 {
7517 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7518 return token_type::parse_error;
7519 }
7520
7521 case 0x0F:
7522 {
7523 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7524 return token_type::parse_error;
7525 }
7526
7527 case 0x10:
7528 {
7529 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7530 return token_type::parse_error;
7531 }
7532
7533 case 0x11:
7534 {
7535 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7536 return token_type::parse_error;
7537 }
7538
7539 case 0x12:
7540 {
7541 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7542 return token_type::parse_error;
7543 }
7544
7545 case 0x13:
7546 {
7547 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7548 return token_type::parse_error;
7549 }
7550
7551 case 0x14:
7552 {
7553 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7554 return token_type::parse_error;
7555 }
7556
7557 case 0x15:
7558 {
7559 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7560 return token_type::parse_error;
7561 }
7562
7563 case 0x16:
7564 {
7565 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7566 return token_type::parse_error;
7567 }
7568
7569 case 0x17:
7570 {
7571 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7572 return token_type::parse_error;
7573 }
7574
7575 case 0x18:
7576 {
7577 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7578 return token_type::parse_error;
7579 }
7580
7581 case 0x19:
7582 {
7583 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7584 return token_type::parse_error;
7585 }
7586
7587 case 0x1A:
7588 {
7589 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7590 return token_type::parse_error;
7591 }
7592
7593 case 0x1B:
7594 {
7595 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7596 return token_type::parse_error;
7597 }
7598
7599 case 0x1C:
7600 {
7601 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7602 return token_type::parse_error;
7603 }
7604
7605 case 0x1D:
7606 {
7607 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7608 return token_type::parse_error;
7609 }
7610
7611 case 0x1E:
7612 {
7613 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7614 return token_type::parse_error;
7615 }
7616
7617 case 0x1F:
7618 {
7619 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7620 return token_type::parse_error;
7621 }
7622
7623 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7624 case 0x20:
7625 case 0x21:
7626 case 0x23:
7627 case 0x24:
7628 case 0x25:
7629 case 0x26:
7630 case 0x27:
7631 case 0x28:
7632 case 0x29:
7633 case 0x2A:
7634 case 0x2B:
7635 case 0x2C:
7636 case 0x2D:
7637 case 0x2E:
7638 case 0x2F:
7639 case 0x30:
7640 case 0x31:
7641 case 0x32:
7642 case 0x33:
7643 case 0x34:
7644 case 0x35:
7645 case 0x36:
7646 case 0x37:
7647 case 0x38:
7648 case 0x39:
7649 case 0x3A:
7650 case 0x3B:
7651 case 0x3C:
7652 case 0x3D:
7653 case 0x3E:
7654 case 0x3F:
7655 case 0x40:
7656 case 0x41:
7657 case 0x42:
7658 case 0x43:
7659 case 0x44:
7660 case 0x45:
7661 case 0x46:
7662 case 0x47:
7663 case 0x48:
7664 case 0x49:
7665 case 0x4A:
7666 case 0x4B:
7667 case 0x4C:
7668 case 0x4D:
7669 case 0x4E:
7670 case 0x4F:
7671 case 0x50:
7672 case 0x51:
7673 case 0x52:
7674 case 0x53:
7675 case 0x54:
7676 case 0x55:
7677 case 0x56:
7678 case 0x57:
7679 case 0x58:
7680 case 0x59:
7681 case 0x5A:
7682 case 0x5B:
7683 case 0x5D:
7684 case 0x5E:
7685 case 0x5F:
7686 case 0x60:
7687 case 0x61:
7688 case 0x62:
7689 case 0x63:
7690 case 0x64:
7691 case 0x65:
7692 case 0x66:
7693 case 0x67:
7694 case 0x68:
7695 case 0x69:
7696 case 0x6A:
7697 case 0x6B:
7698 case 0x6C:
7699 case 0x6D:
7700 case 0x6E:
7701 case 0x6F:
7702 case 0x70:
7703 case 0x71:
7704 case 0x72:
7705 case 0x73:
7706 case 0x74:
7707 case 0x75:
7708 case 0x76:
7709 case 0x77:
7710 case 0x78:
7711 case 0x79:
7712 case 0x7A:
7713 case 0x7B:
7714 case 0x7C:
7715 case 0x7D:
7716 case 0x7E:
7717 case 0x7F:
7718 {
7719 add(current);
7720 break;
7721 }
7722
7723 // U+0080..U+07FF: bytes C2..DF 80..BF
7724 case 0xC2:
7725 case 0xC3:
7726 case 0xC4:
7727 case 0xC5:
7728 case 0xC6:
7729 case 0xC7:
7730 case 0xC8:
7731 case 0xC9:
7732 case 0xCA:
7733 case 0xCB:
7734 case 0xCC:
7735 case 0xCD:
7736 case 0xCE:
7737 case 0xCF:
7738 case 0xD0:
7739 case 0xD1:
7740 case 0xD2:
7741 case 0xD3:
7742 case 0xD4:
7743 case 0xD5:
7744 case 0xD6:
7745 case 0xD7:
7746 case 0xD8:
7747 case 0xD9:
7748 case 0xDA:
7749 case 0xDB:
7750 case 0xDC:
7751 case 0xDD:
7752 case 0xDE:
7753 case 0xDF:
7754 {
7755 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7756 {
7757 return token_type::parse_error;
7758 }
7759 break;
7760 }
7761
7762 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7763 case 0xE0:
7764 {
7765 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7766 {
7767 return token_type::parse_error;
7768 }
7769 break;
7770 }
7771
7772 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7773 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7774 case 0xE1:
7775 case 0xE2:
7776 case 0xE3:
7777 case 0xE4:
7778 case 0xE5:
7779 case 0xE6:
7780 case 0xE7:
7781 case 0xE8:
7782 case 0xE9:
7783 case 0xEA:
7784 case 0xEB:
7785 case 0xEC:
7786 case 0xEE:
7787 case 0xEF:
7788 {
7789 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7790 {
7791 return token_type::parse_error;
7792 }
7793 break;
7794 }
7795
7796 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7797 case 0xED:
7798 {
7799 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7800 {
7801 return token_type::parse_error;
7802 }
7803 break;
7804 }
7805
7806 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7807 case 0xF0:
7808 {
7809 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7810 {
7811 return token_type::parse_error;
7812 }
7813 break;
7814 }
7815
7816 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7817 case 0xF1:
7818 case 0xF2:
7819 case 0xF3:
7820 {
7821 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7822 {
7823 return token_type::parse_error;
7824 }
7825 break;
7826 }
7827
7828 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7829 case 0xF4:
7830 {
7831 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7832 {
7833 return token_type::parse_error;
7834 }
7835 break;
7836 }
7837
7838 // remaining bytes (80..C1 and F5..FF) are ill-formed
7839 default:
7840 {
7841 error_message = "invalid string: ill-formed UTF-8 byte";
7842 return token_type::parse_error;
7843 }
7844 }
7845 }
7846 }
7847
7853 {
7854 switch (get())
7855 {
7856 // single-line comments skip input until a newline or EOF is read
7857 case '/':
7858 {
7859 while (true)
7860 {
7861 switch (get())
7862 {
7863 case '\n':
7864 case '\r':
7866 case '\0':
7867 return true;
7868
7869 default:
7870 break;
7871 }
7872 }
7873 }
7874
7875 // multi-line comments skip input until */ is read
7876 case '*':
7877 {
7878 while (true)
7879 {
7880 switch (get())
7881 {
7883 case '\0':
7884 {
7885 error_message = "invalid comment; missing closing '*/'";
7886 return false;
7887 }
7888
7889 case '*':
7890 {
7891 switch (get())
7892 {
7893 case '/':
7894 return true;
7895
7896 default:
7897 {
7898 unget();
7899 continue;
7900 }
7901 }
7902 }
7903
7904 default:
7905 continue;
7906 }
7907 }
7908 }
7909
7910 // unexpected character after reading '/'
7911 default:
7912 {
7913 error_message = "invalid comment; expecting '/' or '*' after '/'";
7914 return false;
7915 }
7916 }
7917 }
7918
7920 static void strtof(float& f, const char* str, char** endptr) noexcept
7921 {
7922 f = std::strtof(str, endptr);
7923 }
7924
7926 static void strtof(double& f, const char* str, char** endptr) noexcept
7927 {
7928 f = std::strtod(str, endptr);
7929 }
7930
7932 static void strtof(long double& f, const char* str, char** endptr) noexcept
7933 {
7934 f = std::strtold(str, endptr);
7935 }
7936
7977 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.
7978 {
7979 // reset token_buffer to store the number's bytes
7980 reset();
7981
7982 // the type of the parsed number; initially set to unsigned; will be
7983 // changed if minus sign, decimal point or exponent is read
7984 token_type number_type = token_type::value_unsigned;
7985
7986 // state (init): we just found out we need to scan a number
7987 switch (current)
7988 {
7989 case '-':
7990 {
7991 add(current);
7992 goto scan_number_minus;
7993 }
7994
7995 case '0':
7996 {
7997 add(current);
7998 goto scan_number_zero;
7999 }
8000
8001 case '1':
8002 case '2':
8003 case '3':
8004 case '4':
8005 case '5':
8006 case '6':
8007 case '7':
8008 case '8':
8009 case '9':
8010 {
8011 add(current);
8012 goto scan_number_any1;
8013 }
8014
8015 // all other characters are rejected outside scan_number()
8016 default: // LCOV_EXCL_LINE
8017 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8018 }
8019
8020scan_number_minus:
8021 // state: we just parsed a leading minus sign
8022 number_type = token_type::value_integer;
8023 switch (get())
8024 {
8025 case '0':
8026 {
8027 add(current);
8028 goto scan_number_zero;
8029 }
8030
8031 case '1':
8032 case '2':
8033 case '3':
8034 case '4':
8035 case '5':
8036 case '6':
8037 case '7':
8038 case '8':
8039 case '9':
8040 {
8041 add(current);
8042 goto scan_number_any1;
8043 }
8044
8045 default:
8046 {
8047 error_message = "invalid number; expected digit after '-'";
8048 return token_type::parse_error;
8049 }
8050 }
8051
8052scan_number_zero:
8053 // state: we just parse a zero (maybe with a leading minus sign)
8054 switch (get())
8055 {
8056 case '.':
8057 {
8060 goto scan_number_decimal1;
8061 }
8062
8063 case 'e':
8064 case 'E':
8065 {
8066 add(current);
8067 goto scan_number_exponent;
8068 }
8069
8070 default:
8071 goto scan_number_done;
8072 }
8073
8074scan_number_any1:
8075 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8076 switch (get())
8077 {
8078 case '0':
8079 case '1':
8080 case '2':
8081 case '3':
8082 case '4':
8083 case '5':
8084 case '6':
8085 case '7':
8086 case '8':
8087 case '9':
8088 {
8089 add(current);
8090 goto scan_number_any1;
8091 }
8092
8093 case '.':
8094 {
8097 goto scan_number_decimal1;
8098 }
8099
8100 case 'e':
8101 case 'E':
8102 {
8103 add(current);
8104 goto scan_number_exponent;
8105 }
8106
8107 default:
8108 goto scan_number_done;
8109 }
8110
8111scan_number_decimal1:
8112 // state: we just parsed a decimal point
8113 number_type = token_type::value_float;
8114 switch (get())
8115 {
8116 case '0':
8117 case '1':
8118 case '2':
8119 case '3':
8120 case '4':
8121 case '5':
8122 case '6':
8123 case '7':
8124 case '8':
8125 case '9':
8126 {
8127 add(current);
8128 goto scan_number_decimal2;
8129 }
8130
8131 default:
8132 {
8133 error_message = "invalid number; expected digit after '.'";
8134 return token_type::parse_error;
8135 }
8136 }
8137
8138scan_number_decimal2:
8139 // we just parsed at least one number after a decimal point
8140 switch (get())
8141 {
8142 case '0':
8143 case '1':
8144 case '2':
8145 case '3':
8146 case '4':
8147 case '5':
8148 case '6':
8149 case '7':
8150 case '8':
8151 case '9':
8152 {
8153 add(current);
8154 goto scan_number_decimal2;
8155 }
8156
8157 case 'e':
8158 case 'E':
8159 {
8160 add(current);
8161 goto scan_number_exponent;
8162 }
8163
8164 default:
8165 goto scan_number_done;
8166 }
8167
8168scan_number_exponent:
8169 // we just parsed an exponent
8170 number_type = token_type::value_float;
8171 switch (get())
8172 {
8173 case '+':
8174 case '-':
8175 {
8176 add(current);
8177 goto scan_number_sign;
8178 }
8179
8180 case '0':
8181 case '1':
8182 case '2':
8183 case '3':
8184 case '4':
8185 case '5':
8186 case '6':
8187 case '7':
8188 case '8':
8189 case '9':
8190 {
8191 add(current);
8192 goto scan_number_any2;
8193 }
8194
8195 default:
8196 {
8198 "invalid number; expected '+', '-', or digit after exponent";
8199 return token_type::parse_error;
8200 }
8201 }
8202
8203scan_number_sign:
8204 // we just parsed an exponent sign
8205 switch (get())
8206 {
8207 case '0':
8208 case '1':
8209 case '2':
8210 case '3':
8211 case '4':
8212 case '5':
8213 case '6':
8214 case '7':
8215 case '8':
8216 case '9':
8217 {
8218 add(current);
8219 goto scan_number_any2;
8220 }
8221
8222 default:
8223 {
8224 error_message = "invalid number; expected digit after exponent sign";
8225 return token_type::parse_error;
8226 }
8227 }
8228
8229scan_number_any2:
8230 // we just parsed a number after the exponent or exponent sign
8231 switch (get())
8232 {
8233 case '0':
8234 case '1':
8235 case '2':
8236 case '3':
8237 case '4':
8238 case '5':
8239 case '6':
8240 case '7':
8241 case '8':
8242 case '9':
8243 {
8244 add(current);
8245 goto scan_number_any2;
8246 }
8247
8248 default:
8249 goto scan_number_done;
8250 }
8251
8252scan_number_done:
8253 // unget the character after the number (we only read it to know that
8254 // we are done scanning a number)
8255 unget();
8256
8257 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8258 errno = 0;
8259
8260 // try to parse integers first and fall back to floats
8261 if (number_type == token_type::value_unsigned)
8262 {
8263 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8264
8265 // we checked the number format before
8266 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8267
8268 if (errno != ERANGE)
8269 {
8270 value_unsigned = static_cast<number_unsigned_t>(x);
8271 if (value_unsigned == x)
8272 {
8273 return token_type::value_unsigned;
8274 }
8275 }
8276 }
8277 else if (number_type == token_type::value_integer)
8278 {
8279 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8280
8281 // we checked the number format before
8282 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8283
8284 if (errno != ERANGE)
8285 {
8286 value_integer = static_cast<number_integer_t>(x);
8287 if (value_integer == x)
8288 {
8289 return token_type::value_integer;
8290 }
8291 }
8292 }
8293
8294 // this code is reached if we parse a floating-point number or if an
8295 // integer conversion above failed
8296 strtof(value_float, token_buffer.data(), &endptr);
8297
8298 // we checked the number format before
8299 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8300
8301 return token_type::value_float;
8302 }
8303
8310 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8311 token_type return_type)
8312 {
8314 for (std::size_t i = 1; i < length; ++i)
8315 {
8317 {
8318 error_message = "invalid literal";
8319 return token_type::parse_error;
8320 }
8321 }
8322 return return_type;
8323 }
8324
8326 // input management
8328
8330 void reset() noexcept
8331 {
8332 token_buffer.clear();
8333 token_string.clear();
8334 decimal_point_position = std::string::npos;
8336 }
8337
8338 /*
8339 @brief get next character from the input
8340
8341 This function provides the interface to the used input adapter. It does
8342 not throw in case the input reached EOF, but returns a
8343 `char_traits<char>::eof()` in that case. Stores the scanned characters
8344 for use in error messages.
8345
8346 @return character read from the input
8347 */
8349 {
8350 ++position.chars_read_total;
8351 ++position.chars_read_current_line;
8352
8353 if (next_unget)
8354 {
8355 // just reset the next_unget variable and work with current
8356 next_unget = false;
8357 }
8358 else
8359 {
8360 current = ia.get_character();
8361 }
8362
8364 {
8366 }
8367
8368 if (current == '\n')
8369 {
8370 ++position.lines_read;
8371 position.chars_read_current_line = 0;
8372 }
8373
8374 return current;
8375 }
8376
8385 void unget()
8386 {
8387 next_unget = true;
8388
8389 --position.chars_read_total;
8390
8391 // in case we "unget" a newline, we have to also decrement the lines_read
8392 if (position.chars_read_current_line == 0)
8393 {
8394 if (position.lines_read > 0)
8395 {
8396 --position.lines_read;
8397 }
8398 }
8399 else
8400 {
8401 --position.chars_read_current_line;
8402 }
8403
8405 {
8406 JSON_ASSERT(!token_string.empty());
8407 token_string.pop_back();
8408 }
8409 }
8410
8413 {
8414 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8415 }
8416
8417 public:
8419 // value getters
8421
8423 constexpr number_integer_t get_number_integer() const noexcept
8424 {
8425 return value_integer;
8426 }
8427
8429 constexpr number_unsigned_t get_number_unsigned() const noexcept
8430 {
8431 return value_unsigned;
8432 }
8433
8435 constexpr number_float_t get_number_float() const noexcept
8436 {
8437 return value_float;
8438 }
8439
8442 {
8443 // translate decimal points from locale back to '.' (#4084)
8444 if (decimal_point_char != '.' && decimal_point_position != std::string::npos)
8445 {
8447 }
8448 return token_buffer;
8449 }
8450
8452 // diagnostics
8454
8456 constexpr position_t get_position() const noexcept
8457 {
8458 return position;
8459 }
8460
8464 std::string get_token_string() const
8465 {
8466 // escape control characters
8467 std::string result;
8468 for (const auto c : token_string)
8469 {
8470 if (static_cast<unsigned char>(c) <= '\x1F')
8471 {
8472 // escape control characters
8473 std::array<char, 9> cs{{}};
8474 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8475 result += cs.data();
8476 }
8477 else
8478 {
8479 // add character as is
8480 result.push_back(static_cast<std::string::value_type>(c));
8481 }
8482 }
8483
8484 return result;
8485 }
8486
8489 constexpr const char* get_error_message() const noexcept
8490 {
8491 return error_message;
8492 }
8493
8495 // actual scanner
8497
8503 {
8504 if (get() == 0xEF)
8505 {
8506 // check if we completely parse the BOM
8507 return get() == 0xBB && get() == 0xBF;
8508 }
8509
8510 // the first character is not the beginning of the BOM; unget it to
8511 // process is later
8512 unget();
8513 return true;
8514 }
8515
8517 {
8518 do
8519 {
8520 get();
8521 }
8522 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8523 }
8524
8526 {
8527 // initially, skip the BOM
8528 if (position.chars_read_total == 0 && !skip_bom())
8529 {
8530 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8531 return token_type::parse_error;
8532 }
8533
8534 // read next character and ignore whitespace
8536
8537 // ignore comments
8538 while (ignore_comments && current == '/')
8539 {
8540 if (!scan_comment())
8541 {
8542 return token_type::parse_error;
8543 }
8544
8545 // skip following whitespace
8547 }
8548
8549 switch (current)
8550 {
8551 // structural characters
8552 case '[':
8553 return token_type::begin_array;
8554 case ']':
8555 return token_type::end_array;
8556 case '{':
8557 return token_type::begin_object;
8558 case '}':
8559 return token_type::end_object;
8560 case ':':
8561 return token_type::name_separator;
8562 case ',':
8563 return token_type::value_separator;
8564
8565 // literals
8566 case 't':
8567 {
8568 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')}};
8569 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8570 }
8571 case 'f':
8572 {
8573 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')}};
8574 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8575 }
8576 case 'n':
8577 {
8578 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')}};
8579 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8580 }
8581
8582 // string
8583 case '\"':
8584 return scan_string();
8585
8586 // number
8587 case '-':
8588 case '0':
8589 case '1':
8590 case '2':
8591 case '3':
8592 case '4':
8593 case '5':
8594 case '6':
8595 case '7':
8596 case '8':
8597 case '9':
8598 return scan_number();
8599
8600 // end of input (the null byte is needed when parsing from
8601 // string literals)
8602 case '\0':
8604 return token_type::end_of_input;
8605
8606 // error
8607 default:
8608 error_message = "invalid literal";
8609 return token_type::parse_error;
8610 }
8611 }
8612
8613 private:
8615 InputAdapterType ia;
8616
8618 const bool ignore_comments = false;
8619
8622
8624 bool next_unget = false;
8625
8628
8630 std::vector<char_type> token_string {};
8631
8634
8636 const char* error_message = "";
8637
8638 // number values
8642
8646 std::size_t decimal_point_position = std::string::npos;
8647};
8648
8649} // namespace detail
8651
8652// #include <nlohmann/detail/macro_scope.hpp>
8653
8654// #include <nlohmann/detail/string_concat.hpp>
8655
8657
8666template<typename BasicJsonType>
8668{
8669 using number_integer_t = typename BasicJsonType::number_integer_t;
8670 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8671 using number_float_t = typename BasicJsonType::number_float_t;
8672 using string_t = typename BasicJsonType::string_t;
8673 using binary_t = typename BasicJsonType::binary_t;
8674
8679 virtual bool null() = 0;
8680
8686 virtual bool boolean(bool val) = 0;
8687
8693 virtual bool number_integer(number_integer_t val) = 0;
8694
8700 virtual bool number_unsigned(number_unsigned_t val) = 0;
8701
8708 virtual bool number_float(number_float_t val, const string_t& s) = 0;
8709
8716 virtual bool string(string_t& val) = 0;
8717
8724 virtual bool binary(binary_t& val) = 0;
8725
8732 virtual bool start_object(std::size_t elements) = 0;
8733
8740 virtual bool key(string_t& val) = 0;
8741
8746 virtual bool end_object() = 0;
8747
8754 virtual bool start_array(std::size_t elements) = 0;
8755
8760 virtual bool end_array() = 0;
8761
8769 virtual bool parse_error(std::size_t position,
8770 const std::string& last_token,
8771 const detail::exception& ex) = 0;
8772
8773 json_sax() = default;
8774 json_sax(const json_sax&) = default;
8775 json_sax(json_sax&&) noexcept = default;
8776 json_sax& operator=(const json_sax&) = default;
8777 json_sax& operator=(json_sax&&) noexcept = default;
8778 virtual ~json_sax() = default;
8779};
8780
8781namespace detail
8782{
8783constexpr std::size_t unknown_size()
8784{
8785 return (std::numeric_limits<std::size_t>::max)();
8786}
8787
8801template<typename BasicJsonType, typename InputAdapterType>
8803{
8804 public:
8805 using number_integer_t = typename BasicJsonType::number_integer_t;
8806 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8807 using number_float_t = typename BasicJsonType::number_float_t;
8808 using string_t = typename BasicJsonType::string_t;
8809 using binary_t = typename BasicJsonType::binary_t;
8811
8817 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr)
8818 : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
8819 {}
8820
8821 // make class move-only
8823 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8825 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8827
8828 bool null()
8829 {
8830 handle_value(nullptr);
8831 return true;
8832 }
8833
8834 bool boolean(bool val)
8835 {
8836 handle_value(val);
8837 return true;
8838 }
8839
8841 {
8842 handle_value(val);
8843 return true;
8844 }
8845
8847 {
8848 handle_value(val);
8849 return true;
8850 }
8851
8852 bool number_float(number_float_t val, const string_t& /*unused*/)
8853 {
8854 handle_value(val);
8855 return true;
8856 }
8857
8858 bool string(string_t& val)
8859 {
8860 handle_value(val);
8861 return true;
8862 }
8863
8864 bool binary(binary_t& val)
8865 {
8866 handle_value(std::move(val));
8867 return true;
8868 }
8869
8870 bool start_object(std::size_t len)
8871 {
8872 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
8873
8874#if JSON_DIAGNOSTIC_POSITIONS
8875 // Manually set the start position of the object here.
8876 // Ensure this is after the call to handle_value to ensure correct start position.
8877 if (m_lexer_ref)
8878 {
8879 // Lexer has read the first character of the object, so
8880 // subtract 1 from the position to get the correct start position.
8881 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8882 }
8883#endif
8884
8885 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
8886 {
8887 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
8888 }
8889
8890 return true;
8891 }
8892
8893 bool key(string_t& val)
8894 {
8895 JSON_ASSERT(!ref_stack.empty());
8896 JSON_ASSERT(ref_stack.back()->is_object());
8897
8898 // add null at given key and store the reference for later
8899 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
8900 return true;
8901 }
8902
8904 {
8905 JSON_ASSERT(!ref_stack.empty());
8906 JSON_ASSERT(ref_stack.back()->is_object());
8907
8908#if JSON_DIAGNOSTIC_POSITIONS
8909 if (m_lexer_ref)
8910 {
8911 // Lexer's position is past the closing brace, so set that as the end position.
8912 ref_stack.back()->end_position = m_lexer_ref->get_position();
8913 }
8914#endif
8915
8916 ref_stack.back()->set_parents();
8917 ref_stack.pop_back();
8918 return true;
8919 }
8920
8921 bool start_array(std::size_t len)
8922 {
8923 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
8924
8925#if JSON_DIAGNOSTIC_POSITIONS
8926 // Manually set the start position of the array here.
8927 // Ensure this is after the call to handle_value to ensure correct start position.
8928 if (m_lexer_ref)
8929 {
8930 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8931 }
8932#endif
8933
8934 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
8935 {
8936 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
8937 }
8938
8939 return true;
8940 }
8941
8943 {
8944 JSON_ASSERT(!ref_stack.empty());
8945 JSON_ASSERT(ref_stack.back()->is_array());
8946
8947#if JSON_DIAGNOSTIC_POSITIONS
8948 if (m_lexer_ref)
8949 {
8950 // Lexer's position is past the closing bracket, so set that as the end position.
8951 ref_stack.back()->end_position = m_lexer_ref->get_position();
8952 }
8953#endif
8954
8955 ref_stack.back()->set_parents();
8956 ref_stack.pop_back();
8957 return true;
8958 }
8959
8960 template<class Exception>
8961 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
8962 const Exception& ex)
8963 {
8964 errored = true;
8965 static_cast<void>(ex);
8966 if (allow_exceptions)
8967 {
8968 JSON_THROW(ex);
8969 }
8970 return false;
8971 }
8972
8973 constexpr bool is_errored() const
8974 {
8975 return errored;
8976 }
8977
8978 private:
8979
8980#if JSON_DIAGNOSTIC_POSITIONS
8981 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
8982 {
8983 if (m_lexer_ref)
8984 {
8985 // Lexer has read past the current field value, so set the end position to the current position.
8986 // The start position will be set below based on the length of the string representation
8987 // of the value.
8988 v.end_position = m_lexer_ref->get_position();
8989
8990 switch (v.type())
8991 {
8992 case value_t::boolean:
8993 {
8994 // 4 and 5 are the string length of "true" and "false"
8995 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
8996 break;
8997 }
8998
8999 case value_t::null:
9000 {
9001 // 4 is the string length of "null"
9002 v.start_position = v.end_position - 4;
9003 break;
9004 }
9005
9006 case value_t::string:
9007 {
9008 // include the length of the quotes, which is 2
9009 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9010 break;
9011 }
9012
9013 // As we handle the start and end positions for values created during parsing,
9014 // we do not expect the following value type to be called. Regardless, set the positions
9015 // in case this is created manually or through a different constructor. Exclude from lcov
9016 // since the exact condition of this switch is esoteric.
9017 // LCOV_EXCL_START
9018 case value_t::discarded:
9019 {
9020 v.end_position = std::string::npos;
9021 v.start_position = v.end_position;
9022 break;
9023 }
9024 // LCOV_EXCL_STOP
9025 case value_t::binary:
9026 case value_t::number_integer:
9027 case value_t::number_unsigned:
9028 case value_t::number_float:
9029 {
9030 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9031 break;
9032 }
9033 case value_t::object:
9034 case value_t::array:
9035 {
9036 // object and array are handled in start_object() and start_array() handlers
9037 // skip setting the values here.
9038 break;
9039 }
9040 default: // LCOV_EXCL_LINE
9041 // Handle all possible types discretely, default handler should never be reached.
9042 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9043 }
9044 }
9045 }
9046#endif
9047
9054 template<typename Value>
9056 BasicJsonType* handle_value(Value&& v)
9057 {
9058 if (ref_stack.empty())
9059 {
9060 root = BasicJsonType(std::forward<Value>(v));
9061
9062#if JSON_DIAGNOSTIC_POSITIONS
9063 handle_diagnostic_positions_for_json_value(root);
9064#endif
9065
9066 return &root;
9067 }
9068
9069 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9070
9071 if (ref_stack.back()->is_array())
9072 {
9073 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
9074
9075#if JSON_DIAGNOSTIC_POSITIONS
9076 handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back());
9077#endif
9078
9079 return &(ref_stack.back()->m_data.m_value.array->back());
9080 }
9081
9082 JSON_ASSERT(ref_stack.back()->is_object());
9084 *object_element = BasicJsonType(std::forward<Value>(v));
9085
9086#if JSON_DIAGNOSTIC_POSITIONS
9087 handle_diagnostic_positions_for_json_value(*object_element);
9088#endif
9089
9090 return object_element;
9091 }
9092
9094 BasicJsonType& root;
9096 std::vector<BasicJsonType*> ref_stack {};
9098 BasicJsonType* object_element = nullptr;
9100 bool errored = false;
9102 const bool allow_exceptions = true;
9105};
9106
9107template<typename BasicJsonType, typename InputAdapterType>
9109{
9110 public:
9111 using number_integer_t = typename BasicJsonType::number_integer_t;
9112 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9113 using number_float_t = typename BasicJsonType::number_float_t;
9114 using string_t = typename BasicJsonType::string_t;
9115 using binary_t = typename BasicJsonType::binary_t;
9116 using parser_callback_t = typename BasicJsonType::parser_callback_t;
9117 using parse_event_t = typename BasicJsonType::parse_event_t;
9119
9122 const bool allow_exceptions_ = true,
9123 lexer_t* lexer_ = nullptr)
9124 : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
9125 {
9126 keep_stack.push_back(true);
9127 }
9128
9129 // make class move-only
9131 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9133 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9135
9136 bool null()
9137 {
9138 handle_value(nullptr);
9139 return true;
9140 }
9141
9142 bool boolean(bool val)
9143 {
9144 handle_value(val);
9145 return true;
9146 }
9147
9149 {
9150 handle_value(val);
9151 return true;
9152 }
9153
9155 {
9156 handle_value(val);
9157 return true;
9158 }
9159
9160 bool number_float(number_float_t val, const string_t& /*unused*/)
9161 {
9162 handle_value(val);
9163 return true;
9164 }
9165
9166 bool string(string_t& val)
9167 {
9168 handle_value(val);
9169 return true;
9170 }
9171
9172 bool binary(binary_t& val)
9173 {
9174 handle_value(std::move(val));
9175 return true;
9176 }
9177
9178 bool start_object(std::size_t len)
9179 {
9180 // check callback for object start
9181 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
9182 keep_stack.push_back(keep);
9183
9184 auto val = handle_value(BasicJsonType::value_t::object, true);
9185 ref_stack.push_back(val.second);
9186
9187 if (ref_stack.back())
9188 {
9189
9190#if JSON_DIAGNOSTIC_POSITIONS
9191 // Manually set the start position of the object here.
9192 // Ensure this is after the call to handle_value to ensure correct start position.
9193 if (m_lexer_ref)
9194 {
9195 // Lexer has read the first character of the object, so
9196 // subtract 1 from the position to get the correct start position.
9197 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9198 }
9199#endif
9200
9201 // check object limit
9202 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9203 {
9204 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
9205 }
9206 }
9207 return true;
9208 }
9209
9210 bool key(string_t& val)
9211 {
9212 BasicJsonType k = BasicJsonType(val);
9213
9214 // check callback for key
9215 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
9216 key_keep_stack.push_back(keep);
9217
9218 // add discarded value at given key and store the reference for later
9219 if (keep && ref_stack.back())
9220 {
9221 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
9222 }
9223
9224 return true;
9225 }
9226
9228 {
9229 if (ref_stack.back())
9230 {
9231 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
9232 {
9233 // discard object
9234 *ref_stack.back() = discarded;
9235
9236#if JSON_DIAGNOSTIC_POSITIONS
9237 // Set start/end positions for discarded object.
9238 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9239#endif
9240 }
9241 else
9242 {
9243
9244#if JSON_DIAGNOSTIC_POSITIONS
9245 if (m_lexer_ref)
9246 {
9247 // Lexer's position is past the closing brace, so set that as the end position.
9248 ref_stack.back()->end_position = m_lexer_ref->get_position();
9249 }
9250#endif
9251
9252 ref_stack.back()->set_parents();
9253 }
9254 }
9255
9256 JSON_ASSERT(!ref_stack.empty());
9257 JSON_ASSERT(!keep_stack.empty());
9258 ref_stack.pop_back();
9259 keep_stack.pop_back();
9260
9261 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
9262 {
9263 // remove discarded value
9264 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
9265 {
9266 if (it->is_discarded())
9267 {
9268 ref_stack.back()->erase(it);
9269 break;
9270 }
9271 }
9272 }
9273
9274 return true;
9275 }
9276
9277 bool start_array(std::size_t len)
9278 {
9279 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
9280 keep_stack.push_back(keep);
9281
9282 auto val = handle_value(BasicJsonType::value_t::array, true);
9283 ref_stack.push_back(val.second);
9284
9285 if (ref_stack.back())
9286 {
9287
9288#if JSON_DIAGNOSTIC_POSITIONS
9289 // Manually set the start position of the array here.
9290 // Ensure this is after the call to handle_value to ensure correct start position.
9291 if (m_lexer_ref)
9292 {
9293 // Lexer has read the first character of the array, so
9294 // subtract 1 from the position to get the correct start position.
9295 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9296 }
9297#endif
9298
9299 // check array limit
9300 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9301 {
9302 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
9303 }
9304 }
9305
9306 return true;
9307 }
9308
9310 {
9311 bool keep = true;
9312
9313 if (ref_stack.back())
9314 {
9315 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
9316 if (keep)
9317 {
9318
9319#if JSON_DIAGNOSTIC_POSITIONS
9320 if (m_lexer_ref)
9321 {
9322 // Lexer's position is past the closing bracket, so set that as the end position.
9323 ref_stack.back()->end_position = m_lexer_ref->get_position();
9324 }
9325#endif
9326
9327 ref_stack.back()->set_parents();
9328 }
9329 else
9330 {
9331 // discard array
9332 *ref_stack.back() = discarded;
9333
9334#if JSON_DIAGNOSTIC_POSITIONS
9335 // Set start/end positions for discarded array.
9336 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9337#endif
9338 }
9339 }
9340
9341 JSON_ASSERT(!ref_stack.empty());
9342 JSON_ASSERT(!keep_stack.empty());
9343 ref_stack.pop_back();
9344 keep_stack.pop_back();
9345
9346 // remove discarded value
9347 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
9348 {
9349 ref_stack.back()->m_data.m_value.array->pop_back();
9350 }
9351
9352 return true;
9353 }
9354
9355 template<class Exception>
9356 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9357 const Exception& ex)
9358 {
9359 errored = true;
9360 static_cast<void>(ex);
9361 if (allow_exceptions)
9362 {
9363 JSON_THROW(ex);
9364 }
9365 return false;
9366 }
9367
9368 constexpr bool is_errored() const
9369 {
9370 return errored;
9371 }
9372
9373 private:
9374
9375#if JSON_DIAGNOSTIC_POSITIONS
9376 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9377 {
9378 if (m_lexer_ref)
9379 {
9380 // Lexer has read past the current field value, so set the end position to the current position.
9381 // The start position will be set below based on the length of the string representation
9382 // of the value.
9383 v.end_position = m_lexer_ref->get_position();
9384
9385 switch (v.type())
9386 {
9387 case value_t::boolean:
9388 {
9389 // 4 and 5 are the string length of "true" and "false"
9390 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9391 break;
9392 }
9393
9394 case value_t::null:
9395 {
9396 // 4 is the string length of "null"
9397 v.start_position = v.end_position - 4;
9398 break;
9399 }
9400
9401 case value_t::string:
9402 {
9403 // include the length of the quotes, which is 2
9404 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9405 break;
9406 }
9407
9408 case value_t::discarded:
9409 {
9410 v.end_position = std::string::npos;
9411 v.start_position = v.end_position;
9412 break;
9413 }
9414
9415 case value_t::binary:
9416 case value_t::number_integer:
9417 case value_t::number_unsigned:
9418 case value_t::number_float:
9419 {
9420 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9421 break;
9422 }
9423
9424 case value_t::object:
9425 case value_t::array:
9426 {
9427 // object and array are handled in start_object() and start_array() handlers
9428 // skip setting the values here.
9429 break;
9430 }
9431 default: // LCOV_EXCL_LINE
9432 // Handle all possible types discretely, default handler should never be reached.
9433 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9434 }
9435 }
9436 }
9437#endif
9438
9454 template<typename Value>
9455 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
9456 {
9457 JSON_ASSERT(!keep_stack.empty());
9458
9459 // do not handle this value if we know it would be added to a discarded
9460 // container
9461 if (!keep_stack.back())
9462 {
9463 return {false, nullptr};
9464 }
9465
9466 // create value
9467 auto value = BasicJsonType(std::forward<Value>(v));
9468
9469#if JSON_DIAGNOSTIC_POSITIONS
9470 handle_diagnostic_positions_for_json_value(value);
9471#endif
9472
9473 // check callback
9474 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
9475
9476 // do not handle this value if we just learnt it shall be discarded
9477 if (!keep)
9478 {
9479 return {false, nullptr};
9480 }
9481
9482 if (ref_stack.empty())
9483 {
9484 root = std::move(value);
9485 return {true, & root};
9486 }
9487
9488 // skip this value if we already decided to skip the parent
9489 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
9490 if (!ref_stack.back())
9491 {
9492 return {false, nullptr};
9493 }
9494
9495 // we now only expect arrays and objects
9496 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9497
9498 // array
9499 if (ref_stack.back()->is_array())
9500 {
9501 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
9502 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
9503 }
9504
9505 // object
9506 JSON_ASSERT(ref_stack.back()->is_object());
9507 // check if we should store an element for the current key
9508 JSON_ASSERT(!key_keep_stack.empty());
9509 const bool store_element = key_keep_stack.back();
9510 key_keep_stack.pop_back();
9511
9512 if (!store_element)
9513 {
9514 return {false, nullptr};
9515 }
9516
9518 *object_element = std::move(value);
9519 return {true, object_element};
9520 }
9521
9523 BasicJsonType& root;
9525 std::vector<BasicJsonType*> ref_stack {};
9527 std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
9529 std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
9531 BasicJsonType* object_element = nullptr;
9533 bool errored = false;
9537 const bool allow_exceptions = true;
9539 BasicJsonType discarded = BasicJsonType::value_t::discarded;
9542};
9543
9544template<typename BasicJsonType>
9546{
9547 public:
9548 using number_integer_t = typename BasicJsonType::number_integer_t;
9549 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9550 using number_float_t = typename BasicJsonType::number_float_t;
9551 using string_t = typename BasicJsonType::string_t;
9552 using binary_t = typename BasicJsonType::binary_t;
9553
9554 bool null()
9555 {
9556 return true;
9557 }
9558
9559 bool boolean(bool /*unused*/)
9560 {
9561 return true;
9562 }
9563
9565 {
9566 return true;
9567 }
9568
9570 {
9571 return true;
9572 }
9573
9574 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
9575 {
9576 return true;
9577 }
9578
9579 bool string(string_t& /*unused*/)
9580 {
9581 return true;
9582 }
9583
9584 bool binary(binary_t& /*unused*/)
9585 {
9586 return true;
9587 }
9588
9589 bool start_object(std::size_t /*unused*/ = detail::unknown_size())
9590 {
9591 return true;
9592 }
9593
9594 bool key(string_t& /*unused*/)
9595 {
9596 return true;
9597 }
9598
9600 {
9601 return true;
9602 }
9603
9604 bool start_array(std::size_t /*unused*/ = detail::unknown_size())
9605 {
9606 return true;
9607 }
9608
9610 {
9611 return true;
9612 }
9613
9614 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
9615 {
9616 return false;
9617 }
9618};
9619
9620} // namespace detail
9622
9623// #include <nlohmann/detail/input/lexer.hpp>
9624
9625// #include <nlohmann/detail/macro_scope.hpp>
9626
9627// #include <nlohmann/detail/meta/is_sax.hpp>
9628// __ _____ _____ _____
9629// __| | __| | | | JSON for Modern C++
9630// | | |__ | | | | | | version 3.11.3
9631// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9632//
9633// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
9634// SPDX-License-Identifier: MIT
9635
9636
9637
9638#include <cstdint> // size_t
9639#include <utility> // declval
9640#include <string> // string
9641
9642// #include <nlohmann/detail/abi_macros.hpp>
9643
9644// #include <nlohmann/detail/meta/detected.hpp>
9645
9646// #include <nlohmann/detail/meta/type_traits.hpp>
9647
9648
9650namespace detail
9651{
9652
9653template<typename T>
9654using null_function_t = decltype(std::declval<T&>().null());
9655
9656template<typename T>
9658 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9659
9660template<typename T, typename Integer>
9662 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9663
9664template<typename T, typename Unsigned>
9666 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9667
9668template<typename T, typename Float, typename String>
9669using number_float_function_t = decltype(std::declval<T&>().number_float(
9670 std::declval<Float>(), std::declval<const String&>()));
9671
9672template<typename T, typename String>
9674 decltype(std::declval<T&>().string(std::declval<String&>()));
9675
9676template<typename T, typename Binary>
9678 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9679
9680template<typename T>
9682 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9683
9684template<typename T, typename String>
9686 decltype(std::declval<T&>().key(std::declval<String&>()));
9687
9688template<typename T>
9689using end_object_function_t = decltype(std::declval<T&>().end_object());
9690
9691template<typename T>
9693 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9694
9695template<typename T>
9696using end_array_function_t = decltype(std::declval<T&>().end_array());
9697
9698template<typename T, typename Exception>
9699using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9700 std::declval<std::size_t>(), std::declval<const std::string&>(),
9701 std::declval<const Exception&>()));
9702
9703template<typename SAX, typename BasicJsonType>
9705{
9706 private:
9708 "BasicJsonType must be of type basic_json<...>");
9709
9710 using number_integer_t = typename BasicJsonType::number_integer_t;
9711 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9712 using number_float_t = typename BasicJsonType::number_float_t;
9713 using string_t = typename BasicJsonType::string_t;
9714 using binary_t = typename BasicJsonType::binary_t;
9715 using exception_t = typename BasicJsonType::exception;
9716
9717 public:
9718 static constexpr bool value =
9732};
9733
9734template<typename SAX, typename BasicJsonType>
9736{
9737 private:
9739 "BasicJsonType must be of type basic_json<...>");
9740
9741 using number_integer_t = typename BasicJsonType::number_integer_t;
9742 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9743 using number_float_t = typename BasicJsonType::number_float_t;
9744 using string_t = typename BasicJsonType::string_t;
9745 using binary_t = typename BasicJsonType::binary_t;
9746 using exception_t = typename BasicJsonType::exception;
9747
9748 public:
9750 "Missing/invalid function: bool null()");
9752 "Missing/invalid function: bool boolean(bool)");
9754 "Missing/invalid function: bool boolean(bool)");
9755 static_assert(
9758 "Missing/invalid function: bool number_integer(number_integer_t)");
9759 static_assert(
9762 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9763 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9765 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9766 static_assert(
9768 "Missing/invalid function: bool string(string_t&)");
9769 static_assert(
9771 "Missing/invalid function: bool binary(binary_t&)");
9773 "Missing/invalid function: bool start_object(std::size_t)");
9775 "Missing/invalid function: bool key(string_t&)");
9777 "Missing/invalid function: bool end_object()");
9779 "Missing/invalid function: bool start_array(std::size_t)");
9781 "Missing/invalid function: bool end_array()");
9782 static_assert(
9784 "Missing/invalid function: bool parse_error(std::size_t, const "
9785 "std::string&, const exception&)");
9786};
9787
9788} // namespace detail
9790
9791// #include <nlohmann/detail/meta/type_traits.hpp>
9792
9793// #include <nlohmann/detail/string_concat.hpp>
9794
9795// #include <nlohmann/detail/value_t.hpp>
9796
9797
9799namespace detail
9800{
9801
9809
9817static inline bool little_endianness(int num = 1) noexcept
9818{
9819 return *reinterpret_cast<char*>(&num) == 1;
9820}
9821
9823// binary reader //
9825
9829template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType, InputAdapterType>>
9831{
9832 using number_integer_t = typename BasicJsonType::number_integer_t;
9833 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9834 using number_float_t = typename BasicJsonType::number_float_t;
9835 using string_t = typename BasicJsonType::string_t;
9836 using binary_t = typename BasicJsonType::binary_t;
9837 using json_sax_t = SAX;
9838 using char_type = typename InputAdapterType::char_type;
9840
9841 public:
9847 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9848 {
9850 }
9851
9852 // make class move-only
9854 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9856 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9857 ~binary_reader() = default;
9858
9868 bool sax_parse(const input_format_t format,
9869 json_sax_t* sax_,
9870 const bool strict = true,
9871 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9872 {
9873 sax = sax_;
9874 bool result = false;
9875
9876 switch (format)
9877 {
9879 result = parse_bson_internal();
9880 break;
9881
9883 result = parse_cbor_internal(true, tag_handler);
9884 break;
9885
9887 result = parse_msgpack_internal();
9888 break;
9889
9892 result = parse_ubjson_internal();
9893 break;
9894
9895 case input_format_t::json: // LCOV_EXCL_LINE
9896 default: // LCOV_EXCL_LINE
9897 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9898 }
9899
9900 // strict mode: next byte must be EOF
9901 if (result && strict)
9902 {
9904 {
9906 }
9907 else
9908 {
9909 get();
9910 }
9911
9913 {
9914 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9915 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9916 }
9917 }
9918
9919 return result;
9920 }
9921
9922 private:
9924 // BSON //
9926
9932 {
9933 std::int32_t document_size{};
9935
9936 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
9937 {
9938 return false;
9939 }
9940
9941 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9942 {
9943 return false;
9944 }
9945
9946 return sax->end_object();
9947 }
9948
9957 {
9958 auto out = std::back_inserter(result);
9959 while (true)
9960 {
9961 get();
9963 {
9964 return false;
9965 }
9966 if (current == 0x00)
9967 {
9968 return true;
9969 }
9970 *out++ = static_cast<typename string_t::value_type>(current);
9971 }
9972 }
9973
9985 template<typename NumberType>
9986 bool get_bson_string(const NumberType len, string_t& result)
9987 {
9988 if (JSON_HEDLEY_UNLIKELY(len < 1))
9989 {
9990 auto last_token = get_token_string();
9991 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9992 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
9993 }
9994
9995 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
9996 }
9997
10007 template<typename NumberType>
10008 bool get_bson_binary(const NumberType len, binary_t& result)
10009 {
10010 if (JSON_HEDLEY_UNLIKELY(len < 0))
10011 {
10012 auto last_token = get_token_string();
10013 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10014 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
10015 }
10016
10017 // All BSON binary values have a subtype
10018 std::uint8_t subtype{};
10020 result.set_subtype(subtype);
10021
10022 return get_binary(input_format_t::bson, len, result);
10023 }
10024
10036 const std::size_t element_type_parse_position)
10037 {
10038 switch (element_type)
10039 {
10040 case 0x01: // double
10041 {
10042 double number{};
10043 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10044 }
10045
10046 case 0x02: // string
10047 {
10048 std::int32_t len{};
10051 }
10052
10053 case 0x03: // object
10054 {
10055 return parse_bson_internal();
10056 }
10057
10058 case 0x04: // array
10059 {
10060 return parse_bson_array();
10061 }
10062
10063 case 0x05: // binary
10064 {
10065 std::int32_t len{};
10068 }
10069
10070 case 0x08: // boolean
10071 {
10072 return sax->boolean(get() != 0);
10073 }
10074
10075 case 0x0A: // null
10076 {
10077 return sax->null();
10078 }
10079
10080 case 0x10: // int32
10081 {
10082 std::int32_t value{};
10084 }
10085
10086 case 0x12: // int64
10087 {
10088 std::int64_t value{};
10090 }
10091
10092 case 0x11: // uint64
10093 {
10094 std::uint64_t value{};
10096 }
10097
10098 default: // anything else not supported (yet)
10099 {
10100 std::array<char, 3> cr{{}};
10101 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10102 const std::string cr_str{cr.data()};
10103 return sax->parse_error(element_type_parse_position, cr_str,
10104 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
10105 }
10106 }
10107 }
10108
10121 bool parse_bson_element_list(const bool is_array)
10122 {
10123 string_t key;
10124
10125 while (auto element_type = get())
10126 {
10128 {
10129 return false;
10130 }
10131
10132 const std::size_t element_type_parse_position = chars_read;
10134 {
10135 return false;
10136 }
10137
10138 if (!is_array && !sax->key(key))
10139 {
10140 return false;
10141 }
10142
10143 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
10144 {
10145 return false;
10146 }
10147
10148 // get_bson_cstr only appends
10149 key.clear();
10150 }
10151
10152 return true;
10153 }
10154
10160 {
10161 std::int32_t document_size{};
10163
10164 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
10165 {
10166 return false;
10167 }
10168
10169 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
10170 {
10171 return false;
10172 }
10173
10174 return sax->end_array();
10175 }
10176
10178 // CBOR //
10180
10189 bool parse_cbor_internal(const bool get_char,
10190 const cbor_tag_handler_t tag_handler)
10191 {
10192 switch (get_char ? get() : current)
10193 {
10194 // EOF
10196 return unexpect_eof(input_format_t::cbor, "value");
10197
10198 // Integer 0x00..0x17 (0..23)
10199 case 0x00:
10200 case 0x01:
10201 case 0x02:
10202 case 0x03:
10203 case 0x04:
10204 case 0x05:
10205 case 0x06:
10206 case 0x07:
10207 case 0x08:
10208 case 0x09:
10209 case 0x0A:
10210 case 0x0B:
10211 case 0x0C:
10212 case 0x0D:
10213 case 0x0E:
10214 case 0x0F:
10215 case 0x10:
10216 case 0x11:
10217 case 0x12:
10218 case 0x13:
10219 case 0x14:
10220 case 0x15:
10221 case 0x16:
10222 case 0x17:
10223 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10224
10225 case 0x18: // Unsigned integer (one-byte uint8_t follows)
10226 {
10227 std::uint8_t number{};
10228 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10229 }
10230
10231 case 0x19: // Unsigned integer (two-byte uint16_t follows)
10232 {
10233 std::uint16_t number{};
10234 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10235 }
10236
10237 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
10238 {
10239 std::uint32_t number{};
10240 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10241 }
10242
10243 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
10244 {
10245 std::uint64_t number{};
10246 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10247 }
10248
10249 // Negative integer -1-0x00..-1-0x17 (-1..-24)
10250 case 0x20:
10251 case 0x21:
10252 case 0x22:
10253 case 0x23:
10254 case 0x24:
10255 case 0x25:
10256 case 0x26:
10257 case 0x27:
10258 case 0x28:
10259 case 0x29:
10260 case 0x2A:
10261 case 0x2B:
10262 case 0x2C:
10263 case 0x2D:
10264 case 0x2E:
10265 case 0x2F:
10266 case 0x30:
10267 case 0x31:
10268 case 0x32:
10269 case 0x33:
10270 case 0x34:
10271 case 0x35:
10272 case 0x36:
10273 case 0x37:
10274 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
10275
10276 case 0x38: // Negative integer (one-byte uint8_t follows)
10277 {
10278 std::uint8_t number{};
10279 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10280 }
10281
10282 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
10283 {
10284 std::uint16_t number{};
10285 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10286 }
10287
10288 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
10289 {
10290 std::uint32_t number{};
10291 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10292 }
10293
10294 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
10295 {
10296 std::uint64_t number{};
10297 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
10298 - static_cast<number_integer_t>(number));
10299 }
10300
10301 // Binary data (0x00..0x17 bytes follow)
10302 case 0x40:
10303 case 0x41:
10304 case 0x42:
10305 case 0x43:
10306 case 0x44:
10307 case 0x45:
10308 case 0x46:
10309 case 0x47:
10310 case 0x48:
10311 case 0x49:
10312 case 0x4A:
10313 case 0x4B:
10314 case 0x4C:
10315 case 0x4D:
10316 case 0x4E:
10317 case 0x4F:
10318 case 0x50:
10319 case 0x51:
10320 case 0x52:
10321 case 0x53:
10322 case 0x54:
10323 case 0x55:
10324 case 0x56:
10325 case 0x57:
10326 case 0x58: // Binary data (one-byte uint8_t for n follows)
10327 case 0x59: // Binary data (two-byte uint16_t for n follow)
10328 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10329 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10330 case 0x5F: // Binary data (indefinite length)
10331 {
10332 binary_t b;
10333 return get_cbor_binary(b) && sax->binary(b);
10334 }
10335
10336 // UTF-8 string (0x00..0x17 bytes follow)
10337 case 0x60:
10338 case 0x61:
10339 case 0x62:
10340 case 0x63:
10341 case 0x64:
10342 case 0x65:
10343 case 0x66:
10344 case 0x67:
10345 case 0x68:
10346 case 0x69:
10347 case 0x6A:
10348 case 0x6B:
10349 case 0x6C:
10350 case 0x6D:
10351 case 0x6E:
10352 case 0x6F:
10353 case 0x70:
10354 case 0x71:
10355 case 0x72:
10356 case 0x73:
10357 case 0x74:
10358 case 0x75:
10359 case 0x76:
10360 case 0x77:
10361 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10362 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10363 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10364 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10365 case 0x7F: // UTF-8 string (indefinite length)
10366 {
10367 string_t s;
10368 return get_cbor_string(s) && sax->string(s);
10369 }
10370
10371 // array (0x00..0x17 data items follow)
10372 case 0x80:
10373 case 0x81:
10374 case 0x82:
10375 case 0x83:
10376 case 0x84:
10377 case 0x85:
10378 case 0x86:
10379 case 0x87:
10380 case 0x88:
10381 case 0x89:
10382 case 0x8A:
10383 case 0x8B:
10384 case 0x8C:
10385 case 0x8D:
10386 case 0x8E:
10387 case 0x8F:
10388 case 0x90:
10389 case 0x91:
10390 case 0x92:
10391 case 0x93:
10392 case 0x94:
10393 case 0x95:
10394 case 0x96:
10395 case 0x97:
10396 return get_cbor_array(
10397 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10398
10399 case 0x98: // array (one-byte uint8_t for n follows)
10400 {
10401 std::uint8_t len{};
10402 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10403 }
10404
10405 case 0x99: // array (two-byte uint16_t for n follow)
10406 {
10407 std::uint16_t len{};
10408 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10409 }
10410
10411 case 0x9A: // array (four-byte uint32_t for n follow)
10412 {
10413 std::uint32_t len{};
10415 }
10416
10417 case 0x9B: // array (eight-byte uint64_t for n follow)
10418 {
10419 std::uint64_t len{};
10421 }
10422
10423 case 0x9F: // array (indefinite length)
10424 return get_cbor_array(detail::unknown_size(), tag_handler);
10425
10426 // map (0x00..0x17 pairs of data items follow)
10427 case 0xA0:
10428 case 0xA1:
10429 case 0xA2:
10430 case 0xA3:
10431 case 0xA4:
10432 case 0xA5:
10433 case 0xA6:
10434 case 0xA7:
10435 case 0xA8:
10436 case 0xA9:
10437 case 0xAA:
10438 case 0xAB:
10439 case 0xAC:
10440 case 0xAD:
10441 case 0xAE:
10442 case 0xAF:
10443 case 0xB0:
10444 case 0xB1:
10445 case 0xB2:
10446 case 0xB3:
10447 case 0xB4:
10448 case 0xB5:
10449 case 0xB6:
10450 case 0xB7:
10451 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10452
10453 case 0xB8: // map (one-byte uint8_t for n follows)
10454 {
10455 std::uint8_t len{};
10456 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10457 }
10458
10459 case 0xB9: // map (two-byte uint16_t for n follow)
10460 {
10461 std::uint16_t len{};
10462 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10463 }
10464
10465 case 0xBA: // map (four-byte uint32_t for n follow)
10466 {
10467 std::uint32_t len{};
10469 }
10470
10471 case 0xBB: // map (eight-byte uint64_t for n follow)
10472 {
10473 std::uint64_t len{};
10475 }
10476
10477 case 0xBF: // map (indefinite length)
10478 return get_cbor_object(detail::unknown_size(), tag_handler);
10479
10480 case 0xC6: // tagged item
10481 case 0xC7:
10482 case 0xC8:
10483 case 0xC9:
10484 case 0xCA:
10485 case 0xCB:
10486 case 0xCC:
10487 case 0xCD:
10488 case 0xCE:
10489 case 0xCF:
10490 case 0xD0:
10491 case 0xD1:
10492 case 0xD2:
10493 case 0xD3:
10494 case 0xD4:
10495 case 0xD8: // tagged item (1 bytes follow)
10496 case 0xD9: // tagged item (2 bytes follow)
10497 case 0xDA: // tagged item (4 bytes follow)
10498 case 0xDB: // tagged item (8 bytes follow)
10499 {
10500 switch (tag_handler)
10501 {
10503 {
10504 auto last_token = get_token_string();
10505 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10506 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10507 }
10508
10510 {
10511 // ignore binary subtype
10512 switch (current)
10513 {
10514 case 0xD8:
10515 {
10516 std::uint8_t subtype_to_ignore{};
10517 get_number(input_format_t::cbor, subtype_to_ignore);
10518 break;
10519 }
10520 case 0xD9:
10521 {
10522 std::uint16_t subtype_to_ignore{};
10523 get_number(input_format_t::cbor, subtype_to_ignore);
10524 break;
10525 }
10526 case 0xDA:
10527 {
10528 std::uint32_t subtype_to_ignore{};
10529 get_number(input_format_t::cbor, subtype_to_ignore);
10530 break;
10531 }
10532 case 0xDB:
10533 {
10534 std::uint64_t subtype_to_ignore{};
10535 get_number(input_format_t::cbor, subtype_to_ignore);
10536 break;
10537 }
10538 default:
10539 break;
10540 }
10541 return parse_cbor_internal(true, tag_handler);
10542 }
10543
10545 {
10546 binary_t b;
10547 // use binary subtype and store in binary container
10548 switch (current)
10549 {
10550 case 0xD8:
10551 {
10552 std::uint8_t subtype{};
10555 break;
10556 }
10557 case 0xD9:
10558 {
10559 std::uint16_t subtype{};
10562 break;
10563 }
10564 case 0xDA:
10565 {
10566 std::uint32_t subtype{};
10569 break;
10570 }
10571 case 0xDB:
10572 {
10573 std::uint64_t subtype{};
10576 break;
10577 }
10578 default:
10579 return parse_cbor_internal(true, tag_handler);
10580 }
10581 get();
10582 return get_cbor_binary(b) && sax->binary(b);
10583 }
10584
10585 default: // LCOV_EXCL_LINE
10586 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10587 return false; // LCOV_EXCL_LINE
10588 }
10589 }
10590
10591 case 0xF4: // false
10592 return sax->boolean(false);
10593
10594 case 0xF5: // true
10595 return sax->boolean(true);
10596
10597 case 0xF6: // null
10598 return sax->null();
10599
10600 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10601 {
10602 const auto byte1_raw = get();
10604 {
10605 return false;
10606 }
10607 const auto byte2_raw = get();
10609 {
10610 return false;
10611 }
10612
10613 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10614 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10615
10616 // code from RFC 7049, Appendix D, Figure 3:
10617 // As half-precision floating-point numbers were only added
10618 // to IEEE 754 in 2008, today's programming platforms often
10619 // still only have limited support for them. It is very
10620 // easy to include at least decoding support for them even
10621 // without such support. An example of a small decoder for
10622 // half-precision floating-point numbers in the C language
10623 // is shown in Fig. 3.
10624 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10625 const double val = [&half]
10626 {
10627 const int exp = (half >> 10u) & 0x1Fu;
10628 const unsigned int mant = half & 0x3FFu;
10629 JSON_ASSERT(0 <= exp&& exp <= 32);
10630 JSON_ASSERT(mant <= 1024);
10631 switch (exp)
10632 {
10633 case 0:
10634 return std::ldexp(mant, -24);
10635 case 31:
10636 return (mant == 0)
10637 ? std::numeric_limits<double>::infinity()
10638 : std::numeric_limits<double>::quiet_NaN();
10639 default:
10640 return std::ldexp(mant + 1024, exp - 25);
10641 }
10642 }();
10643 return sax->number_float((half & 0x8000u) != 0
10644 ? static_cast<number_float_t>(-val)
10645 : static_cast<number_float_t>(val), "");
10646 }
10647
10648 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10649 {
10650 float number{};
10651 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10652 }
10653
10654 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10655 {
10656 double number{};
10657 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10658 }
10659
10660 default: // anything else (0xFF is handled inside the other types)
10661 {
10662 auto last_token = get_token_string();
10663 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10664 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10665 }
10666 }
10667 }
10668
10681 {
10683 {
10684 return false;
10685 }
10686
10687 switch (current)
10688 {
10689 // UTF-8 string (0x00..0x17 bytes follow)
10690 case 0x60:
10691 case 0x61:
10692 case 0x62:
10693 case 0x63:
10694 case 0x64:
10695 case 0x65:
10696 case 0x66:
10697 case 0x67:
10698 case 0x68:
10699 case 0x69:
10700 case 0x6A:
10701 case 0x6B:
10702 case 0x6C:
10703 case 0x6D:
10704 case 0x6E:
10705 case 0x6F:
10706 case 0x70:
10707 case 0x71:
10708 case 0x72:
10709 case 0x73:
10710 case 0x74:
10711 case 0x75:
10712 case 0x76:
10713 case 0x77:
10714 {
10715 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10716 }
10717
10718 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10719 {
10720 std::uint8_t len{};
10721 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10722 }
10723
10724 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10725 {
10726 std::uint16_t len{};
10727 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10728 }
10729
10730 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10731 {
10732 std::uint32_t len{};
10733 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10734 }
10735
10736 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10737 {
10738 std::uint64_t len{};
10739 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10740 }
10741
10742 case 0x7F: // UTF-8 string (indefinite length)
10743 {
10744 while (get() != 0xFF)
10745 {
10746 string_t chunk;
10747 if (!get_cbor_string(chunk))
10748 {
10749 return false;
10750 }
10751 result.append(chunk);
10752 }
10753 return true;
10754 }
10755
10756 default:
10757 {
10758 auto last_token = get_token_string();
10759 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10760 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10761 }
10762 }
10763 }
10764
10777 {
10779 {
10780 return false;
10781 }
10782
10783 switch (current)
10784 {
10785 // Binary data (0x00..0x17 bytes follow)
10786 case 0x40:
10787 case 0x41:
10788 case 0x42:
10789 case 0x43:
10790 case 0x44:
10791 case 0x45:
10792 case 0x46:
10793 case 0x47:
10794 case 0x48:
10795 case 0x49:
10796 case 0x4A:
10797 case 0x4B:
10798 case 0x4C:
10799 case 0x4D:
10800 case 0x4E:
10801 case 0x4F:
10802 case 0x50:
10803 case 0x51:
10804 case 0x52:
10805 case 0x53:
10806 case 0x54:
10807 case 0x55:
10808 case 0x56:
10809 case 0x57:
10810 {
10811 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10812 }
10813
10814 case 0x58: // Binary data (one-byte uint8_t for n follows)
10815 {
10816 std::uint8_t len{};
10817 return get_number(input_format_t::cbor, len) &&
10818 get_binary(input_format_t::cbor, len, result);
10819 }
10820
10821 case 0x59: // Binary data (two-byte uint16_t for n follow)
10822 {
10823 std::uint16_t len{};
10824 return get_number(input_format_t::cbor, len) &&
10825 get_binary(input_format_t::cbor, len, result);
10826 }
10827
10828 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10829 {
10830 std::uint32_t len{};
10831 return get_number(input_format_t::cbor, len) &&
10832 get_binary(input_format_t::cbor, len, result);
10833 }
10834
10835 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10836 {
10837 std::uint64_t len{};
10838 return get_number(input_format_t::cbor, len) &&
10839 get_binary(input_format_t::cbor, len, result);
10840 }
10841
10842 case 0x5F: // Binary data (indefinite length)
10843 {
10844 while (get() != 0xFF)
10845 {
10846 binary_t chunk;
10847 if (!get_cbor_binary(chunk))
10848 {
10849 return false;
10850 }
10851 result.insert(result.end(), chunk.begin(), chunk.end());
10852 }
10853 return true;
10854 }
10855
10856 default:
10857 {
10858 auto last_token = get_token_string();
10859 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10860 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));
10861 }
10862 }
10863 }
10864
10871 bool get_cbor_array(const std::size_t len,
10872 const cbor_tag_handler_t tag_handler)
10873 {
10874 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10875 {
10876 return false;
10877 }
10878
10879 if (len != detail::unknown_size())
10880 {
10881 for (std::size_t i = 0; i < len; ++i)
10882 {
10883 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10884 {
10885 return false;
10886 }
10887 }
10888 }
10889 else
10890 {
10891 while (get() != 0xFF)
10892 {
10893 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10894 {
10895 return false;
10896 }
10897 }
10898 }
10899
10900 return sax->end_array();
10901 }
10902
10909 bool get_cbor_object(const std::size_t len,
10910 const cbor_tag_handler_t tag_handler)
10911 {
10912 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10913 {
10914 return false;
10915 }
10916
10917 if (len != 0)
10918 {
10919 string_t key;
10920 if (len != detail::unknown_size())
10921 {
10922 for (std::size_t i = 0; i < len; ++i)
10923 {
10924 get();
10926 {
10927 return false;
10928 }
10929
10930 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10931 {
10932 return false;
10933 }
10934 key.clear();
10935 }
10936 }
10937 else
10938 {
10939 while (get() != 0xFF)
10940 {
10942 {
10943 return false;
10944 }
10945
10946 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10947 {
10948 return false;
10949 }
10950 key.clear();
10951 }
10952 }
10953 }
10954
10955 return sax->end_object();
10956 }
10957
10959 // MsgPack //
10961
10966 {
10967 switch (get())
10968 {
10969 // EOF
10971 return unexpect_eof(input_format_t::msgpack, "value");
10972
10973 // positive fixint
10974 case 0x00:
10975 case 0x01:
10976 case 0x02:
10977 case 0x03:
10978 case 0x04:
10979 case 0x05:
10980 case 0x06:
10981 case 0x07:
10982 case 0x08:
10983 case 0x09:
10984 case 0x0A:
10985 case 0x0B:
10986 case 0x0C:
10987 case 0x0D:
10988 case 0x0E:
10989 case 0x0F:
10990 case 0x10:
10991 case 0x11:
10992 case 0x12:
10993 case 0x13:
10994 case 0x14:
10995 case 0x15:
10996 case 0x16:
10997 case 0x17:
10998 case 0x18:
10999 case 0x19:
11000 case 0x1A:
11001 case 0x1B:
11002 case 0x1C:
11003 case 0x1D:
11004 case 0x1E:
11005 case 0x1F:
11006 case 0x20:
11007 case 0x21:
11008 case 0x22:
11009 case 0x23:
11010 case 0x24:
11011 case 0x25:
11012 case 0x26:
11013 case 0x27:
11014 case 0x28:
11015 case 0x29:
11016 case 0x2A:
11017 case 0x2B:
11018 case 0x2C:
11019 case 0x2D:
11020 case 0x2E:
11021 case 0x2F:
11022 case 0x30:
11023 case 0x31:
11024 case 0x32:
11025 case 0x33:
11026 case 0x34:
11027 case 0x35:
11028 case 0x36:
11029 case 0x37:
11030 case 0x38:
11031 case 0x39:
11032 case 0x3A:
11033 case 0x3B:
11034 case 0x3C:
11035 case 0x3D:
11036 case 0x3E:
11037 case 0x3F:
11038 case 0x40:
11039 case 0x41:
11040 case 0x42:
11041 case 0x43:
11042 case 0x44:
11043 case 0x45:
11044 case 0x46:
11045 case 0x47:
11046 case 0x48:
11047 case 0x49:
11048 case 0x4A:
11049 case 0x4B:
11050 case 0x4C:
11051 case 0x4D:
11052 case 0x4E:
11053 case 0x4F:
11054 case 0x50:
11055 case 0x51:
11056 case 0x52:
11057 case 0x53:
11058 case 0x54:
11059 case 0x55:
11060 case 0x56:
11061 case 0x57:
11062 case 0x58:
11063 case 0x59:
11064 case 0x5A:
11065 case 0x5B:
11066 case 0x5C:
11067 case 0x5D:
11068 case 0x5E:
11069 case 0x5F:
11070 case 0x60:
11071 case 0x61:
11072 case 0x62:
11073 case 0x63:
11074 case 0x64:
11075 case 0x65:
11076 case 0x66:
11077 case 0x67:
11078 case 0x68:
11079 case 0x69:
11080 case 0x6A:
11081 case 0x6B:
11082 case 0x6C:
11083 case 0x6D:
11084 case 0x6E:
11085 case 0x6F:
11086 case 0x70:
11087 case 0x71:
11088 case 0x72:
11089 case 0x73:
11090 case 0x74:
11091 case 0x75:
11092 case 0x76:
11093 case 0x77:
11094 case 0x78:
11095 case 0x79:
11096 case 0x7A:
11097 case 0x7B:
11098 case 0x7C:
11099 case 0x7D:
11100 case 0x7E:
11101 case 0x7F:
11102 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
11103
11104 // fixmap
11105 case 0x80:
11106 case 0x81:
11107 case 0x82:
11108 case 0x83:
11109 case 0x84:
11110 case 0x85:
11111 case 0x86:
11112 case 0x87:
11113 case 0x88:
11114 case 0x89:
11115 case 0x8A:
11116 case 0x8B:
11117 case 0x8C:
11118 case 0x8D:
11119 case 0x8E:
11120 case 0x8F:
11121 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11122
11123 // fixarray
11124 case 0x90:
11125 case 0x91:
11126 case 0x92:
11127 case 0x93:
11128 case 0x94:
11129 case 0x95:
11130 case 0x96:
11131 case 0x97:
11132 case 0x98:
11133 case 0x99:
11134 case 0x9A:
11135 case 0x9B:
11136 case 0x9C:
11137 case 0x9D:
11138 case 0x9E:
11139 case 0x9F:
11140 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11141
11142 // fixstr
11143 case 0xA0:
11144 case 0xA1:
11145 case 0xA2:
11146 case 0xA3:
11147 case 0xA4:
11148 case 0xA5:
11149 case 0xA6:
11150 case 0xA7:
11151 case 0xA8:
11152 case 0xA9:
11153 case 0xAA:
11154 case 0xAB:
11155 case 0xAC:
11156 case 0xAD:
11157 case 0xAE:
11158 case 0xAF:
11159 case 0xB0:
11160 case 0xB1:
11161 case 0xB2:
11162 case 0xB3:
11163 case 0xB4:
11164 case 0xB5:
11165 case 0xB6:
11166 case 0xB7:
11167 case 0xB8:
11168 case 0xB9:
11169 case 0xBA:
11170 case 0xBB:
11171 case 0xBC:
11172 case 0xBD:
11173 case 0xBE:
11174 case 0xBF:
11175 case 0xD9: // str 8
11176 case 0xDA: // str 16
11177 case 0xDB: // str 32
11178 {
11179 string_t s;
11180 return get_msgpack_string(s) && sax->string(s);
11181 }
11182
11183 case 0xC0: // nil
11184 return sax->null();
11185
11186 case 0xC2: // false
11187 return sax->boolean(false);
11188
11189 case 0xC3: // true
11190 return sax->boolean(true);
11191
11192 case 0xC4: // bin 8
11193 case 0xC5: // bin 16
11194 case 0xC6: // bin 32
11195 case 0xC7: // ext 8
11196 case 0xC8: // ext 16
11197 case 0xC9: // ext 32
11198 case 0xD4: // fixext 1
11199 case 0xD5: // fixext 2
11200 case 0xD6: // fixext 4
11201 case 0xD7: // fixext 8
11202 case 0xD8: // fixext 16
11203 {
11204 binary_t b;
11205 return get_msgpack_binary(b) && sax->binary(b);
11206 }
11207
11208 case 0xCA: // float 32
11209 {
11210 float number{};
11211 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11212 }
11213
11214 case 0xCB: // float 64
11215 {
11216 double number{};
11217 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11218 }
11219
11220 case 0xCC: // uint 8
11221 {
11222 std::uint8_t number{};
11223 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11224 }
11225
11226 case 0xCD: // uint 16
11227 {
11228 std::uint16_t number{};
11229 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11230 }
11231
11232 case 0xCE: // uint 32
11233 {
11234 std::uint32_t number{};
11235 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11236 }
11237
11238 case 0xCF: // uint 64
11239 {
11240 std::uint64_t number{};
11241 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11242 }
11243
11244 case 0xD0: // int 8
11245 {
11246 std::int8_t number{};
11247 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11248 }
11249
11250 case 0xD1: // int 16
11251 {
11252 std::int16_t number{};
11253 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11254 }
11255
11256 case 0xD2: // int 32
11257 {
11258 std::int32_t number{};
11259 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11260 }
11261
11262 case 0xD3: // int 64
11263 {
11264 std::int64_t number{};
11265 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11266 }
11267
11268 case 0xDC: // array 16
11269 {
11270 std::uint16_t len{};
11271 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
11272 }
11273
11274 case 0xDD: // array 32
11275 {
11276 std::uint32_t len{};
11278 }
11279
11280 case 0xDE: // map 16
11281 {
11282 std::uint16_t len{};
11283 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
11284 }
11285
11286 case 0xDF: // map 32
11287 {
11288 std::uint32_t len{};
11290 }
11291
11292 // negative fixint
11293 case 0xE0:
11294 case 0xE1:
11295 case 0xE2:
11296 case 0xE3:
11297 case 0xE4:
11298 case 0xE5:
11299 case 0xE6:
11300 case 0xE7:
11301 case 0xE8:
11302 case 0xE9:
11303 case 0xEA:
11304 case 0xEB:
11305 case 0xEC:
11306 case 0xED:
11307 case 0xEE:
11308 case 0xEF:
11309 case 0xF0:
11310 case 0xF1:
11311 case 0xF2:
11312 case 0xF3:
11313 case 0xF4:
11314 case 0xF5:
11315 case 0xF6:
11316 case 0xF7:
11317 case 0xF8:
11318 case 0xF9:
11319 case 0xFA:
11320 case 0xFB:
11321 case 0xFC:
11322 case 0xFD:
11323 case 0xFE:
11324 case 0xFF:
11325 return sax->number_integer(static_cast<std::int8_t>(current));
11326
11327 default: // anything else
11328 {
11329 auto last_token = get_token_string();
11330 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11331 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
11332 }
11333 }
11334 }
11335
11347 {
11349 {
11350 return false;
11351 }
11352
11353 switch (current)
11354 {
11355 // fixstr
11356 case 0xA0:
11357 case 0xA1:
11358 case 0xA2:
11359 case 0xA3:
11360 case 0xA4:
11361 case 0xA5:
11362 case 0xA6:
11363 case 0xA7:
11364 case 0xA8:
11365 case 0xA9:
11366 case 0xAA:
11367 case 0xAB:
11368 case 0xAC:
11369 case 0xAD:
11370 case 0xAE:
11371 case 0xAF:
11372 case 0xB0:
11373 case 0xB1:
11374 case 0xB2:
11375 case 0xB3:
11376 case 0xB4:
11377 case 0xB5:
11378 case 0xB6:
11379 case 0xB7:
11380 case 0xB8:
11381 case 0xB9:
11382 case 0xBA:
11383 case 0xBB:
11384 case 0xBC:
11385 case 0xBD:
11386 case 0xBE:
11387 case 0xBF:
11388 {
11389 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
11390 }
11391
11392 case 0xD9: // str 8
11393 {
11394 std::uint8_t len{};
11396 }
11397
11398 case 0xDA: // str 16
11399 {
11400 std::uint16_t len{};
11402 }
11403
11404 case 0xDB: // str 32
11405 {
11406 std::uint32_t len{};
11408 }
11409
11410 default:
11411 {
11412 auto last_token = get_token_string();
11413 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11414 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
11415 }
11416 }
11417 }
11418
11430 {
11431 // helper function to set the subtype
11432 auto assign_and_return_true = [&result](std::int8_t subtype)
11433 {
11434 result.set_subtype(static_cast<std::uint8_t>(subtype));
11435 return true;
11436 };
11437
11438 switch (current)
11439 {
11440 case 0xC4: // bin 8
11441 {
11442 std::uint8_t len{};
11443 return get_number(input_format_t::msgpack, len) &&
11444 get_binary(input_format_t::msgpack, len, result);
11445 }
11446
11447 case 0xC5: // bin 16
11448 {
11449 std::uint16_t len{};
11450 return get_number(input_format_t::msgpack, len) &&
11451 get_binary(input_format_t::msgpack, len, result);
11452 }
11453
11454 case 0xC6: // bin 32
11455 {
11456 std::uint32_t len{};
11457 return get_number(input_format_t::msgpack, len) &&
11458 get_binary(input_format_t::msgpack, len, result);
11459 }
11460
11461 case 0xC7: // ext 8
11462 {
11463 std::uint8_t len{};
11464 std::int8_t subtype{};
11465 return get_number(input_format_t::msgpack, len) &&
11467 get_binary(input_format_t::msgpack, len, result) &&
11468 assign_and_return_true(subtype);
11469 }
11470
11471 case 0xC8: // ext 16
11472 {
11473 std::uint16_t len{};
11474 std::int8_t subtype{};
11475 return get_number(input_format_t::msgpack, len) &&
11477 get_binary(input_format_t::msgpack, len, result) &&
11478 assign_and_return_true(subtype);
11479 }
11480
11481 case 0xC9: // ext 32
11482 {
11483 std::uint32_t len{};
11484 std::int8_t subtype{};
11485 return get_number(input_format_t::msgpack, len) &&
11487 get_binary(input_format_t::msgpack, len, result) &&
11488 assign_and_return_true(subtype);
11489 }
11490
11491 case 0xD4: // fixext 1
11492 {
11493 std::int8_t subtype{};
11494 return get_number(input_format_t::msgpack, subtype) &&
11495 get_binary(input_format_t::msgpack, 1, result) &&
11496 assign_and_return_true(subtype);
11497 }
11498
11499 case 0xD5: // fixext 2
11500 {
11501 std::int8_t subtype{};
11502 return get_number(input_format_t::msgpack, subtype) &&
11503 get_binary(input_format_t::msgpack, 2, result) &&
11504 assign_and_return_true(subtype);
11505 }
11506
11507 case 0xD6: // fixext 4
11508 {
11509 std::int8_t subtype{};
11510 return get_number(input_format_t::msgpack, subtype) &&
11511 get_binary(input_format_t::msgpack, 4, result) &&
11512 assign_and_return_true(subtype);
11513 }
11514
11515 case 0xD7: // fixext 8
11516 {
11517 std::int8_t subtype{};
11518 return get_number(input_format_t::msgpack, subtype) &&
11519 get_binary(input_format_t::msgpack, 8, result) &&
11520 assign_and_return_true(subtype);
11521 }
11522
11523 case 0xD8: // fixext 16
11524 {
11525 std::int8_t subtype{};
11526 return get_number(input_format_t::msgpack, subtype) &&
11527 get_binary(input_format_t::msgpack, 16, result) &&
11528 assign_and_return_true(subtype);
11529 }
11530
11531 default: // LCOV_EXCL_LINE
11532 return false; // LCOV_EXCL_LINE
11533 }
11534 }
11535
11540 bool get_msgpack_array(const std::size_t len)
11541 {
11542 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
11543 {
11544 return false;
11545 }
11546
11547 for (std::size_t i = 0; i < len; ++i)
11548 {
11550 {
11551 return false;
11552 }
11553 }
11554
11555 return sax->end_array();
11556 }
11557
11562 bool get_msgpack_object(const std::size_t len)
11563 {
11564 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
11565 {
11566 return false;
11567 }
11568
11569 string_t key;
11570 for (std::size_t i = 0; i < len; ++i)
11571 {
11572 get();
11574 {
11575 return false;
11576 }
11577
11579 {
11580 return false;
11581 }
11582 key.clear();
11583 }
11584
11585 return sax->end_object();
11586 }
11587
11589 // UBJSON //
11591
11599 bool parse_ubjson_internal(const bool get_char = true)
11600 {
11601 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11602 }
11603
11618 bool get_ubjson_string(string_t& result, const bool get_char = true)
11619 {
11620 if (get_char)
11621 {
11622 get(); // TODO(niels): may we ignore N here?
11623 }
11624
11626 {
11627 return false;
11628 }
11629
11630 switch (current)
11631 {
11632 case 'U':
11633 {
11634 std::uint8_t len{};
11635 return get_number(input_format, len) && get_string(input_format, len, result);
11636 }
11637
11638 case 'i':
11639 {
11640 std::int8_t len{};
11641 return get_number(input_format, len) && get_string(input_format, len, result);
11642 }
11643
11644 case 'I':
11645 {
11646 std::int16_t len{};
11647 return get_number(input_format, len) && get_string(input_format, len, result);
11648 }
11649
11650 case 'l':
11651 {
11652 std::int32_t len{};
11653 return get_number(input_format, len) && get_string(input_format, len, result);
11654 }
11655
11656 case 'L':
11657 {
11658 std::int64_t len{};
11659 return get_number(input_format, len) && get_string(input_format, len, result);
11660 }
11661
11662 case 'u':
11663 {
11665 {
11666 break;
11667 }
11668 std::uint16_t len{};
11669 return get_number(input_format, len) && get_string(input_format, len, result);
11670 }
11671
11672 case 'm':
11673 {
11675 {
11676 break;
11677 }
11678 std::uint32_t len{};
11679 return get_number(input_format, len) && get_string(input_format, len, result);
11680 }
11681
11682 case 'M':
11683 {
11685 {
11686 break;
11687 }
11688 std::uint64_t len{};
11689 return get_number(input_format, len) && get_string(input_format, len, result);
11690 }
11691
11692 default:
11693 break;
11694 }
11695 auto last_token = get_token_string();
11696 std::string message;
11697
11699 {
11700 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11701 }
11702 else
11703 {
11704 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11705 }
11706 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11707 }
11708
11713 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11714 {
11715 std::pair<std::size_t, char_int_type> size_and_type;
11716 size_t dimlen = 0;
11717 bool no_ndarray = true;
11718
11719 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11720 {
11721 return false;
11722 }
11723
11724 if (size_and_type.first != npos)
11725 {
11726 if (size_and_type.second != 0)
11727 {
11728 if (size_and_type.second != 'N')
11729 {
11730 for (std::size_t i = 0; i < size_and_type.first; ++i)
11731 {
11732 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11733 {
11734 return false;
11735 }
11736 dim.push_back(dimlen);
11737 }
11738 }
11739 }
11740 else
11741 {
11742 for (std::size_t i = 0; i < size_and_type.first; ++i)
11743 {
11744 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11745 {
11746 return false;
11747 }
11748 dim.push_back(dimlen);
11749 }
11750 }
11751 }
11752 else
11753 {
11754 while (current != ']')
11755 {
11756 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11757 {
11758 return false;
11759 }
11760 dim.push_back(dimlen);
11762 }
11763 }
11764 return true;
11765 }
11766
11778 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11779 {
11780 if (prefix == 0)
11781 {
11782 prefix = get_ignore_noop();
11783 }
11784
11785 switch (prefix)
11786 {
11787 case 'U':
11788 {
11789 std::uint8_t number{};
11791 {
11792 return false;
11793 }
11794 result = static_cast<std::size_t>(number);
11795 return true;
11796 }
11797
11798 case 'i':
11799 {
11800 std::int8_t number{};
11802 {
11803 return false;
11804 }
11805 if (number < 0)
11806 {
11807 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11808 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11809 }
11810 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11811 return true;
11812 }
11813
11814 case 'I':
11815 {
11816 std::int16_t number{};
11818 {
11819 return false;
11820 }
11821 if (number < 0)
11822 {
11823 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11824 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11825 }
11826 result = static_cast<std::size_t>(number);
11827 return true;
11828 }
11829
11830 case 'l':
11831 {
11832 std::int32_t number{};
11834 {
11835 return false;
11836 }
11837 if (number < 0)
11838 {
11839 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11840 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11841 }
11842 result = static_cast<std::size_t>(number);
11843 return true;
11844 }
11845
11846 case 'L':
11847 {
11848 std::int64_t number{};
11850 {
11851 return false;
11852 }
11853 if (number < 0)
11854 {
11855 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11856 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11857 }
11858 if (!value_in_range_of<std::size_t>(number))
11859 {
11860 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11861 exception_message(input_format, "integer value overflow", "size"), nullptr));
11862 }
11863 result = static_cast<std::size_t>(number);
11864 return true;
11865 }
11866
11867 case 'u':
11868 {
11870 {
11871 break;
11872 }
11873 std::uint16_t number{};
11875 {
11876 return false;
11877 }
11878 result = static_cast<std::size_t>(number);
11879 return true;
11880 }
11881
11882 case 'm':
11883 {
11885 {
11886 break;
11887 }
11888 std::uint32_t number{};
11890 {
11891 return false;
11892 }
11893 result = conditional_static_cast<std::size_t>(number);
11894 return true;
11895 }
11896
11897 case 'M':
11898 {
11900 {
11901 break;
11902 }
11903 std::uint64_t number{};
11905 {
11906 return false;
11907 }
11908 if (!value_in_range_of<std::size_t>(number))
11909 {
11910 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11911 exception_message(input_format, "integer value overflow", "size"), nullptr));
11912 }
11914 return true;
11915 }
11916
11917 case '[':
11918 {
11920 {
11921 break;
11922 }
11923 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11924 {
11925 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));
11926 }
11927 std::vector<size_t> dim;
11929 {
11930 return false;
11931 }
11932 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11933 {
11934 result = dim.at(dim.size() - 1);
11935 return true;
11936 }
11937 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11938 {
11939 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11940 {
11941 if ( i == 0 )
11942 {
11943 result = 0;
11944 return true;
11945 }
11946 }
11947
11948 string_t key = "_ArraySize_";
11949 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11950 {
11951 return false;
11952 }
11953 result = 1;
11954 for (auto i : dim)
11955 {
11956 result *= i;
11957 if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type()
11958 {
11959 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));
11960 }
11961 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11962 {
11963 return false;
11964 }
11965 }
11966 is_ndarray = true;
11967 return sax->end_array();
11968 }
11969 result = 0;
11970 return true;
11971 }
11972
11973 default:
11974 break;
11975 }
11976 auto last_token = get_token_string();
11977 std::string message;
11978
11980 {
11981 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11982 }
11983 else
11984 {
11985 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11986 }
11987 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
11988 }
11989
12001 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
12002 {
12003 result.first = npos; // size
12004 result.second = 0; // type
12005 bool is_ndarray = false;
12006
12008
12009 if (current == '$')
12010 {
12011 result.second = get(); // must not ignore 'N', because 'N' maybe the type
12013 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
12014 {
12015 auto last_token = get_token_string();
12016 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12017 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
12018 }
12019
12021 {
12022 return false;
12023 }
12024
12026 if (JSON_HEDLEY_UNLIKELY(current != '#'))
12027 {
12029 {
12030 return false;
12031 }
12032 auto last_token = get_token_string();
12033 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12034 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
12035 }
12036
12037 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12038 if (input_format == input_format_t::bjdata && is_ndarray)
12039 {
12040 if (inside_ndarray)
12041 {
12042 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12043 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
12044 }
12045 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
12046 }
12047 return is_error;
12048 }
12049
12050 if (current == '#')
12051 {
12052 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12053 if (input_format == input_format_t::bjdata && is_ndarray)
12054 {
12055 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12056 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
12057 }
12058 return is_error;
12059 }
12060
12061 return true;
12062 }
12063
12069 {
12070 switch (prefix)
12071 {
12072 case char_traits<char_type>::eof(): // EOF
12073 return unexpect_eof(input_format, "value");
12074
12075 case 'T': // true
12076 return sax->boolean(true);
12077 case 'F': // false
12078 return sax->boolean(false);
12079
12080 case 'Z': // null
12081 return sax->null();
12082
12083 case 'B': // byte
12084 {
12086 {
12087 break;
12088 }
12089 std::uint8_t number{};
12090 return get_number(input_format, number) && sax->number_unsigned(number);
12091 }
12092
12093 case 'U':
12094 {
12095 std::uint8_t number{};
12096 return get_number(input_format, number) && sax->number_unsigned(number);
12097 }
12098
12099 case 'i':
12100 {
12101 std::int8_t number{};
12102 return get_number(input_format, number) && sax->number_integer(number);
12103 }
12104
12105 case 'I':
12106 {
12107 std::int16_t number{};
12108 return get_number(input_format, number) && sax->number_integer(number);
12109 }
12110
12111 case 'l':
12112 {
12113 std::int32_t number{};
12114 return get_number(input_format, number) && sax->number_integer(number);
12115 }
12116
12117 case 'L':
12118 {
12119 std::int64_t number{};
12120 return get_number(input_format, number) && sax->number_integer(number);
12121 }
12122
12123 case 'u':
12124 {
12126 {
12127 break;
12128 }
12129 std::uint16_t number{};
12130 return get_number(input_format, number) && sax->number_unsigned(number);
12131 }
12132
12133 case 'm':
12134 {
12136 {
12137 break;
12138 }
12139 std::uint32_t number{};
12140 return get_number(input_format, number) && sax->number_unsigned(number);
12141 }
12142
12143 case 'M':
12144 {
12146 {
12147 break;
12148 }
12149 std::uint64_t number{};
12150 return get_number(input_format, number) && sax->number_unsigned(number);
12151 }
12152
12153 case 'h':
12154 {
12156 {
12157 break;
12158 }
12159 const auto byte1_raw = get();
12161 {
12162 return false;
12163 }
12164 const auto byte2_raw = get();
12166 {
12167 return false;
12168 }
12169
12170 const auto byte1 = static_cast<unsigned char>(byte1_raw);
12171 const auto byte2 = static_cast<unsigned char>(byte2_raw);
12172
12173 // code from RFC 7049, Appendix D, Figure 3:
12174 // As half-precision floating-point numbers were only added
12175 // to IEEE 754 in 2008, today's programming platforms often
12176 // still only have limited support for them. It is very
12177 // easy to include at least decoding support for them even
12178 // without such support. An example of a small decoder for
12179 // half-precision floating-point numbers in the C language
12180 // is shown in Fig. 3.
12181 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
12182 const double val = [&half]
12183 {
12184 const int exp = (half >> 10u) & 0x1Fu;
12185 const unsigned int mant = half & 0x3FFu;
12186 JSON_ASSERT(0 <= exp&& exp <= 32);
12187 JSON_ASSERT(mant <= 1024);
12188 switch (exp)
12189 {
12190 case 0:
12191 return std::ldexp(mant, -24);
12192 case 31:
12193 return (mant == 0)
12194 ? std::numeric_limits<double>::infinity()
12195 : std::numeric_limits<double>::quiet_NaN();
12196 default:
12197 return std::ldexp(mant + 1024, exp - 25);
12198 }
12199 }();
12200 return sax->number_float((half & 0x8000u) != 0
12201 ? static_cast<number_float_t>(-val)
12202 : static_cast<number_float_t>(val), "");
12203 }
12204
12205 case 'd':
12206 {
12207 float number{};
12208 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12209 }
12210
12211 case 'D':
12212 {
12213 double number{};
12214 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12215 }
12216
12217 case 'H':
12218 {
12220 }
12221
12222 case 'C': // char
12223 {
12224 get();
12226 {
12227 return false;
12228 }
12229 if (JSON_HEDLEY_UNLIKELY(current > 127))
12230 {
12231 auto last_token = get_token_string();
12232 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
12233 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
12234 }
12235 string_t s(1, static_cast<typename string_t::value_type>(current));
12236 return sax->string(s);
12237 }
12238
12239 case 'S': // string
12240 {
12241 string_t s;
12242 return get_ubjson_string(s) && sax->string(s);
12243 }
12244
12245 case '[': // array
12246 return get_ubjson_array();
12247
12248 case '{': // object
12249 return get_ubjson_object();
12250
12251 default: // anything else
12252 break;
12253 }
12254 auto last_token = get_token_string();
12255 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));
12256 }
12257
12262 {
12263 std::pair<std::size_t, char_int_type> size_and_type;
12264 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12265 {
12266 return false;
12267 }
12268
12269 // 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):
12270 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
12271
12272 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12273 {
12274 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
12275 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)
12276 {
12277 return p.first < t;
12278 });
12279 string_t key = "_ArrayType_";
12280 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
12281 {
12282 auto last_token = get_token_string();
12283 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12284 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
12285 }
12286
12287 string_t type = it->second; // sax->string() takes a reference
12288 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
12289 {
12290 return false;
12291 }
12292
12293 if (size_and_type.second == 'C' || size_and_type.second == 'B')
12294 {
12295 size_and_type.second = 'U';
12296 }
12297
12298 key = "_ArrayData_";
12299 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
12300 {
12301 return false;
12302 }
12303
12304 for (std::size_t i = 0; i < size_and_type.first; ++i)
12305 {
12306 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12307 {
12308 return false;
12309 }
12310 }
12311
12312 return (sax->end_array() && sax->end_object());
12313 }
12314
12315 // If BJData type marker is 'B' decode as binary
12316 if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second == 'B')
12317 {
12318 binary_t result;
12319 return get_binary(input_format, size_and_type.first, result) && sax->binary(result);
12320 }
12321
12322 if (size_and_type.first != npos)
12323 {
12324 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
12325 {
12326 return false;
12327 }
12328
12329 if (size_and_type.second != 0)
12330 {
12331 if (size_and_type.second != 'N')
12332 {
12333 for (std::size_t i = 0; i < size_and_type.first; ++i)
12334 {
12335 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12336 {
12337 return false;
12338 }
12339 }
12340 }
12341 }
12342 else
12343 {
12344 for (std::size_t i = 0; i < size_and_type.first; ++i)
12345 {
12347 {
12348 return false;
12349 }
12350 }
12351 }
12352 }
12353 else
12354 {
12355 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
12356 {
12357 return false;
12358 }
12359
12360 while (current != ']')
12361 {
12363 {
12364 return false;
12365 }
12367 }
12368 }
12369
12370 return sax->end_array();
12371 }
12372
12377 {
12378 std::pair<std::size_t, char_int_type> size_and_type;
12379 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12380 {
12381 return false;
12382 }
12383
12384 // do not accept ND-array size in objects in BJData
12385 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12386 {
12387 auto last_token = get_token_string();
12388 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12389 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
12390 }
12391
12392 string_t key;
12393 if (size_and_type.first != npos)
12394 {
12395 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
12396 {
12397 return false;
12398 }
12399
12400 if (size_and_type.second != 0)
12401 {
12402 for (std::size_t i = 0; i < size_and_type.first; ++i)
12403 {
12405 {
12406 return false;
12407 }
12408 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12409 {
12410 return false;
12411 }
12412 key.clear();
12413 }
12414 }
12415 else
12416 {
12417 for (std::size_t i = 0; i < size_and_type.first; ++i)
12418 {
12420 {
12421 return false;
12422 }
12424 {
12425 return false;
12426 }
12427 key.clear();
12428 }
12429 }
12430 }
12431 else
12432 {
12433 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
12434 {
12435 return false;
12436 }
12437
12438 while (current != '}')
12439 {
12440 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
12441 {
12442 return false;
12443 }
12445 {
12446 return false;
12447 }
12449 key.clear();
12450 }
12451 }
12452
12453 return sax->end_object();
12454 }
12455
12456 // Note, no reader for UBJSON binary types is implemented because they do
12457 // not exist
12458
12460 {
12461 // get size of following number string
12462 std::size_t size{};
12463 bool no_ndarray = true;
12464 auto res = get_ubjson_size_value(size, no_ndarray);
12465 if (JSON_HEDLEY_UNLIKELY(!res))
12466 {
12467 return res;
12468 }
12469
12470 // get number string
12471 std::vector<char> number_vector;
12472 for (std::size_t i = 0; i < size; ++i)
12473 {
12474 get();
12476 {
12477 return false;
12478 }
12479 number_vector.push_back(static_cast<char>(current));
12480 }
12481
12482 // parse number string
12483 using ia_type = decltype(detail::input_adapter(number_vector));
12484 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
12485 const auto result_number = number_lexer.scan();
12486 const auto number_string = number_lexer.get_token_string();
12487 const auto result_remainder = number_lexer.scan();
12488
12489 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
12490
12491 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
12492 {
12493 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12494 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12495 }
12496
12497 switch (result_number)
12498 {
12499 case token_type::value_integer:
12500 return sax->number_integer(number_lexer.get_number_integer());
12501 case token_type::value_unsigned:
12502 return sax->number_unsigned(number_lexer.get_number_unsigned());
12503 case token_type::value_float:
12504 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
12505 case token_type::uninitialized:
12506 case token_type::literal_true:
12507 case token_type::literal_false:
12508 case token_type::literal_null:
12509 case token_type::value_string:
12510 case token_type::begin_array:
12511 case token_type::begin_object:
12512 case token_type::end_array:
12513 case token_type::end_object:
12514 case token_type::name_separator:
12515 case token_type::value_separator:
12516 case token_type::parse_error:
12517 case token_type::end_of_input:
12518 case token_type::literal_or_value:
12519 default:
12520 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12521 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12522 }
12523 }
12524
12526 // Utility functions //
12528
12539 {
12540 ++chars_read;
12541 return current = ia.get_character();
12542 }
12543
12552 template<class T>
12553 bool get_to(T& dest, const input_format_t format, const char* context)
12554 {
12555 auto new_chars_read = ia.get_elements(&dest);
12556 chars_read += new_chars_read;
12557 if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T)))
12558 {
12559 // in case of failure, advance position by 1 to report failing location
12560 ++chars_read;
12561 sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12562 return false;
12563 }
12564 return true;
12565 }
12566
12571 {
12572 do
12573 {
12574 get();
12575 }
12576 while (current == 'N');
12577
12578 return current;
12579 }
12580
12581 template<class NumberType>
12582 static void byte_swap(NumberType& number)
12583 {
12584 constexpr std::size_t sz = sizeof(number);
12585#ifdef __cpp_lib_byteswap
12586 if constexpr (sz == 1)
12587 {
12588 return;
12589 }
12590 if constexpr(std::is_integral_v<NumberType>)
12591 {
12592 number = std::byteswap(number);
12593 return;
12594 }
12595#endif
12596 auto* ptr = reinterpret_cast<std::uint8_t*>(&number);
12597 for (std::size_t i = 0; i < sz / 2; ++i)
12598 {
12599 std::swap(ptr[i], ptr[sz - i - 1]);
12600 }
12601 }
12602
12603 /*
12604 @brief read a number from the input
12605
12606 @tparam NumberType the type of the number
12607 @param[in] format the current format (for diagnostics)
12608 @param[out] result number of type @a NumberType
12609
12610 @return whether conversion completed
12611
12612 @note This function needs to respect the system's endianness, because
12613 bytes in CBOR, MessagePack, and UBJSON are stored in network order
12614 (big endian) and therefore need reordering on little endian systems.
12615 On the other hand, BSON and BJData use little endian and should reorder
12616 on big endian systems.
12617 */
12618 template<typename NumberType, bool InputIsLittleEndian = false>
12619 bool get_number(const input_format_t format, NumberType& result)
12620 {
12621 // read in the original format
12622
12623 if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number")))
12624 {
12625 return false;
12626 }
12627 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
12628 {
12629 byte_swap(result);
12630 }
12631 return true;
12632 }
12633
12648 template<typename NumberType>
12649 bool get_string(const input_format_t format,
12650 const NumberType len,
12651 string_t& result)
12652 {
12653 bool success = true;
12654 for (NumberType i = 0; i < len; i++)
12655 {
12656 get();
12657 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
12658 {
12659 success = false;
12660 break;
12661 }
12662 result.push_back(static_cast<typename string_t::value_type>(current));
12663 }
12664 return success;
12665 }
12666
12681 template<typename NumberType>
12682 bool get_binary(const input_format_t format,
12683 const NumberType len,
12684 binary_t& result)
12685 {
12686 bool success = true;
12687 for (NumberType i = 0; i < len; i++)
12688 {
12689 get();
12690 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12691 {
12692 success = false;
12693 break;
12694 }
12695 result.push_back(static_cast<std::uint8_t>(current));
12696 }
12697 return success;
12698 }
12699
12706 bool unexpect_eof(const input_format_t format, const char* context) const
12707 {
12709 {
12710 return sax->parse_error(chars_read, "<end of file>",
12711 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12712 }
12713 return true;
12714 }
12715
12719 std::string get_token_string() const
12720 {
12721 std::array<char, 3> cr{{}};
12722 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12723 return std::string{cr.data()};
12724 }
12725
12732 std::string exception_message(const input_format_t format,
12733 const std::string& detail,
12734 const std::string& context) const
12735 {
12736 std::string error_msg = "syntax error while parsing ";
12737
12738 switch (format)
12739 {
12741 error_msg += "CBOR";
12742 break;
12743
12745 error_msg += "MessagePack";
12746 break;
12747
12749 error_msg += "UBJSON";
12750 break;
12751
12753 error_msg += "BSON";
12754 break;
12755
12757 error_msg += "BJData";
12758 break;
12759
12760 case input_format_t::json: // LCOV_EXCL_LINE
12761 default: // LCOV_EXCL_LINE
12762 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12763 }
12764
12765 return concat(error_msg, ' ', context, ": ", detail);
12766 }
12767
12768 private:
12769 static JSON_INLINE_VARIABLE constexpr std::size_t npos = detail::unknown_size();
12770
12772 InputAdapterType ia;
12773
12776
12778 std::size_t chars_read = 0;
12779
12782
12785
12787 json_sax_t* sax = nullptr;
12788
12789 // excluded markers in bjdata optimized type
12790#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12791 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12792
12793#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12794 make_array<bjd_type>( \
12795 bjd_type{'B', "byte"}, \
12796 bjd_type{'C', "char"}, \
12797 bjd_type{'D', "double"}, \
12798 bjd_type{'I', "int16"}, \
12799 bjd_type{'L', "int64"}, \
12800 bjd_type{'M', "uint64"}, \
12801 bjd_type{'U', "uint8"}, \
12802 bjd_type{'d', "single"}, \
12803 bjd_type{'i', "int8"}, \
12804 bjd_type{'l', "int32"}, \
12805 bjd_type{'m', "uint32"}, \
12806 bjd_type{'u', "uint16"})
12807
12809 // lookup tables
12810 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12811 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12813
12814 using bjd_type = std::pair<char_int_type, string_t>;
12815 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12818
12819#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12820#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12821};
12822
12823#ifndef JSON_HAS_CPP_17
12824 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12826#endif
12827
12828} // namespace detail
12830
12831// #include <nlohmann/detail/input/input_adapters.hpp>
12832
12833// #include <nlohmann/detail/input/lexer.hpp>
12834
12835// #include <nlohmann/detail/input/parser.hpp>
12836// __ _____ _____ _____
12837// __| | __| | | | JSON for Modern C++
12838// | | |__ | | | | | | version 3.11.3
12839// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12840//
12841// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
12842// SPDX-License-Identifier: MIT
12843
12844
12845
12846#include <cmath> // isfinite
12847#include <cstdint> // uint8_t
12848#include <functional> // function
12849#include <string> // string
12850#include <utility> // move
12851#include <vector> // vector
12852
12853// #include <nlohmann/detail/exceptions.hpp>
12854
12855// #include <nlohmann/detail/input/input_adapters.hpp>
12856
12857// #include <nlohmann/detail/input/json_sax.hpp>
12858
12859// #include <nlohmann/detail/input/lexer.hpp>
12860
12861// #include <nlohmann/detail/macro_scope.hpp>
12862
12863// #include <nlohmann/detail/meta/is_sax.hpp>
12864
12865// #include <nlohmann/detail/string_concat.hpp>
12866
12867// #include <nlohmann/detail/value_t.hpp>
12868
12869
12871namespace detail
12872{
12874// parser //
12876
12892
12893template<typename BasicJsonType>
12895 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12896
12902template<typename BasicJsonType, typename InputAdapterType>
12904{
12905 using number_integer_t = typename BasicJsonType::number_integer_t;
12906 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12907 using number_float_t = typename BasicJsonType::number_float_t;
12908 using string_t = typename BasicJsonType::string_t;
12911
12912 public:
12914 explicit parser(InputAdapterType&& adapter,
12916 const bool allow_exceptions_ = true,
12917 const bool skip_comments = false)
12918 : callback(std::move(cb))
12919 , m_lexer(std::move(adapter), skip_comments)
12920 , allow_exceptions(allow_exceptions_)
12921 {
12922 // read first token
12923 get_token();
12924 }
12925
12936 void parse(const bool strict, BasicJsonType& result)
12937 {
12938 if (callback)
12939 {
12941 sax_parse_internal(&sdp);
12942
12943 // in strict mode, input must be completely read
12944 if (strict && (get_token() != token_type::end_of_input))
12945 {
12946 sdp.parse_error(m_lexer.get_position(),
12947 m_lexer.get_token_string(),
12948 parse_error::create(101, m_lexer.get_position(),
12949 exception_message(token_type::end_of_input, "value"), nullptr));
12950 }
12951
12952 // in case of an error, return discarded value
12953 if (sdp.is_errored())
12954 {
12955 result = value_t::discarded;
12956 return;
12957 }
12958
12959 // set top-level value to null if it was discarded by the callback
12960 // function
12961 if (result.is_discarded())
12962 {
12963 result = nullptr;
12964 }
12965 }
12966 else
12967 {
12969 sax_parse_internal(&sdp);
12970
12971 // in strict mode, input must be completely read
12972 if (strict && (get_token() != token_type::end_of_input))
12973 {
12974 sdp.parse_error(m_lexer.get_position(),
12975 m_lexer.get_token_string(),
12976 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12977 }
12978
12979 // in case of an error, return discarded value
12980 if (sdp.is_errored())
12981 {
12982 result = value_t::discarded;
12983 return;
12984 }
12985 }
12986
12987 result.assert_invariant();
12988 }
12989
12996 bool accept(const bool strict = true)
12997 {
12999 return sax_parse(&sax_acceptor, strict);
13000 }
13001
13002 template<typename SAX>
13004 bool sax_parse(SAX* sax, const bool strict = true)
13005 {
13007 const bool result = sax_parse_internal(sax);
13008
13009 // strict mode: next byte must be EOF
13010 if (result && strict && (get_token() != token_type::end_of_input))
13011 {
13012 return sax->parse_error(m_lexer.get_position(),
13013 m_lexer.get_token_string(),
13014 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13015 }
13016
13017 return result;
13018 }
13019
13020 private:
13021 template<typename SAX>
13023 bool sax_parse_internal(SAX* sax)
13024 {
13025 // stack to remember the hierarchy of structured values we are parsing
13026 // true = array; false = object
13027 std::vector<bool> states;
13028 // value to avoid a goto (see comment where set to true)
13029 bool skip_to_state_evaluation = false;
13030
13031 while (true)
13032 {
13033 if (!skip_to_state_evaluation)
13034 {
13035 // invariant: get_token() was called before each iteration
13036 switch (last_token)
13037 {
13038 case token_type::begin_object:
13039 {
13040 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
13041 {
13042 return false;
13043 }
13044
13045 // closing } -> we are done
13046 if (get_token() == token_type::end_object)
13047 {
13048 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13049 {
13050 return false;
13051 }
13052 break;
13053 }
13054
13055 // parse key
13056 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13057 {
13058 return sax->parse_error(m_lexer.get_position(),
13059 m_lexer.get_token_string(),
13060 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13061 }
13062 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13063 {
13064 return false;
13065 }
13066
13067 // parse separator (:)
13068 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13069 {
13070 return sax->parse_error(m_lexer.get_position(),
13071 m_lexer.get_token_string(),
13072 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13073 }
13074
13075 // remember we are now inside an object
13076 states.push_back(false);
13077
13078 // parse values
13079 get_token();
13080 continue;
13081 }
13082
13083 case token_type::begin_array:
13084 {
13085 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
13086 {
13087 return false;
13088 }
13089
13090 // closing ] -> we are done
13091 if (get_token() == token_type::end_array)
13092 {
13093 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13094 {
13095 return false;
13096 }
13097 break;
13098 }
13099
13100 // remember we are now inside an array
13101 states.push_back(true);
13102
13103 // parse values (no need to call get_token)
13104 continue;
13105 }
13106
13107 case token_type::value_float:
13108 {
13109 const auto res = m_lexer.get_number_float();
13110
13111 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
13112 {
13113 return sax->parse_error(m_lexer.get_position(),
13114 m_lexer.get_token_string(),
13115 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
13116 }
13117
13118 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
13119 {
13120 return false;
13121 }
13122
13123 break;
13124 }
13125
13126 case token_type::literal_false:
13127 {
13128 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
13129 {
13130 return false;
13131 }
13132 break;
13133 }
13134
13135 case token_type::literal_null:
13136 {
13137 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
13138 {
13139 return false;
13140 }
13141 break;
13142 }
13143
13144 case token_type::literal_true:
13145 {
13146 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
13147 {
13148 return false;
13149 }
13150 break;
13151 }
13152
13153 case token_type::value_integer:
13154 {
13155 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
13156 {
13157 return false;
13158 }
13159 break;
13160 }
13161
13162 case token_type::value_string:
13163 {
13164 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
13165 {
13166 return false;
13167 }
13168 break;
13169 }
13170
13171 case token_type::value_unsigned:
13172 {
13173 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
13174 {
13175 return false;
13176 }
13177 break;
13178 }
13179
13180 case token_type::parse_error:
13181 {
13182 // using "uninitialized" to avoid "expected" message
13183 return sax->parse_error(m_lexer.get_position(),
13184 m_lexer.get_token_string(),
13185 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
13186 }
13187 case token_type::end_of_input:
13188 {
13189 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
13190 {
13191 return sax->parse_error(m_lexer.get_position(),
13192 m_lexer.get_token_string(),
13193 parse_error::create(101, m_lexer.get_position(),
13194 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
13195 }
13196
13197 return sax->parse_error(m_lexer.get_position(),
13198 m_lexer.get_token_string(),
13199 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13200 }
13201 case token_type::uninitialized:
13202 case token_type::end_array:
13203 case token_type::end_object:
13204 case token_type::name_separator:
13205 case token_type::value_separator:
13206 case token_type::literal_or_value:
13207 default: // the last token was unexpected
13208 {
13209 return sax->parse_error(m_lexer.get_position(),
13210 m_lexer.get_token_string(),
13211 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13212 }
13213 }
13214 }
13215 else
13216 {
13217 skip_to_state_evaluation = false;
13218 }
13219
13220 // we reached this line after we successfully parsed a value
13221 if (states.empty())
13222 {
13223 // empty stack: we reached the end of the hierarchy: done
13224 return true;
13225 }
13226
13227 if (states.back()) // array
13228 {
13229 // comma -> next value
13230 if (get_token() == token_type::value_separator)
13231 {
13232 // parse a new value
13233 get_token();
13234 continue;
13235 }
13236
13237 // closing ]
13238 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
13239 {
13240 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13241 {
13242 return false;
13243 }
13244
13245 // We are done with this array. Before we can parse a
13246 // new value, we need to evaluate the new state first.
13247 // By setting skip_to_state_evaluation to false, we
13248 // are effectively jumping to the beginning of this if.
13249 JSON_ASSERT(!states.empty());
13250 states.pop_back();
13251 skip_to_state_evaluation = true;
13252 continue;
13253 }
13254
13255 return sax->parse_error(m_lexer.get_position(),
13256 m_lexer.get_token_string(),
13257 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
13258 }
13259
13260 // states.back() is false -> object
13261
13262 // comma -> next value
13263 if (get_token() == token_type::value_separator)
13264 {
13265 // parse key
13266 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
13267 {
13268 return sax->parse_error(m_lexer.get_position(),
13269 m_lexer.get_token_string(),
13270 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13271 }
13272
13273 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13274 {
13275 return false;
13276 }
13277
13278 // parse separator (:)
13279 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13280 {
13281 return sax->parse_error(m_lexer.get_position(),
13282 m_lexer.get_token_string(),
13283 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13284 }
13285
13286 // parse values
13287 get_token();
13288 continue;
13289 }
13290
13291 // closing }
13292 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
13293 {
13294 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13295 {
13296 return false;
13297 }
13298
13299 // We are done with this object. Before we can parse a
13300 // new value, we need to evaluate the new state first.
13301 // By setting skip_to_state_evaluation to false, we
13302 // are effectively jumping to the beginning of this if.
13303 JSON_ASSERT(!states.empty());
13304 states.pop_back();
13305 skip_to_state_evaluation = true;
13306 continue;
13307 }
13308
13309 return sax->parse_error(m_lexer.get_position(),
13310 m_lexer.get_token_string(),
13311 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
13312 }
13313 }
13314
13317 {
13318 return last_token = m_lexer.scan();
13319 }
13320
13321 std::string exception_message(const token_type expected, const std::string& context)
13322 {
13323 std::string error_msg = "syntax error ";
13324
13325 if (!context.empty())
13326 {
13327 error_msg += concat("while parsing ", context, ' ');
13328 }
13329
13330 error_msg += "- ";
13331
13332 if (last_token == token_type::parse_error)
13333 {
13334 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
13335 m_lexer.get_token_string(), '\'');
13336 }
13337 else
13338 {
13339 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
13340 }
13341
13342 if (expected != token_type::uninitialized)
13343 {
13344 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
13345 }
13346
13347 return error_msg;
13348 }
13349
13350 private:
13354 token_type last_token = token_type::uninitialized;
13358 const bool allow_exceptions = true;
13359};
13360
13361} // namespace detail
13363
13364// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13365// __ _____ _____ _____
13366// __| | __| | | | JSON for Modern C++
13367// | | |__ | | | | | | version 3.11.3
13368// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13369//
13370// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13371// SPDX-License-Identifier: MIT
13372
13373
13374
13375// #include <nlohmann/detail/abi_macros.hpp>
13376
13377// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13378// __ _____ _____ _____
13379// __| | __| | | | JSON for Modern C++
13380// | | |__ | | | | | | version 3.11.3
13381// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13382//
13383// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13384// SPDX-License-Identifier: MIT
13385
13386
13387
13388#include <cstddef> // ptrdiff_t
13389#include <limits> // numeric_limits
13390
13391// #include <nlohmann/detail/macro_scope.hpp>
13392
13393
13395namespace detail
13396{
13397
13398/*
13399@brief an iterator for primitive JSON types
13400
13401This class models an iterator for primitive JSON types (boolean, number,
13402string). It's only purpose is to allow the iterator/const_iterator classes
13403to "iterate" over primitive values. Internally, the iterator is modeled by
13404a `difference_type` variable. Value begin_value (`0`) models the begin,
13405end_value (`1`) models past the end.
13406*/
13408{
13409 private:
13410 using difference_type = std::ptrdiff_t;
13411 static constexpr difference_type begin_value = 0;
13412 static constexpr difference_type end_value = begin_value + 1;
13413
13416 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
13417
13418 public:
13419 constexpr difference_type get_value() const noexcept
13420 {
13421 return m_it;
13422 }
13423
13425 void set_begin() noexcept
13426 {
13427 m_it = begin_value;
13428 }
13429
13431 void set_end() noexcept
13432 {
13433 m_it = end_value;
13434 }
13435
13437 constexpr bool is_begin() const noexcept
13438 {
13439 return m_it == begin_value;
13440 }
13441
13443 constexpr bool is_end() const noexcept
13444 {
13445 return m_it == end_value;
13446 }
13447
13448 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13449 {
13450 return lhs.m_it == rhs.m_it;
13451 }
13452
13453 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13454 {
13455 return lhs.m_it < rhs.m_it;
13456 }
13457
13459 {
13460 auto result = *this;
13461 result += n;
13462 return result;
13463 }
13464
13466 {
13467 return lhs.m_it - rhs.m_it;
13468 }
13469
13471 {
13472 ++m_it;
13473 return *this;
13474 }
13475
13476 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
13477 {
13478 auto result = *this;
13479 ++m_it;
13480 return result;
13481 }
13482
13484 {
13485 --m_it;
13486 return *this;
13487 }
13488
13489 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
13490 {
13491 auto result = *this;
13492 --m_it;
13493 return result;
13494 }
13495
13497 {
13498 m_it += n;
13499 return *this;
13500 }
13501
13503 {
13504 m_it -= n;
13505 return *this;
13506 }
13507};
13508
13509} // namespace detail
13511
13512
13514namespace detail
13515{
13516
13523template<typename BasicJsonType> struct internal_iterator
13524{
13526 typename BasicJsonType::object_t::iterator object_iterator {};
13528 typename BasicJsonType::array_t::iterator array_iterator {};
13531};
13532
13533} // namespace detail
13535
13536// #include <nlohmann/detail/iterators/iter_impl.hpp>
13537// __ _____ _____ _____
13538// __| | __| | | | JSON for Modern C++
13539// | | |__ | | | | | | version 3.11.3
13540// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13541//
13542// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13543// SPDX-License-Identifier: MIT
13544
13545
13546
13547#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
13548#include <type_traits> // conditional, is_const, remove_const
13549
13550// #include <nlohmann/detail/exceptions.hpp>
13551
13552// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13553
13554// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13555
13556// #include <nlohmann/detail/macro_scope.hpp>
13557
13558// #include <nlohmann/detail/meta/cpp_future.hpp>
13559
13560// #include <nlohmann/detail/meta/type_traits.hpp>
13561
13562// #include <nlohmann/detail/value_t.hpp>
13563
13564
13566namespace detail
13567{
13568
13569// forward declare, to be able to friend it later on
13570template<typename IteratorType> class iteration_proxy;
13571template<typename IteratorType> class iteration_proxy_value;
13572
13589template<typename BasicJsonType>
13590class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
13591{
13593 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
13599
13600 using object_t = typename BasicJsonType::object_t;
13601 using array_t = typename BasicJsonType::array_t;
13602 // make sure BasicJsonType is basic_json or const basic_json
13604 "iter_impl only accepts (const) basic_json");
13605 // superficial check for the LegacyBidirectionalIterator named requirement
13606 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
13607 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
13608 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
13609
13610 public:
13616 using iterator_category = std::bidirectional_iterator_tag;
13617
13619 using value_type = typename BasicJsonType::value_type;
13621 using difference_type = typename BasicJsonType::difference_type;
13623 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
13624 typename BasicJsonType::const_pointer,
13625 typename BasicJsonType::pointer>::type;
13628 typename std::conditional<std::is_const<BasicJsonType>::value,
13629 typename BasicJsonType::const_reference,
13630 typename BasicJsonType::reference>::type;
13631
13632 iter_impl() = default;
13633 ~iter_impl() = default;
13634 iter_impl(iter_impl&&) noexcept = default;
13635 iter_impl& operator=(iter_impl&&) noexcept = default;
13636
13643 explicit iter_impl(pointer object) noexcept : m_object(object)
13644 {
13645 JSON_ASSERT(m_object != nullptr);
13646
13647 switch (m_object->m_data.m_type)
13648 {
13649 case value_t::object:
13650 {
13651 m_it.object_iterator = typename object_t::iterator();
13652 break;
13653 }
13654
13655 case value_t::array:
13656 {
13657 m_it.array_iterator = typename array_t::iterator();
13658 break;
13659 }
13660
13661 case value_t::null:
13662 case value_t::string:
13663 case value_t::boolean:
13667 case value_t::binary:
13668 case value_t::discarded:
13669 default:
13670 {
13671 m_it.primitive_iterator = primitive_iterator_t();
13672 break;
13673 }
13674 }
13675 }
13676
13685
13694 : m_object(other.m_object), m_it(other.m_it)
13695 {}
13696
13704 {
13705 if (&other != this)
13706 {
13707 m_object = other.m_object;
13708 m_it = other.m_it;
13709 }
13710 return *this;
13711 }
13712
13718 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13719 : m_object(other.m_object), m_it(other.m_it)
13720 {}
13721
13728 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13729 {
13730 m_object = other.m_object;
13731 m_it = other.m_it;
13732 return *this;
13733 }
13734
13740 void set_begin() noexcept
13741 {
13742 JSON_ASSERT(m_object != nullptr);
13743
13744 switch (m_object->m_data.m_type)
13745 {
13746 case value_t::object:
13747 {
13748 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13749 break;
13750 }
13751
13752 case value_t::array:
13753 {
13754 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13755 break;
13756 }
13757
13758 case value_t::null:
13759 {
13760 // set to end so begin()==end() is true: null is empty
13761 m_it.primitive_iterator.set_end();
13762 break;
13763 }
13764
13765 case value_t::string:
13766 case value_t::boolean:
13770 case value_t::binary:
13771 case value_t::discarded:
13772 default:
13773 {
13774 m_it.primitive_iterator.set_begin();
13775 break;
13776 }
13777 }
13778 }
13779
13784 void set_end() noexcept
13785 {
13786 JSON_ASSERT(m_object != nullptr);
13787
13788 switch (m_object->m_data.m_type)
13789 {
13790 case value_t::object:
13791 {
13792 m_it.object_iterator = m_object->m_data.m_value.object->end();
13793 break;
13794 }
13795
13796 case value_t::array:
13797 {
13798 m_it.array_iterator = m_object->m_data.m_value.array->end();
13799 break;
13800 }
13801
13802 case value_t::null:
13803 case value_t::string:
13804 case value_t::boolean:
13808 case value_t::binary:
13809 case value_t::discarded:
13810 default:
13811 {
13812 m_it.primitive_iterator.set_end();
13813 break;
13814 }
13815 }
13816 }
13817
13818 public:
13824 {
13825 JSON_ASSERT(m_object != nullptr);
13826
13827 switch (m_object->m_data.m_type)
13828 {
13829 case value_t::object:
13830 {
13831 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13832 return m_it.object_iterator->second;
13833 }
13834
13835 case value_t::array:
13836 {
13837 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13838 return *m_it.array_iterator;
13839 }
13840
13841 case value_t::null:
13842 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13843
13844 case value_t::string:
13845 case value_t::boolean:
13849 case value_t::binary:
13850 case value_t::discarded:
13851 default:
13852 {
13853 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13854 {
13855 return *m_object;
13856 }
13857
13858 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13859 }
13860 }
13861 }
13862
13868 {
13869 JSON_ASSERT(m_object != nullptr);
13870
13871 switch (m_object->m_data.m_type)
13872 {
13873 case value_t::object:
13874 {
13875 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13876 return &(m_it.object_iterator->second);
13877 }
13878
13879 case value_t::array:
13880 {
13881 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13882 return &*m_it.array_iterator;
13883 }
13884
13885 case value_t::null:
13886 case value_t::string:
13887 case value_t::boolean:
13891 case value_t::binary:
13892 case value_t::discarded:
13893 default:
13894 {
13895 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13896 {
13897 return m_object;
13898 }
13899
13900 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13901 }
13902 }
13903 }
13904
13909 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13910 {
13911 auto result = *this;
13912 ++(*this);
13913 return result;
13914 }
13915
13921 {
13922 JSON_ASSERT(m_object != nullptr);
13923
13924 switch (m_object->m_data.m_type)
13925 {
13926 case value_t::object:
13927 {
13928 std::advance(m_it.object_iterator, 1);
13929 break;
13930 }
13931
13932 case value_t::array:
13933 {
13934 std::advance(m_it.array_iterator, 1);
13935 break;
13936 }
13937
13938 case value_t::null:
13939 case value_t::string:
13940 case value_t::boolean:
13944 case value_t::binary:
13945 case value_t::discarded:
13946 default:
13947 {
13948 ++m_it.primitive_iterator;
13949 break;
13950 }
13951 }
13952
13953 return *this;
13954 }
13955
13960 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13961 {
13962 auto result = *this;
13963 --(*this);
13964 return result;
13965 }
13966
13972 {
13973 JSON_ASSERT(m_object != nullptr);
13974
13975 switch (m_object->m_data.m_type)
13976 {
13977 case value_t::object:
13978 {
13979 std::advance(m_it.object_iterator, -1);
13980 break;
13981 }
13982
13983 case value_t::array:
13984 {
13985 std::advance(m_it.array_iterator, -1);
13986 break;
13987 }
13988
13989 case value_t::null:
13990 case value_t::string:
13991 case value_t::boolean:
13995 case value_t::binary:
13996 case value_t::discarded:
13997 default:
13998 {
13999 --m_it.primitive_iterator;
14000 break;
14001 }
14002 }
14003
14004 return *this;
14005 }
14006
14011 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 >
14012 bool operator==(const IterImpl& other) const
14013 {
14014 // if objects are not the same, the comparison is undefined
14015 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14016 {
14017 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14018 }
14019
14020 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14021 if (m_object == nullptr)
14022 {
14023 return true;
14024 }
14025
14026 switch (m_object->m_data.m_type)
14027 {
14028 case value_t::object:
14029 return (m_it.object_iterator == other.m_it.object_iterator);
14030
14031 case value_t::array:
14032 return (m_it.array_iterator == other.m_it.array_iterator);
14033
14034 case value_t::null:
14035 case value_t::string:
14036 case value_t::boolean:
14040 case value_t::binary:
14041 case value_t::discarded:
14042 default:
14043 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
14044 }
14045 }
14046
14051 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 >
14052 bool operator!=(const IterImpl& other) const
14053 {
14054 return !operator==(other);
14055 }
14056
14061 bool operator<(const iter_impl& other) const
14062 {
14063 // if objects are not the same, the comparison is undefined
14064 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14065 {
14066 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14067 }
14068
14069 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14070 if (m_object == nullptr)
14071 {
14072 // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false
14073 return false;
14074 }
14075
14076 switch (m_object->m_data.m_type)
14077 {
14078 case value_t::object:
14079 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
14080
14081 case value_t::array:
14082 return (m_it.array_iterator < other.m_it.array_iterator);
14083
14084 case value_t::null:
14085 case value_t::string:
14086 case value_t::boolean:
14090 case value_t::binary:
14091 case value_t::discarded:
14092 default:
14093 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
14094 }
14095 }
14096
14101 bool operator<=(const iter_impl& other) const
14102 {
14103 return !other.operator < (*this);
14104 }
14105
14110 bool operator>(const iter_impl& other) const
14111 {
14112 return !operator<=(other);
14113 }
14114
14119 bool operator>=(const iter_impl& other) const
14120 {
14121 return !operator<(other);
14122 }
14123
14129 {
14130 JSON_ASSERT(m_object != nullptr);
14131
14132 switch (m_object->m_data.m_type)
14133 {
14134 case value_t::object:
14135 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14136
14137 case value_t::array:
14138 {
14139 std::advance(m_it.array_iterator, i);
14140 break;
14141 }
14142
14143 case value_t::null:
14144 case value_t::string:
14145 case value_t::boolean:
14149 case value_t::binary:
14150 case value_t::discarded:
14151 default:
14152 {
14153 m_it.primitive_iterator += i;
14154 break;
14155 }
14156 }
14157
14158 return *this;
14159 }
14160
14166 {
14167 return operator+=(-i);
14168 }
14169
14175 {
14176 auto result = *this;
14177 result += i;
14178 return result;
14179 }
14180
14186 {
14187 auto result = it;
14188 result += i;
14189 return result;
14190 }
14191
14197 {
14198 auto result = *this;
14199 result -= i;
14200 return result;
14201 }
14202
14208 {
14209 JSON_ASSERT(m_object != nullptr);
14210
14211 switch (m_object->m_data.m_type)
14212 {
14213 case value_t::object:
14214 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14215
14216 case value_t::array:
14217 return m_it.array_iterator - other.m_it.array_iterator;
14218
14219 case value_t::null:
14220 case value_t::string:
14221 case value_t::boolean:
14225 case value_t::binary:
14226 case value_t::discarded:
14227 default:
14228 return m_it.primitive_iterator - other.m_it.primitive_iterator;
14229 }
14230 }
14231
14237 {
14238 JSON_ASSERT(m_object != nullptr);
14239
14240 switch (m_object->m_data.m_type)
14241 {
14242 case value_t::object:
14243 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
14244
14245 case value_t::array:
14246 return *std::next(m_it.array_iterator, n);
14247
14248 case value_t::null:
14249 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14250
14251 case value_t::string:
14252 case value_t::boolean:
14256 case value_t::binary:
14257 case value_t::discarded:
14258 default:
14259 {
14260 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
14261 {
14262 return *m_object;
14263 }
14264
14265 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14266 }
14267 }
14268 }
14269
14274 const typename object_t::key_type& key() const
14275 {
14276 JSON_ASSERT(m_object != nullptr);
14277
14278 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
14279 {
14280 return m_it.object_iterator->first;
14281 }
14282
14283 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
14284 }
14285
14291 {
14292 return operator*();
14293 }
14294
14297 pointer m_object = nullptr;
14300};
14301
14302} // namespace detail
14304
14305// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
14306
14307// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
14308// __ _____ _____ _____
14309// __| | __| | | | JSON for Modern C++
14310// | | |__ | | | | | | version 3.11.3
14311// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14312//
14313// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14314// SPDX-License-Identifier: MIT
14315
14316
14317
14318#include <cstddef> // ptrdiff_t
14319#include <iterator> // reverse_iterator
14320#include <utility> // declval
14321
14322// #include <nlohmann/detail/abi_macros.hpp>
14323
14324
14326namespace detail
14327{
14328
14330// reverse_iterator //
14332
14351template<typename Base>
14352class json_reverse_iterator : public std::reverse_iterator<Base>
14353{
14354 public:
14355 using difference_type = std::ptrdiff_t;
14357 using base_iterator = std::reverse_iterator<Base>;
14359 using reference = typename Base::reference;
14360
14362 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
14363 : base_iterator(it) {}
14364
14366 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
14367
14369 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
14370 {
14371 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
14372 }
14373
14376 {
14377 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
14378 }
14379
14381 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
14382 {
14383 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
14384 }
14385
14388 {
14389 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
14390 }
14391
14394 {
14395 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
14396 }
14397
14400 {
14401 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
14402 }
14403
14406 {
14407 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
14408 }
14409
14412 {
14413 return base_iterator(*this) - base_iterator(other);
14414 }
14415
14418 {
14419 return *(this->operator+(n));
14420 }
14421
14423 auto key() const -> decltype(std::declval<Base>().key())
14424 {
14425 auto it = --this->base();
14426 return it.key();
14427 }
14428
14431 {
14432 auto it = --this->base();
14433 return it.operator * ();
14434 }
14435};
14436
14437} // namespace detail
14439
14440// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
14441
14442// #include <nlohmann/detail/json_custom_base_class.hpp>
14443// __ _____ _____ _____
14444// __| | __| | | | JSON for Modern C++
14445// | | |__ | | | | | | version 3.11.3
14446// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14447//
14448// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14449// SPDX-License-Identifier: MIT
14450
14451
14452
14453#include <type_traits> // conditional, is_same
14454
14455// #include <nlohmann/detail/abi_macros.hpp>
14456
14457
14459namespace detail
14460{
14461
14473
14474template<class T>
14475using json_base_class = typename std::conditional <
14476 std::is_same<T, void>::value,
14478 T
14479 >::type;
14480
14481} // namespace detail
14483
14484// #include <nlohmann/detail/json_pointer.hpp>
14485// __ _____ _____ _____
14486// __| | __| | | | JSON for Modern C++
14487// | | |__ | | | | | | version 3.11.3
14488// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14489//
14490// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14491// SPDX-License-Identifier: MIT
14492
14493
14494
14495#include <algorithm> // all_of
14496#include <cctype> // isdigit
14497#include <cerrno> // errno, ERANGE
14498#include <cstdlib> // strtoull
14499#ifndef JSON_NO_IO
14500 #include <iosfwd> // ostream
14501#endif // JSON_NO_IO
14502#include <limits> // max
14503#include <numeric> // accumulate
14504#include <string> // string
14505#include <utility> // move
14506#include <vector> // vector
14507
14508// #include <nlohmann/detail/exceptions.hpp>
14509
14510// #include <nlohmann/detail/macro_scope.hpp>
14511
14512// #include <nlohmann/detail/string_concat.hpp>
14513
14514// #include <nlohmann/detail/string_escape.hpp>
14515
14516// #include <nlohmann/detail/value_t.hpp>
14517
14518
14520
14523template<typename RefStringType>
14525{
14526 // allow basic_json to access private members
14528 friend class basic_json;
14529
14530 template<typename>
14531 friend class json_pointer;
14532
14533 template<typename T>
14535 {
14536 using type = T;
14537 };
14538
14541 {
14542 using type = StringType;
14543 };
14544
14545 public:
14546 // for backwards compatibility accept BasicJsonType
14548
14551 explicit json_pointer(const string_t& s = "")
14553 {}
14554
14558 {
14559 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
14560 string_t{},
14561 [](const string_t& a, const string_t& b)
14562 {
14563 return detail::concat(a, '/', detail::escape(b));
14564 });
14565 }
14566
14570 operator string_t() const
14571 {
14572 return to_string();
14573 }
14574
14575#ifndef JSON_NO_IO
14578 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
14579 {
14580 o << ptr.to_string();
14581 return o;
14582 }
14583#endif
14584
14588 {
14590 ptr.reference_tokens.begin(),
14591 ptr.reference_tokens.end());
14592 return *this;
14593 }
14594
14598 {
14599 push_back(std::move(token));
14600 return *this;
14601 }
14602
14605 json_pointer& operator/=(std::size_t array_idx)
14606 {
14607 return *this /= std::to_string(array_idx);
14608 }
14609
14613 const json_pointer& rhs)
14614 {
14615 return json_pointer(lhs) /= rhs;
14616 }
14617
14620 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
14621 {
14622 return json_pointer(lhs) /= std::move(token);
14623 }
14624
14627 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
14628 {
14629 return json_pointer(lhs) /= array_idx;
14630 }
14631
14635 {
14636 if (empty())
14637 {
14638 return *this;
14639 }
14640
14641 json_pointer res = *this;
14642 res.pop_back();
14643 return res;
14644 }
14645
14649 {
14651 {
14652 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14653 }
14654
14655 reference_tokens.pop_back();
14656 }
14657
14660 const string_t& back() const
14661 {
14663 {
14664 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14665 }
14666
14667 return reference_tokens.back();
14668 }
14669
14672 void push_back(const string_t& token)
14673 {
14674 reference_tokens.push_back(token);
14675 }
14676
14679 void push_back(string_t&& token)
14680 {
14681 reference_tokens.push_back(std::move(token));
14682 }
14683
14686 bool empty() const noexcept
14687 {
14688 return reference_tokens.empty();
14689 }
14690
14691 private:
14702 template<typename BasicJsonType>
14703 static typename BasicJsonType::size_type array_index(const string_t& s)
14704 {
14705 using size_type = typename BasicJsonType::size_type;
14706
14707 // error condition (cf. RFC 6901, Sect. 4)
14708 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14709 {
14710 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14711 }
14712
14713 // error condition (cf. RFC 6901, Sect. 4)
14714 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14715 {
14716 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14717 }
14718
14719 const char* p = s.c_str();
14720 char* p_end = nullptr;
14721 errno = 0; // strtoull doesn't reset errno
14722 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14723 if (p == p_end // invalid input or empty string
14724 || errno == ERANGE // out of range
14725 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14726 {
14727 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14728 }
14729
14730 // only triggered on special platforms (like 32bit), see also
14731 // https://github.com/nlohmann/json/pull/2203
14732 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14733 {
14734 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14735 }
14736
14737 return static_cast<size_type>(res);
14738 }
14739
14741 json_pointer top() const
14742 {
14744 {
14745 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14746 }
14747
14749 result.reference_tokens = {reference_tokens[0]};
14750 return result;
14751 }
14752
14753 private:
14762 template<typename BasicJsonType>
14763 BasicJsonType& get_and_create(BasicJsonType& j) const
14764 {
14765 auto* result = &j;
14766
14767 // in case no reference tokens exist, return a reference to the JSON value
14768 // j which will be overwritten by a primitive value
14769 for (const auto& reference_token : reference_tokens)
14770 {
14771 switch (result->type())
14772 {
14774 {
14775 if (reference_token == "0")
14776 {
14777 // start a new array if reference token is 0
14778 result = &result->operator[](0);
14779 }
14780 else
14781 {
14782 // start a new object otherwise
14783 result = &result->operator[](reference_token);
14784 }
14785 break;
14786 }
14787
14789 {
14790 // create an entry in the object
14791 result = &result->operator[](reference_token);
14792 break;
14793 }
14794
14796 {
14797 // create an entry in the array
14798 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14799 break;
14800 }
14801
14802 /*
14803 The following code is only reached if there exists a reference
14804 token _and_ the current value is primitive. In this case, we have
14805 an error situation, because primitive values may only occur as
14806 single value; that is, with an empty list of reference tokens.
14807 */
14815 default:
14816 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14817 }
14818 }
14819
14820 return *result;
14821 }
14822
14842 template<typename BasicJsonType>
14843 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14844 {
14845 for (const auto& reference_token : reference_tokens)
14846 {
14847 // convert null values to arrays or objects before continuing
14848 if (ptr->is_null())
14849 {
14850 // check if reference token is a number
14851 const bool nums =
14852 std::all_of(reference_token.begin(), reference_token.end(),
14853 [](const unsigned char x)
14854 {
14855 return std::isdigit(x);
14856 });
14857
14858 // change value to array for numbers or "-" or to object otherwise
14859 *ptr = (nums || reference_token == "-")
14862 }
14863
14864 switch (ptr->type())
14865 {
14867 {
14868 // use unchecked object access
14869 ptr = &ptr->operator[](reference_token);
14870 break;
14871 }
14872
14874 {
14875 if (reference_token == "-")
14876 {
14877 // explicitly treat "-" as index beyond the end
14878 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14879 }
14880 else
14881 {
14882 // convert array index to number; unchecked access
14883 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14884 }
14885 break;
14886 }
14887
14896 default:
14897 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14898 }
14899 }
14900
14901 return *ptr;
14902 }
14903
14910 template<typename BasicJsonType>
14911 BasicJsonType& get_checked(BasicJsonType* ptr) const
14912 {
14913 for (const auto& reference_token : reference_tokens)
14914 {
14915 switch (ptr->type())
14916 {
14918 {
14919 // note: at performs range check
14920 ptr = &ptr->at(reference_token);
14921 break;
14922 }
14923
14925 {
14926 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14927 {
14928 // "-" always fails the range check
14930 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14931 ") is out of range"), ptr));
14932 }
14933
14934 // note: at performs range check
14935 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14936 break;
14937 }
14938
14947 default:
14948 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14949 }
14950 }
14951
14952 return *ptr;
14953 }
14954
14968 template<typename BasicJsonType>
14969 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
14970 {
14971 for (const auto& reference_token : reference_tokens)
14972 {
14973 switch (ptr->type())
14974 {
14976 {
14977 // use unchecked object access
14978 ptr = &ptr->operator[](reference_token);
14979 break;
14980 }
14981
14983 {
14984 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14985 {
14986 // "-" cannot be used for const access
14987 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));
14988 }
14989
14990 // use unchecked array access
14991 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14992 break;
14993 }
14994
15003 default:
15004 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15005 }
15006 }
15007
15008 return *ptr;
15009 }
15010
15017 template<typename BasicJsonType>
15018 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
15019 {
15020 for (const auto& reference_token : reference_tokens)
15021 {
15022 switch (ptr->type())
15023 {
15025 {
15026 // note: at performs range check
15027 ptr = &ptr->at(reference_token);
15028 break;
15029 }
15030
15032 {
15033 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15034 {
15035 // "-" always fails the range check
15037 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15038 ") is out of range"), ptr));
15039 }
15040
15041 // note: at performs range check
15042 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15043 break;
15044 }
15045
15054 default:
15055 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15056 }
15057 }
15058
15059 return *ptr;
15060 }
15061
15066 template<typename BasicJsonType>
15067 bool contains(const BasicJsonType* ptr) const
15068 {
15069 for (const auto& reference_token : reference_tokens)
15070 {
15071 switch (ptr->type())
15072 {
15074 {
15075 if (!ptr->contains(reference_token))
15076 {
15077 // we did not find the key in the object
15078 return false;
15079 }
15080
15081 ptr = &ptr->operator[](reference_token);
15082 break;
15083 }
15084
15086 {
15087 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15088 {
15089 // "-" always fails the range check
15090 return false;
15091 }
15092 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
15093 {
15094 // invalid char
15095 return false;
15096 }
15097 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
15098 {
15099 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
15100 {
15101 // first char should be between '1' and '9'
15102 return false;
15103 }
15104 for (std::size_t i = 1; i < reference_token.size(); i++)
15105 {
15106 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
15107 {
15108 // other char should be between '0' and '9'
15109 return false;
15110 }
15111 }
15112 }
15113
15114 const auto idx = array_index<BasicJsonType>(reference_token);
15115 if (idx >= ptr->size())
15116 {
15117 // index out of range
15118 return false;
15119 }
15120
15121 ptr = &ptr->operator[](idx);
15122 break;
15123 }
15124
15133 default:
15134 {
15135 // we do not expect primitive values if there is still a
15136 // reference token to process
15137 return false;
15138 }
15139 }
15140 }
15141
15142 // no reference token left means we found a primitive value
15143 return true;
15144 }
15145
15155 static std::vector<string_t> split(const string_t& reference_string)
15156 {
15157 std::vector<string_t> result;
15158
15159 // special case: empty reference string -> no reference tokens
15160 if (reference_string.empty())
15161 {
15162 return result;
15163 }
15164
15165 // check if nonempty reference string begins with slash
15166 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
15167 {
15168 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
15169 }
15170
15171 // extract the reference tokens:
15172 // - slash: position of the last read slash (or end of string)
15173 // - start: position after the previous slash
15174 for (
15175 // search for the first slash after the first character
15176 std::size_t slash = reference_string.find_first_of('/', 1),
15177 // set the beginning of the first reference token
15178 start = 1;
15179 // we can stop if start == 0 (if slash == string_t::npos)
15180 start != 0;
15181 // set the beginning of the next reference token
15182 // (will eventually be 0 if slash == string_t::npos)
15183 start = (slash == string_t::npos) ? 0 : slash + 1,
15184 // find next slash
15185 slash = reference_string.find_first_of('/', start))
15186 {
15187 // use the text between the beginning of the reference token
15188 // (start) and the last slash (slash).
15189 auto reference_token = reference_string.substr(start, slash - start);
15190
15191 // check reference tokens are properly escaped
15192 for (std::size_t pos = reference_token.find_first_of('~');
15193 pos != string_t::npos;
15194 pos = reference_token.find_first_of('~', pos + 1))
15195 {
15196 JSON_ASSERT(reference_token[pos] == '~');
15197
15198 // ~ must be followed by 0 or 1
15199 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
15200 (reference_token[pos + 1] != '0' &&
15201 reference_token[pos + 1] != '1')))
15202 {
15203 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
15204 }
15205 }
15206
15207 // finally, store the reference token
15208 detail::unescape(reference_token);
15209 result.push_back(reference_token);
15210 }
15211
15212 return result;
15213 }
15214
15215 private:
15223 template<typename BasicJsonType>
15224 static void flatten(const string_t& reference_string,
15225 const BasicJsonType& value,
15226 BasicJsonType& result)
15227 {
15228 switch (value.type())
15229 {
15231 {
15232 if (value.m_data.m_value.array->empty())
15233 {
15234 // flatten empty array as null
15235 result[reference_string] = nullptr;
15236 }
15237 else
15238 {
15239 // iterate array and use index as reference string
15240 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
15241 {
15242 flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
15243 value.m_data.m_value.array->operator[](i), result);
15244 }
15245 }
15246 break;
15247 }
15248
15250 {
15251 if (value.m_data.m_value.object->empty())
15252 {
15253 // flatten empty object as null
15254 result[reference_string] = nullptr;
15255 }
15256 else
15257 {
15258 // iterate object and use keys as reference string
15259 for (const auto& element : *value.m_data.m_value.object)
15260 {
15261 flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
15262 }
15263 }
15264 break;
15265 }
15266
15275 default:
15276 {
15277 // add primitive value with its reference string
15278 result[reference_string] = value;
15279 break;
15280 }
15281 }
15282 }
15283
15294 template<typename BasicJsonType>
15295 static BasicJsonType
15296 unflatten(const BasicJsonType& value)
15297 {
15298 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
15299 {
15300 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
15301 }
15302
15303 BasicJsonType result;
15304
15305 // iterate the JSON object values
15306 for (const auto& element : *value.m_data.m_value.object)
15307 {
15308 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
15309 {
15310 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
15311 }
15312
15313 // assign value to reference pointed to by JSON pointer; Note that if
15314 // the JSON pointer is "" (i.e., points to the whole value), function
15315 // get_and_create returns a reference to result itself. An assignment
15316 // will then create a primitive value.
15317 json_pointer(element.first).get_and_create(result) = element.second;
15318 }
15319
15320 return result;
15321 }
15322
15323 // can't use conversion operator because of ambiguity
15325 {
15327 result.reference_tokens = reference_tokens;
15328 return result;
15329 }
15330
15332 {
15334 result.reference_tokens = std::move(reference_tokens);
15335 return result;
15336 }
15337
15338 public:
15339#if JSON_HAS_THREE_WAY_COMPARISON
15342 template<typename RefStringTypeRhs>
15343 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
15344 {
15345 return reference_tokens == rhs.reference_tokens;
15346 }
15347
15350 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
15351 bool operator==(const string_t& rhs) const
15352 {
15353 return *this == json_pointer(rhs);
15354 }
15355
15357 template<typename RefStringTypeRhs>
15358 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
15359 {
15360 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
15361 }
15362#else
15365 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15366 // NOLINTNEXTLINE(readability-redundant-declaration)
15367 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15368 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15369
15372 template<typename RefStringTypeLhs, typename StringType>
15373 // NOLINTNEXTLINE(readability-redundant-declaration)
15374 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15375 const StringType& rhs);
15376
15379 template<typename RefStringTypeRhs, typename StringType>
15380 // NOLINTNEXTLINE(readability-redundant-declaration)
15381 friend bool operator==(const StringType& lhs,
15382 const json_pointer<RefStringTypeRhs>& rhs);
15383
15386 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15387 // NOLINTNEXTLINE(readability-redundant-declaration)
15388 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15389 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15390
15393 template<typename RefStringTypeLhs, typename StringType>
15394 // NOLINTNEXTLINE(readability-redundant-declaration)
15395 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15396 const StringType& rhs);
15397
15400 template<typename RefStringTypeRhs, typename StringType>
15401 // NOLINTNEXTLINE(readability-redundant-declaration)
15402 friend bool operator!=(const StringType& lhs,
15403 const json_pointer<RefStringTypeRhs>& rhs);
15404
15406 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15407 // NOLINTNEXTLINE(readability-redundant-declaration)
15408 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
15409 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15410#endif
15411
15412 private:
15414 std::vector<string_t> reference_tokens;
15415};
15416
15417#if !JSON_HAS_THREE_WAY_COMPARISON
15418// functions cannot be defined inside class due to ODR violations
15419template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15421 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15422{
15423 return lhs.reference_tokens == rhs.reference_tokens;
15424}
15425
15426template<typename RefStringTypeLhs,
15427 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15429inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15430 const StringType& rhs)
15431{
15432 return lhs == json_pointer<RefStringTypeLhs>(rhs);
15433}
15434
15435template<typename RefStringTypeRhs,
15436 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15438inline bool operator==(const StringType& lhs,
15439 const json_pointer<RefStringTypeRhs>& rhs)
15440{
15441 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
15442}
15443
15444template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15446 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15447{
15448 return !(lhs == rhs);
15449}
15450
15451template<typename RefStringTypeLhs,
15452 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15454inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15455 const StringType& rhs)
15456{
15457 return !(lhs == rhs);
15458}
15459
15460template<typename RefStringTypeRhs,
15461 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15463inline bool operator!=(const StringType& lhs,
15464 const json_pointer<RefStringTypeRhs>& rhs)
15465{
15466 return !(lhs == rhs);
15467}
15468
15469template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15471 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15472{
15473 return lhs.reference_tokens < rhs.reference_tokens;
15474}
15475#endif
15476
15478
15479// #include <nlohmann/detail/json_ref.hpp>
15480// __ _____ _____ _____
15481// __| | __| | | | JSON for Modern C++
15482// | | |__ | | | | | | version 3.11.3
15483// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15484//
15485// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15486// SPDX-License-Identifier: MIT
15487
15488
15489
15490#include <initializer_list>
15491#include <utility>
15492
15493// #include <nlohmann/detail/abi_macros.hpp>
15494
15495// #include <nlohmann/detail/meta/type_traits.hpp>
15496
15497
15499namespace detail
15500{
15501
15502template<typename BasicJsonType>
15504{
15505 public:
15506 using value_type = BasicJsonType;
15507
15509 : owned_value(std::move(value))
15510 {}
15511
15513 : value_ref(&value)
15514 {}
15515
15516 json_ref(std::initializer_list<json_ref> init)
15517 : owned_value(init)
15518 {}
15519
15520 template <
15521 class... Args,
15522 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
15523 json_ref(Args && ... args)
15524 : owned_value(std::forward<Args>(args)...)
15525 {}
15526
15527 // class should be movable only
15528 json_ref(json_ref&&) noexcept = default;
15529 json_ref(const json_ref&) = delete;
15530 json_ref& operator=(const json_ref&) = delete;
15531 json_ref& operator=(json_ref&&) = delete;
15532 ~json_ref() = default;
15533
15535 {
15536 if (value_ref == nullptr)
15537 {
15538 return std::move(owned_value);
15539 }
15540 return *value_ref;
15541 }
15542
15543 value_type const& operator*() const
15544 {
15545 return value_ref ? *value_ref : owned_value;
15546 }
15547
15548 value_type const* operator->() const
15549 {
15550 return &** this;
15551 }
15552
15553 private:
15554 mutable value_type owned_value = nullptr;
15555 value_type const* value_ref = nullptr;
15556};
15557
15558} // namespace detail
15560
15561// #include <nlohmann/detail/macro_scope.hpp>
15562
15563// #include <nlohmann/detail/string_concat.hpp>
15564
15565// #include <nlohmann/detail/string_escape.hpp>
15566
15567// #include <nlohmann/detail/string_utils.hpp>
15568
15569// #include <nlohmann/detail/meta/cpp_future.hpp>
15570
15571// #include <nlohmann/detail/meta/type_traits.hpp>
15572
15573// #include <nlohmann/detail/output/binary_writer.hpp>
15574// __ _____ _____ _____
15575// __| | __| | | | JSON for Modern C++
15576// | | |__ | | | | | | version 3.11.3
15577// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15578//
15579// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15580// SPDX-License-Identifier: MIT
15581
15582
15583
15584#include <algorithm> // reverse
15585#include <array> // array
15586#include <map> // map
15587#include <cmath> // isnan, isinf
15588#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
15589#include <cstring> // memcpy
15590#include <limits> // numeric_limits
15591#include <string> // string
15592#include <utility> // move
15593#include <vector> // vector
15594
15595// #include <nlohmann/detail/input/binary_reader.hpp>
15596
15597// #include <nlohmann/detail/macro_scope.hpp>
15598
15599// #include <nlohmann/detail/output/output_adapters.hpp>
15600// __ _____ _____ _____
15601// __| | __| | | | JSON for Modern C++
15602// | | |__ | | | | | | version 3.11.3
15603// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15604//
15605// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15606// SPDX-License-Identifier: MIT
15607
15608
15609
15610#include <algorithm> // copy
15611#include <cstddef> // size_t
15612#include <iterator> // back_inserter
15613#include <memory> // shared_ptr, make_shared
15614#include <string> // basic_string
15615#include <vector> // vector
15616
15617#ifndef JSON_NO_IO
15618 #include <ios> // streamsize
15619 #include <ostream> // basic_ostream
15620#endif // JSON_NO_IO
15621
15622// #include <nlohmann/detail/macro_scope.hpp>
15623
15624
15626namespace detail
15627{
15628
15630template<typename CharType> struct output_adapter_protocol
15631{
15632 virtual void write_character(CharType c) = 0;
15633 virtual void write_characters(const CharType* s, std::size_t length) = 0;
15634 virtual ~output_adapter_protocol() = default;
15635
15640 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
15641};
15642
15644template<typename CharType>
15645using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
15646
15648template<typename CharType, typename AllocatorType = std::allocator<CharType>>
15650{
15651 public:
15652 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
15653 : v(vec)
15654 {}
15655
15656 void write_character(CharType c) override
15657 {
15658 v.push_back(c);
15659 }
15660
15662 void write_characters(const CharType* s, std::size_t length) override
15663 {
15664 v.insert(v.end(), s, s + length);
15665 }
15666
15667 private:
15668 std::vector<CharType, AllocatorType>& v;
15669};
15670
15671#ifndef JSON_NO_IO
15673template<typename CharType>
15675{
15676 public:
15677 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15678 : stream(s)
15679 {}
15680
15681 void write_character(CharType c) override
15682 {
15683 stream.put(c);
15684 }
15685
15687 void write_characters(const CharType* s, std::size_t length) override
15688 {
15689 stream.write(s, static_cast<std::streamsize>(length));
15690 }
15691
15692 private:
15693 std::basic_ostream<CharType>& stream;
15694};
15695#endif // JSON_NO_IO
15696
15698template<typename CharType, typename StringType = std::basic_string<CharType>>
15700{
15701 public:
15702 explicit output_string_adapter(StringType& s) noexcept
15703 : str(s)
15704 {}
15705
15706 void write_character(CharType c) override
15707 {
15708 str.push_back(c);
15709 }
15710
15712 void write_characters(const CharType* s, std::size_t length) override
15713 {
15714 str.append(s, length);
15715 }
15716
15717 private:
15718 StringType& str;
15719};
15720
15721template<typename CharType, typename StringType = std::basic_string<CharType>>
15723{
15724 public:
15725 template<typename AllocatorType = std::allocator<CharType>>
15726 output_adapter(std::vector<CharType, AllocatorType>& vec)
15727 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15728
15729#ifndef JSON_NO_IO
15730 output_adapter(std::basic_ostream<CharType>& s)
15731 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15732#endif // JSON_NO_IO
15733
15734 output_adapter(StringType& s)
15735 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15736
15738 {
15739 return oa;
15740 }
15741
15742 private:
15744};
15745
15746} // namespace detail
15748
15749// #include <nlohmann/detail/string_concat.hpp>
15750
15751
15753namespace detail
15754{
15755
15758{
15761};
15762
15764// binary writer //
15766
15770template<typename BasicJsonType, typename CharType>
15772{
15773 using string_t = typename BasicJsonType::string_t;
15774 using binary_t = typename BasicJsonType::binary_t;
15775 using number_float_t = typename BasicJsonType::number_float_t;
15776
15777 public:
15783 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15784 {
15785 JSON_ASSERT(oa);
15786 }
15787
15792 void write_bson(const BasicJsonType& j)
15793 {
15794 switch (j.type())
15795 {
15796 case value_t::object:
15797 {
15798 write_bson_object(*j.m_data.m_value.object);
15799 break;
15800 }
15801
15802 case value_t::null:
15803 case value_t::array:
15804 case value_t::string:
15805 case value_t::boolean:
15809 case value_t::binary:
15810 case value_t::discarded:
15811 default:
15812 {
15813 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15814 }
15815 }
15816 }
15817
15821 void write_cbor(const BasicJsonType& j)
15822 {
15823 switch (j.type())
15824 {
15825 case value_t::null:
15826 {
15827 oa->write_character(to_char_type(0xF6));
15828 break;
15829 }
15830
15831 case value_t::boolean:
15832 {
15833 oa->write_character(j.m_data.m_value.boolean
15834 ? to_char_type(0xF5)
15835 : to_char_type(0xF4));
15836 break;
15837 }
15838
15840 {
15841 if (j.m_data.m_value.number_integer >= 0)
15842 {
15843 // CBOR does not differentiate between positive signed
15844 // integers and unsigned integers. Therefore, we used the
15845 // code from the value_t::number_unsigned case here.
15846 if (j.m_data.m_value.number_integer <= 0x17)
15847 {
15848 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15849 }
15850 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15851 {
15852 oa->write_character(to_char_type(0x18));
15853 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15854 }
15855 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15856 {
15857 oa->write_character(to_char_type(0x19));
15858 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15859 }
15860 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15861 {
15862 oa->write_character(to_char_type(0x1A));
15863 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15864 }
15865 else
15866 {
15867 oa->write_character(to_char_type(0x1B));
15868 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15869 }
15870 }
15871 else
15872 {
15873 // The conversions below encode the sign in the first
15874 // byte, and the value is converted to a positive number.
15875 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15876 if (j.m_data.m_value.number_integer >= -24)
15877 {
15878 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15879 }
15880 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15881 {
15882 oa->write_character(to_char_type(0x38));
15883 write_number(static_cast<std::uint8_t>(positive_number));
15884 }
15885 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15886 {
15887 oa->write_character(to_char_type(0x39));
15888 write_number(static_cast<std::uint16_t>(positive_number));
15889 }
15890 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15891 {
15892 oa->write_character(to_char_type(0x3A));
15893 write_number(static_cast<std::uint32_t>(positive_number));
15894 }
15895 else
15896 {
15897 oa->write_character(to_char_type(0x3B));
15898 write_number(static_cast<std::uint64_t>(positive_number));
15899 }
15900 }
15901 break;
15902 }
15903
15905 {
15906 if (j.m_data.m_value.number_unsigned <= 0x17)
15907 {
15908 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15909 }
15910 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15911 {
15912 oa->write_character(to_char_type(0x18));
15913 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15914 }
15915 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15916 {
15917 oa->write_character(to_char_type(0x19));
15918 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15919 }
15920 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15921 {
15922 oa->write_character(to_char_type(0x1A));
15923 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15924 }
15925 else
15926 {
15927 oa->write_character(to_char_type(0x1B));
15928 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15929 }
15930 break;
15931 }
15932
15934 {
15935 if (std::isnan(j.m_data.m_value.number_float))
15936 {
15937 // NaN is 0xf97e00 in CBOR
15938 oa->write_character(to_char_type(0xF9));
15939 oa->write_character(to_char_type(0x7E));
15940 oa->write_character(to_char_type(0x00));
15941 }
15942 else if (std::isinf(j.m_data.m_value.number_float))
15943 {
15944 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
15945 oa->write_character(to_char_type(0xf9));
15946 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15947 oa->write_character(to_char_type(0x00));
15948 }
15949 else
15950 {
15951 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15952 }
15953 break;
15954 }
15955
15956 case value_t::string:
15957 {
15958 // step 1: write control byte and the string length
15959 const auto N = j.m_data.m_value.string->size();
15960 if (N <= 0x17)
15961 {
15962 write_number(static_cast<std::uint8_t>(0x60 + N));
15963 }
15964 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15965 {
15966 oa->write_character(to_char_type(0x78));
15967 write_number(static_cast<std::uint8_t>(N));
15968 }
15969 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15970 {
15971 oa->write_character(to_char_type(0x79));
15972 write_number(static_cast<std::uint16_t>(N));
15973 }
15974 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15975 {
15976 oa->write_character(to_char_type(0x7A));
15977 write_number(static_cast<std::uint32_t>(N));
15978 }
15979 // LCOV_EXCL_START
15980 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15981 {
15982 oa->write_character(to_char_type(0x7B));
15983 write_number(static_cast<std::uint64_t>(N));
15984 }
15985 // LCOV_EXCL_STOP
15986
15987 // step 2: write the string
15988 oa->write_characters(
15989 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15990 j.m_data.m_value.string->size());
15991 break;
15992 }
15993
15994 case value_t::array:
15995 {
15996 // step 1: write control byte and the array size
15997 const auto N = j.m_data.m_value.array->size();
15998 if (N <= 0x17)
15999 {
16000 write_number(static_cast<std::uint8_t>(0x80 + N));
16001 }
16002 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16003 {
16004 oa->write_character(to_char_type(0x98));
16005 write_number(static_cast<std::uint8_t>(N));
16006 }
16007 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16008 {
16009 oa->write_character(to_char_type(0x99));
16010 write_number(static_cast<std::uint16_t>(N));
16011 }
16012 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16013 {
16014 oa->write_character(to_char_type(0x9A));
16015 write_number(static_cast<std::uint32_t>(N));
16016 }
16017 // LCOV_EXCL_START
16018 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16019 {
16020 oa->write_character(to_char_type(0x9B));
16021 write_number(static_cast<std::uint64_t>(N));
16022 }
16023 // LCOV_EXCL_STOP
16024
16025 // step 2: write each element
16026 for (const auto& el : *j.m_data.m_value.array)
16027 {
16028 write_cbor(el);
16029 }
16030 break;
16031 }
16032
16033 case value_t::binary:
16034 {
16035 if (j.m_data.m_value.binary->has_subtype())
16036 {
16037 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
16038 {
16039 write_number(static_cast<std::uint8_t>(0xd8));
16040 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
16041 }
16042 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
16043 {
16044 write_number(static_cast<std::uint8_t>(0xd9));
16045 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
16046 }
16047 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
16048 {
16049 write_number(static_cast<std::uint8_t>(0xda));
16050 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
16051 }
16052 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
16053 {
16054 write_number(static_cast<std::uint8_t>(0xdb));
16055 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
16056 }
16057 }
16058
16059 // step 1: write control byte and the binary array size
16060 const auto N = j.m_data.m_value.binary->size();
16061 if (N <= 0x17)
16062 {
16063 write_number(static_cast<std::uint8_t>(0x40 + N));
16064 }
16065 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16066 {
16067 oa->write_character(to_char_type(0x58));
16068 write_number(static_cast<std::uint8_t>(N));
16069 }
16070 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16071 {
16072 oa->write_character(to_char_type(0x59));
16073 write_number(static_cast<std::uint16_t>(N));
16074 }
16075 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16076 {
16077 oa->write_character(to_char_type(0x5A));
16078 write_number(static_cast<std::uint32_t>(N));
16079 }
16080 // LCOV_EXCL_START
16081 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16082 {
16083 oa->write_character(to_char_type(0x5B));
16084 write_number(static_cast<std::uint64_t>(N));
16085 }
16086 // LCOV_EXCL_STOP
16087
16088 // step 2: write each element
16089 oa->write_characters(
16090 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16091 N);
16092
16093 break;
16094 }
16095
16096 case value_t::object:
16097 {
16098 // step 1: write control byte and the object size
16099 const auto N = j.m_data.m_value.object->size();
16100 if (N <= 0x17)
16101 {
16102 write_number(static_cast<std::uint8_t>(0xA0 + N));
16103 }
16104 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16105 {
16106 oa->write_character(to_char_type(0xB8));
16107 write_number(static_cast<std::uint8_t>(N));
16108 }
16109 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16110 {
16111 oa->write_character(to_char_type(0xB9));
16112 write_number(static_cast<std::uint16_t>(N));
16113 }
16114 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16115 {
16116 oa->write_character(to_char_type(0xBA));
16117 write_number(static_cast<std::uint32_t>(N));
16118 }
16119 // LCOV_EXCL_START
16120 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16121 {
16122 oa->write_character(to_char_type(0xBB));
16123 write_number(static_cast<std::uint64_t>(N));
16124 }
16125 // LCOV_EXCL_STOP
16126
16127 // step 2: write each element
16128 for (const auto& el : *j.m_data.m_value.object)
16129 {
16130 write_cbor(el.first);
16131 write_cbor(el.second);
16132 }
16133 break;
16134 }
16135
16136 case value_t::discarded:
16137 default:
16138 break;
16139 }
16140 }
16141
16145 void write_msgpack(const BasicJsonType& j)
16146 {
16147 switch (j.type())
16148 {
16149 case value_t::null: // nil
16150 {
16151 oa->write_character(to_char_type(0xC0));
16152 break;
16153 }
16154
16155 case value_t::boolean: // true and false
16156 {
16157 oa->write_character(j.m_data.m_value.boolean
16158 ? to_char_type(0xC3)
16159 : to_char_type(0xC2));
16160 break;
16161 }
16162
16164 {
16165 if (j.m_data.m_value.number_integer >= 0)
16166 {
16167 // MessagePack does not differentiate between positive
16168 // signed integers and unsigned integers. Therefore, we used
16169 // the code from the value_t::number_unsigned case here.
16170 if (j.m_data.m_value.number_unsigned < 128)
16171 {
16172 // positive fixnum
16173 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16174 }
16175 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16176 {
16177 // uint 8
16178 oa->write_character(to_char_type(0xCC));
16179 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16180 }
16181 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16182 {
16183 // uint 16
16184 oa->write_character(to_char_type(0xCD));
16185 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16186 }
16187 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16188 {
16189 // uint 32
16190 oa->write_character(to_char_type(0xCE));
16191 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16192 }
16193 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16194 {
16195 // uint 64
16196 oa->write_character(to_char_type(0xCF));
16197 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16198 }
16199 }
16200 else
16201 {
16202 if (j.m_data.m_value.number_integer >= -32)
16203 {
16204 // negative fixnum
16205 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16206 }
16207 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
16208 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16209 {
16210 // int 8
16211 oa->write_character(to_char_type(0xD0));
16212 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16213 }
16214 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
16215 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16216 {
16217 // int 16
16218 oa->write_character(to_char_type(0xD1));
16219 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
16220 }
16221 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
16222 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16223 {
16224 // int 32
16225 oa->write_character(to_char_type(0xD2));
16226 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
16227 }
16228 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
16229 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16230 {
16231 // int 64
16232 oa->write_character(to_char_type(0xD3));
16233 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
16234 }
16235 }
16236 break;
16237 }
16238
16240 {
16241 if (j.m_data.m_value.number_unsigned < 128)
16242 {
16243 // positive fixnum
16244 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16245 }
16246 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16247 {
16248 // uint 8
16249 oa->write_character(to_char_type(0xCC));
16250 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16251 }
16252 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16253 {
16254 // uint 16
16255 oa->write_character(to_char_type(0xCD));
16256 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16257 }
16258 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16259 {
16260 // uint 32
16261 oa->write_character(to_char_type(0xCE));
16262 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16263 }
16264 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16265 {
16266 // uint 64
16267 oa->write_character(to_char_type(0xCF));
16268 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16269 }
16270 break;
16271 }
16272
16274 {
16275 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
16276 break;
16277 }
16278
16279 case value_t::string:
16280 {
16281 // step 1: write control byte and the string length
16282 const auto N = j.m_data.m_value.string->size();
16283 if (N <= 31)
16284 {
16285 // fixstr
16286 write_number(static_cast<std::uint8_t>(0xA0 | N));
16287 }
16288 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16289 {
16290 // str 8
16291 oa->write_character(to_char_type(0xD9));
16292 write_number(static_cast<std::uint8_t>(N));
16293 }
16294 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16295 {
16296 // str 16
16297 oa->write_character(to_char_type(0xDA));
16298 write_number(static_cast<std::uint16_t>(N));
16299 }
16300 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16301 {
16302 // str 32
16303 oa->write_character(to_char_type(0xDB));
16304 write_number(static_cast<std::uint32_t>(N));
16305 }
16306
16307 // step 2: write the string
16308 oa->write_characters(
16309 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16310 j.m_data.m_value.string->size());
16311 break;
16312 }
16313
16314 case value_t::array:
16315 {
16316 // step 1: write control byte and the array size
16317 const auto N = j.m_data.m_value.array->size();
16318 if (N <= 15)
16319 {
16320 // fixarray
16321 write_number(static_cast<std::uint8_t>(0x90 | N));
16322 }
16323 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16324 {
16325 // array 16
16326 oa->write_character(to_char_type(0xDC));
16327 write_number(static_cast<std::uint16_t>(N));
16328 }
16329 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16330 {
16331 // array 32
16332 oa->write_character(to_char_type(0xDD));
16333 write_number(static_cast<std::uint32_t>(N));
16334 }
16335
16336 // step 2: write each element
16337 for (const auto& el : *j.m_data.m_value.array)
16338 {
16339 write_msgpack(el);
16340 }
16341 break;
16342 }
16343
16344 case value_t::binary:
16345 {
16346 // step 0: determine if the binary type has a set subtype to
16347 // determine whether to use the ext or fixext types
16348 const bool use_ext = j.m_data.m_value.binary->has_subtype();
16349
16350 // step 1: write control byte and the byte string length
16351 const auto N = j.m_data.m_value.binary->size();
16352 if (N <= (std::numeric_limits<std::uint8_t>::max)())
16353 {
16354 std::uint8_t output_type{};
16355 bool fixed = true;
16356 if (use_ext)
16357 {
16358 switch (N)
16359 {
16360 case 1:
16361 output_type = 0xD4; // fixext 1
16362 break;
16363 case 2:
16364 output_type = 0xD5; // fixext 2
16365 break;
16366 case 4:
16367 output_type = 0xD6; // fixext 4
16368 break;
16369 case 8:
16370 output_type = 0xD7; // fixext 8
16371 break;
16372 case 16:
16373 output_type = 0xD8; // fixext 16
16374 break;
16375 default:
16376 output_type = 0xC7; // ext 8
16377 fixed = false;
16378 break;
16379 }
16380
16381 }
16382 else
16383 {
16384 output_type = 0xC4; // bin 8
16385 fixed = false;
16386 }
16387
16388 oa->write_character(to_char_type(output_type));
16389 if (!fixed)
16390 {
16391 write_number(static_cast<std::uint8_t>(N));
16392 }
16393 }
16394 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16395 {
16396 const std::uint8_t output_type = use_ext
16397 ? 0xC8 // ext 16
16398 : 0xC5; // bin 16
16399
16400 oa->write_character(to_char_type(output_type));
16401 write_number(static_cast<std::uint16_t>(N));
16402 }
16403 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16404 {
16405 const std::uint8_t output_type = use_ext
16406 ? 0xC9 // ext 32
16407 : 0xC6; // bin 32
16408
16409 oa->write_character(to_char_type(output_type));
16410 write_number(static_cast<std::uint32_t>(N));
16411 }
16412
16413 // step 1.5: if this is an ext type, write the subtype
16414 if (use_ext)
16415 {
16416 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
16417 }
16418
16419 // step 2: write the byte string
16420 oa->write_characters(
16421 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16422 N);
16423
16424 break;
16425 }
16426
16427 case value_t::object:
16428 {
16429 // step 1: write control byte and the object size
16430 const auto N = j.m_data.m_value.object->size();
16431 if (N <= 15)
16432 {
16433 // fixmap
16434 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
16435 }
16436 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16437 {
16438 // map 16
16439 oa->write_character(to_char_type(0xDE));
16440 write_number(static_cast<std::uint16_t>(N));
16441 }
16442 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16443 {
16444 // map 32
16445 oa->write_character(to_char_type(0xDF));
16446 write_number(static_cast<std::uint32_t>(N));
16447 }
16448
16449 // step 2: write each element
16450 for (const auto& el : *j.m_data.m_value.object)
16451 {
16452 write_msgpack(el.first);
16453 write_msgpack(el.second);
16454 }
16455 break;
16456 }
16457
16458 case value_t::discarded:
16459 default:
16460 break;
16461 }
16462 }
16463
16472 void write_ubjson(const BasicJsonType& j, const bool use_count,
16473 const bool use_type, const bool add_prefix = true,
16474 const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2)
16475 {
16476 const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3;
16477
16478 switch (j.type())
16479 {
16480 case value_t::null:
16481 {
16482 if (add_prefix)
16483 {
16484 oa->write_character(to_char_type('Z'));
16485 }
16486 break;
16487 }
16488
16489 case value_t::boolean:
16490 {
16491 if (add_prefix)
16492 {
16493 oa->write_character(j.m_data.m_value.boolean
16494 ? to_char_type('T')
16495 : to_char_type('F'));
16496 }
16497 break;
16498 }
16499
16501 {
16502 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
16503 break;
16504 }
16505
16507 {
16508 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
16509 break;
16510 }
16511
16513 {
16514 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
16515 break;
16516 }
16517
16518 case value_t::string:
16519 {
16520 if (add_prefix)
16521 {
16522 oa->write_character(to_char_type('S'));
16523 }
16524 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
16525 oa->write_characters(
16526 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16527 j.m_data.m_value.string->size());
16528 break;
16529 }
16530
16531 case value_t::array:
16532 {
16533 if (add_prefix)
16534 {
16535 oa->write_character(to_char_type('['));
16536 }
16537
16538 bool prefix_required = true;
16539 if (use_type && !j.m_data.m_value.array->empty())
16540 {
16541 JSON_ASSERT(use_count);
16542 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16543 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
16544 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16545 {
16546 return ubjson_prefix(v, use_bjdata) == first_prefix;
16547 });
16548
16549 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16550
16551 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16552 {
16553 prefix_required = false;
16554 oa->write_character(to_char_type('$'));
16555 oa->write_character(first_prefix);
16556 }
16557 }
16558
16559 if (use_count)
16560 {
16561 oa->write_character(to_char_type('#'));
16562 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
16563 }
16564
16565 for (const auto& el : *j.m_data.m_value.array)
16566 {
16567 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16568 }
16569
16570 if (!use_count)
16571 {
16572 oa->write_character(to_char_type(']'));
16573 }
16574
16575 break;
16576 }
16577
16578 case value_t::binary:
16579 {
16580 if (add_prefix)
16581 {
16582 oa->write_character(to_char_type('['));
16583 }
16584
16585 if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
16586 {
16587 JSON_ASSERT(use_count);
16588 oa->write_character(to_char_type('$'));
16589 oa->write_character(bjdata_draft3 ? 'B' : 'U');
16590 }
16591
16592 if (use_count)
16593 {
16594 oa->write_character(to_char_type('#'));
16595 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
16596 }
16597
16598 if (use_type)
16599 {
16600 oa->write_characters(
16601 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16602 j.m_data.m_value.binary->size());
16603 }
16604 else
16605 {
16606 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
16607 {
16608 oa->write_character(to_char_type(bjdata_draft3 ? 'B' : 'U'));
16609 oa->write_character(j.m_data.m_value.binary->data()[i]);
16610 }
16611 }
16612
16613 if (!use_count)
16614 {
16615 oa->write_character(to_char_type(']'));
16616 }
16617
16618 break;
16619 }
16620
16621 case value_t::object:
16622 {
16623 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())
16624 {
16625 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)
16626 {
16627 break;
16628 }
16629 }
16630
16631 if (add_prefix)
16632 {
16633 oa->write_character(to_char_type('{'));
16634 }
16635
16636 bool prefix_required = true;
16637 if (use_type && !j.m_data.m_value.object->empty())
16638 {
16639 JSON_ASSERT(use_count);
16640 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16641 const bool same_prefix = std::all_of(j.begin(), j.end(),
16642 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16643 {
16644 return ubjson_prefix(v, use_bjdata) == first_prefix;
16645 });
16646
16647 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16648
16649 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16650 {
16651 prefix_required = false;
16652 oa->write_character(to_char_type('$'));
16653 oa->write_character(first_prefix);
16654 }
16655 }
16656
16657 if (use_count)
16658 {
16659 oa->write_character(to_char_type('#'));
16660 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
16661 }
16662
16663 for (const auto& el : *j.m_data.m_value.object)
16664 {
16665 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
16666 oa->write_characters(
16667 reinterpret_cast<const CharType*>(el.first.c_str()),
16668 el.first.size());
16669 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16670 }
16671
16672 if (!use_count)
16673 {
16674 oa->write_character(to_char_type('}'));
16675 }
16676
16677 break;
16678 }
16679
16680 case value_t::discarded:
16681 default:
16682 break;
16683 }
16684 }
16685
16686 private:
16688 // BSON //
16690
16695 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16696 {
16697 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16698 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16699 {
16700 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16701 static_cast<void>(j);
16702 }
16703
16704 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16705 }
16706
16711 const std::uint8_t element_type)
16712 {
16713 oa->write_character(to_char_type(element_type)); // boolean
16714 oa->write_characters(
16715 reinterpret_cast<const CharType*>(name.c_str()),
16716 name.size() + 1u);
16717 }
16718
16723 const bool value)
16724 {
16725 write_bson_entry_header(name, 0x08);
16726 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16727 }
16728
16732 void write_bson_double(const string_t& name,
16733 const double value)
16734 {
16735 write_bson_entry_header(name, 0x01);
16737 }
16738
16742 static std::size_t calc_bson_string_size(const string_t& value)
16743 {
16744 return sizeof(std::int32_t) + value.size() + 1ul;
16745 }
16746
16750 void write_bson_string(const string_t& name,
16751 const string_t& value)
16752 {
16753 write_bson_entry_header(name, 0x02);
16754
16755 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16756 oa->write_characters(
16757 reinterpret_cast<const CharType*>(value.c_str()),
16758 value.size() + 1);
16759 }
16760
16764 void write_bson_null(const string_t& name)
16765 {
16766 write_bson_entry_header(name, 0x0A);
16767 }
16768
16772 static std::size_t calc_bson_integer_size(const std::int64_t value)
16773 {
16774 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16775 ? sizeof(std::int32_t)
16776 : sizeof(std::int64_t);
16777 }
16778
16783 const std::int64_t value)
16784 {
16785 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16786 {
16787 write_bson_entry_header(name, 0x10); // int32
16788 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16789 }
16790 else
16791 {
16792 write_bson_entry_header(name, 0x12); // int64
16793 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16794 }
16795 }
16796
16800 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16801 {
16802 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16803 ? sizeof(std::int32_t)
16804 : sizeof(std::int64_t);
16805 }
16806
16811 const BasicJsonType& j)
16812 {
16813 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16814 {
16815 write_bson_entry_header(name, 0x10 /* int32 */);
16816 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16817 }
16818 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16819 {
16820 write_bson_entry_header(name, 0x12 /* int64 */);
16821 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16822 }
16823 else
16824 {
16825 write_bson_entry_header(name, 0x11 /* uint64 */);
16826 write_number<std::uint64_t>(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned), true);
16827 }
16828 }
16829
16834 const typename BasicJsonType::object_t& value)
16835 {
16836 write_bson_entry_header(name, 0x03); // object
16838 }
16839
16843 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16844 {
16845 std::size_t array_index = 0ul;
16846
16847 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)
16848 {
16849 return result + calc_bson_element_size(std::to_string(array_index++), el);
16850 });
16851
16852 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16853 }
16854
16858 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16859 {
16860 return sizeof(std::int32_t) + value.size() + 1ul;
16861 }
16862
16866 void write_bson_array(const string_t& name,
16867 const typename BasicJsonType::array_t& value)
16868 {
16869 write_bson_entry_header(name, 0x04); // array
16870 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16871
16872 std::size_t array_index = 0ul;
16873
16874 for (const auto& el : value)
16875 {
16876 write_bson_element(std::to_string(array_index++), el);
16877 }
16878
16879 oa->write_character(to_char_type(0x00));
16880 }
16881
16885 void write_bson_binary(const string_t& name,
16886 const binary_t& value)
16887 {
16888 write_bson_entry_header(name, 0x05);
16889
16890 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16891 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16892
16893 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16894 }
16895
16900 static std::size_t calc_bson_element_size(const string_t& name,
16901 const BasicJsonType& j)
16902 {
16903 const auto header_size = calc_bson_entry_header_size(name, j);
16904 switch (j.type())
16905 {
16906 case value_t::object:
16907 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16908
16909 case value_t::array:
16910 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16911
16912 case value_t::binary:
16913 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16914
16915 case value_t::boolean:
16916 return header_size + 1ul;
16917
16919 return header_size + 8ul;
16920
16922 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16923
16925 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16926
16927 case value_t::string:
16928 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16929
16930 case value_t::null:
16931 return header_size + 0ul;
16932
16933 // LCOV_EXCL_START
16934 case value_t::discarded:
16935 default:
16936 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16937 return 0ul;
16938 // LCOV_EXCL_STOP
16939 }
16940 }
16941
16949 const BasicJsonType& j)
16950 {
16951 switch (j.type())
16952 {
16953 case value_t::object:
16954 return write_bson_object_entry(name, *j.m_data.m_value.object);
16955
16956 case value_t::array:
16957 return write_bson_array(name, *j.m_data.m_value.array);
16958
16959 case value_t::binary:
16960 return write_bson_binary(name, *j.m_data.m_value.binary);
16961
16962 case value_t::boolean:
16963 return write_bson_boolean(name, j.m_data.m_value.boolean);
16964
16966 return write_bson_double(name, j.m_data.m_value.number_float);
16967
16969 return write_bson_integer(name, j.m_data.m_value.number_integer);
16970
16972 return write_bson_unsigned(name, j);
16973
16974 case value_t::string:
16975 return write_bson_string(name, *j.m_data.m_value.string);
16976
16977 case value_t::null:
16978 return write_bson_null(name);
16979
16980 // LCOV_EXCL_START
16981 case value_t::discarded:
16982 default:
16983 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16984 return;
16985 // LCOV_EXCL_STOP
16986 }
16987 }
16988
16995 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
16996 {
16997 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
16998 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
16999 {
17000 return result += calc_bson_element_size(el.first, el.second);
17001 });
17002
17003 return sizeof(std::int32_t) + document_size + 1ul;
17004 }
17005
17010 void write_bson_object(const typename BasicJsonType::object_t& value)
17011 {
17012 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
17013
17014 for (const auto& el : value)
17015 {
17016 write_bson_element(el.first, el.second);
17017 }
17018
17019 oa->write_character(to_char_type(0x00));
17020 }
17021
17023 // CBOR //
17025
17026 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
17027 {
17028 return to_char_type(0xFA); // Single-Precision Float
17029 }
17030
17031 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
17032 {
17033 return to_char_type(0xFB); // Double-Precision Float
17034 }
17035
17037 // MsgPack //
17039
17040 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
17041 {
17042 return to_char_type(0xCA); // float 32
17043 }
17044
17045 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
17046 {
17047 return to_char_type(0xCB); // float 64
17048 }
17049
17051 // UBJSON //
17053
17054 // UBJSON: write number (floating point)
17055 template<typename NumberType, typename std::enable_if<
17056 std::is_floating_point<NumberType>::value, int>::type = 0>
17057 void write_number_with_ubjson_prefix(const NumberType n,
17058 const bool add_prefix,
17059 const bool use_bjdata)
17060 {
17061 if (add_prefix)
17062 {
17063 oa->write_character(get_ubjson_float_prefix(n));
17064 }
17065 write_number(n, use_bjdata);
17066 }
17067
17068 // UBJSON: write number (unsigned integer)
17069 template<typename NumberType, typename std::enable_if<
17070 std::is_unsigned<NumberType>::value, int>::type = 0>
17071 void write_number_with_ubjson_prefix(const NumberType n,
17072 const bool add_prefix,
17073 const bool use_bjdata)
17074 {
17075 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17076 {
17077 if (add_prefix)
17078 {
17079 oa->write_character(to_char_type('i')); // int8
17080 }
17081 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17082 }
17083 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
17084 {
17085 if (add_prefix)
17086 {
17087 oa->write_character(to_char_type('U')); // uint8
17088 }
17089 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17090 }
17091 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17092 {
17093 if (add_prefix)
17094 {
17095 oa->write_character(to_char_type('I')); // int16
17096 }
17097 write_number(static_cast<std::int16_t>(n), use_bjdata);
17098 }
17099 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
17100 {
17101 if (add_prefix)
17102 {
17103 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17104 }
17105 write_number(static_cast<std::uint16_t>(n), use_bjdata);
17106 }
17107 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17108 {
17109 if (add_prefix)
17110 {
17111 oa->write_character(to_char_type('l')); // int32
17112 }
17113 write_number(static_cast<std::int32_t>(n), use_bjdata);
17114 }
17115 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
17116 {
17117 if (add_prefix)
17118 {
17119 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17120 }
17121 write_number(static_cast<std::uint32_t>(n), use_bjdata);
17122 }
17123 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17124 {
17125 if (add_prefix)
17126 {
17127 oa->write_character(to_char_type('L')); // int64
17128 }
17129 write_number(static_cast<std::int64_t>(n), use_bjdata);
17130 }
17131 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
17132 {
17133 if (add_prefix)
17134 {
17135 oa->write_character(to_char_type('M')); // uint64 - bjdata only
17136 }
17137 write_number(static_cast<std::uint64_t>(n), use_bjdata);
17138 }
17139 else
17140 {
17141 if (add_prefix)
17142 {
17143 oa->write_character(to_char_type('H')); // high-precision number
17144 }
17145
17146 const auto number = BasicJsonType(n).dump();
17147 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17148 for (std::size_t i = 0; i < number.size(); ++i)
17149 {
17150 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17151 }
17152 }
17153 }
17154
17155 // UBJSON: write number (signed integer)
17156 template < typename NumberType, typename std::enable_if <
17157 std::is_signed<NumberType>::value&&
17158 !std::is_floating_point<NumberType>::value, int >::type = 0 >
17159 void write_number_with_ubjson_prefix(const NumberType n,
17160 const bool add_prefix,
17161 const bool use_bjdata)
17162 {
17163 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
17164 {
17165 if (add_prefix)
17166 {
17167 oa->write_character(to_char_type('i')); // int8
17168 }
17169 write_number(static_cast<std::int8_t>(n), use_bjdata);
17170 }
17171 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)()))
17172 {
17173 if (add_prefix)
17174 {
17175 oa->write_character(to_char_type('U')); // uint8
17176 }
17177 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17178 }
17179 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
17180 {
17181 if (add_prefix)
17182 {
17183 oa->write_character(to_char_type('I')); // int16
17184 }
17185 write_number(static_cast<std::int16_t>(n), use_bjdata);
17186 }
17187 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)())))
17188 {
17189 if (add_prefix)
17190 {
17191 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17192 }
17193 write_number(static_cast<uint16_t>(n), use_bjdata);
17194 }
17195 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
17196 {
17197 if (add_prefix)
17198 {
17199 oa->write_character(to_char_type('l')); // int32
17200 }
17201 write_number(static_cast<std::int32_t>(n), use_bjdata);
17202 }
17203 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)())))
17204 {
17205 if (add_prefix)
17206 {
17207 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17208 }
17209 write_number(static_cast<uint32_t>(n), use_bjdata);
17210 }
17211 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
17212 {
17213 if (add_prefix)
17214 {
17215 oa->write_character(to_char_type('L')); // int64
17216 }
17217 write_number(static_cast<std::int64_t>(n), use_bjdata);
17218 }
17219 // LCOV_EXCL_START
17220 else
17221 {
17222 if (add_prefix)
17223 {
17224 oa->write_character(to_char_type('H')); // high-precision number
17225 }
17226
17227 const auto number = BasicJsonType(n).dump();
17228 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17229 for (std::size_t i = 0; i < number.size(); ++i)
17230 {
17231 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17232 }
17233 }
17234 // LCOV_EXCL_STOP
17235 }
17236
17240 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
17241 {
17242 switch (j.type())
17243 {
17244 case value_t::null:
17245 return 'Z';
17246
17247 case value_t::boolean:
17248 return j.m_data.m_value.boolean ? 'T' : 'F';
17249
17251 {
17252 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)())
17253 {
17254 return 'i';
17255 }
17256 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)())
17257 {
17258 return 'U';
17259 }
17260 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)())
17261 {
17262 return 'I';
17263 }
17264 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)()))
17265 {
17266 return 'u';
17267 }
17268 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)())
17269 {
17270 return 'l';
17271 }
17272 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)()))
17273 {
17274 return 'm';
17275 }
17276 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)())
17277 {
17278 return 'L';
17279 }
17280 // anything else is treated as high-precision number
17281 return 'H'; // LCOV_EXCL_LINE
17282 }
17283
17285 {
17286 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17287 {
17288 return 'i';
17289 }
17290 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
17291 {
17292 return 'U';
17293 }
17294 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17295 {
17296 return 'I';
17297 }
17298 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
17299 {
17300 return 'u';
17301 }
17302 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17303 {
17304 return 'l';
17305 }
17306 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
17307 {
17308 return 'm';
17309 }
17310 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17311 {
17312 return 'L';
17313 }
17314 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
17315 {
17316 return 'M';
17317 }
17318 // anything else is treated as high-precision number
17319 return 'H'; // LCOV_EXCL_LINE
17320 }
17321
17323 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
17324
17325 case value_t::string:
17326 return 'S';
17327
17328 case value_t::array: // fallthrough
17329 case value_t::binary:
17330 return '[';
17331
17332 case value_t::object:
17333 return '{';
17334
17335 case value_t::discarded:
17336 default: // discarded values
17337 return 'N';
17338 }
17339 }
17340
17341 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
17342 {
17343 return 'd'; // float 32
17344 }
17345
17346 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
17347 {
17348 return 'D'; // float 64
17349 }
17350
17354 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
17355 {
17356 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
17357 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'},
17358 {"char", 'C'}, {"byte", 'B'}
17359 };
17360
17361 string_t key = "_ArrayType_";
17362 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
17363 if (it == bjdtype.end())
17364 {
17365 return true;
17366 }
17367 CharType dtype = it->second;
17368
17369 key = "_ArraySize_";
17370 std::size_t len = (value.at(key).empty() ? 0 : 1);
17371 for (const auto& el : value.at(key))
17372 {
17373 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
17374 }
17375
17376 key = "_ArrayData_";
17377 if (value.at(key).size() != len)
17378 {
17379 return true;
17380 }
17381
17382 oa->write_character('[');
17383 oa->write_character('$');
17384 oa->write_character(dtype);
17385 oa->write_character('#');
17386
17387 key = "_ArraySize_";
17388 write_ubjson(value.at(key), use_count, use_type, true, true, bjdata_version);
17389
17390 key = "_ArrayData_";
17391 if (dtype == 'U' || dtype == 'C' || dtype == 'B')
17392 {
17393 for (const auto& el : value.at(key))
17394 {
17395 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
17396 }
17397 }
17398 else if (dtype == 'i')
17399 {
17400 for (const auto& el : value.at(key))
17401 {
17402 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
17403 }
17404 }
17405 else if (dtype == 'u')
17406 {
17407 for (const auto& el : value.at(key))
17408 {
17409 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
17410 }
17411 }
17412 else if (dtype == 'I')
17413 {
17414 for (const auto& el : value.at(key))
17415 {
17416 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
17417 }
17418 }
17419 else if (dtype == 'm')
17420 {
17421 for (const auto& el : value.at(key))
17422 {
17423 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
17424 }
17425 }
17426 else if (dtype == 'l')
17427 {
17428 for (const auto& el : value.at(key))
17429 {
17430 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
17431 }
17432 }
17433 else if (dtype == 'M')
17434 {
17435 for (const auto& el : value.at(key))
17436 {
17437 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
17438 }
17439 }
17440 else if (dtype == 'L')
17441 {
17442 for (const auto& el : value.at(key))
17443 {
17444 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
17445 }
17446 }
17447 else if (dtype == 'd')
17448 {
17449 for (const auto& el : value.at(key))
17450 {
17451 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
17452 }
17453 }
17454 else if (dtype == 'D')
17455 {
17456 for (const auto& el : value.at(key))
17457 {
17458 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
17459 }
17460 }
17461 return false;
17462 }
17463
17465 // Utility functions //
17467
17468 /*
17469 @brief write a number to output input
17470 @param[in] n number of type @a NumberType
17471 @param[in] OutputIsLittleEndian Set to true if output data is
17472 required to be little endian
17473 @tparam NumberType the type of the number
17474
17475 @note This function needs to respect the system's endianness, because bytes
17476 in CBOR, MessagePack, and UBJSON are stored in network order (big
17477 endian) and therefore need reordering on little endian systems.
17478 On the other hand, BSON and BJData use little endian and should reorder
17479 on big endian systems.
17480 */
17481 template<typename NumberType>
17482 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
17483 {
17484 // step 1: write number to array of length NumberType
17485 std::array<CharType, sizeof(NumberType)> vec{};
17486 std::memcpy(vec.data(), &n, sizeof(NumberType));
17487
17488 // step 2: write array to output (with possible reordering)
17489 if (is_little_endian != OutputIsLittleEndian)
17490 {
17491 // reverse byte order prior to conversion if necessary
17492 std::reverse(vec.begin(), vec.end());
17493 }
17494
17495 oa->write_characters(vec.data(), sizeof(NumberType));
17496 }
17497
17499 {
17500#ifdef __GNUC__
17501#pragma GCC diagnostic push
17502#pragma GCC diagnostic ignored "-Wfloat-equal"
17503#endif
17504 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
17505 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
17506 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
17507 {
17508 oa->write_character(format == detail::input_format_t::cbor
17509 ? get_cbor_float_prefix(static_cast<float>(n))
17510 : get_msgpack_float_prefix(static_cast<float>(n)));
17511 write_number(static_cast<float>(n));
17512 }
17513 else
17514 {
17515 oa->write_character(format == detail::input_format_t::cbor
17518 write_number(n);
17519 }
17520#ifdef __GNUC__
17521#pragma GCC diagnostic pop
17522#endif
17523 }
17524
17525 public:
17526 // The following to_char_type functions are implement the conversion
17527 // between uint8_t and CharType. In case CharType is not unsigned,
17528 // such a conversion is required to allow values greater than 128.
17529 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
17530 template < typename C = CharType,
17531 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
17532 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17533 {
17534 return *reinterpret_cast<char*>(&x);
17535 }
17536
17537 template < typename C = CharType,
17538 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
17539 static CharType to_char_type(std::uint8_t x) noexcept
17540 {
17541 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
17542 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
17543 CharType result;
17544 std::memcpy(&result, &x, sizeof(x));
17545 return result;
17546 }
17547
17548 template<typename C = CharType,
17550 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17551 {
17552 return x;
17553 }
17554
17555 template < typename InputCharType, typename C = CharType,
17556 enable_if_t <
17557 std::is_signed<C>::value &&
17558 std::is_signed<char>::value &&
17559 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
17560 > * = nullptr >
17561 static constexpr CharType to_char_type(InputCharType x) noexcept
17562 {
17563 return x;
17564 }
17565
17566 private:
17569
17572};
17573
17574} // namespace detail
17576
17577// #include <nlohmann/detail/output/output_adapters.hpp>
17578
17579// #include <nlohmann/detail/output/serializer.hpp>
17580// __ _____ _____ _____
17581// __| | __| | | | JSON for Modern C++
17582// | | |__ | | | | | | version 3.11.3
17583// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17584//
17585// SPDX-FileCopyrightText: 2008 - 2009 Björn Hoehrmann <bjoern@hoehrmann.de>
17586// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17587// SPDX-License-Identifier: MIT
17588
17589
17590
17591#include <algorithm> // reverse, remove, fill, find, none_of
17592#include <array> // array
17593#include <clocale> // localeconv, lconv
17594#include <cmath> // labs, isfinite, isnan, signbit
17595#include <cstddef> // size_t, ptrdiff_t
17596#include <cstdint> // uint8_t
17597#include <cstdio> // snprintf
17598#include <limits> // numeric_limits
17599#include <string> // string, char_traits
17600#include <iomanip> // setfill, setw
17601#include <type_traits> // is_same
17602#include <utility> // move
17603
17604// #include <nlohmann/detail/conversions/to_chars.hpp>
17605// __ _____ _____ _____
17606// __| | __| | | | JSON for Modern C++
17607// | | |__ | | | | | | version 3.11.3
17608// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17609//
17610// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
17611// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17612// SPDX-License-Identifier: MIT
17613
17614
17615
17616#include <array> // array
17617#include <cmath> // signbit, isfinite
17618#include <cstdint> // intN_t, uintN_t
17619#include <cstring> // memcpy, memmove
17620#include <limits> // numeric_limits
17621#include <type_traits> // conditional
17622
17623// #include <nlohmann/detail/macro_scope.hpp>
17624
17625
17627namespace detail
17628{
17629
17649namespace dtoa_impl
17650{
17651
17652template<typename Target, typename Source>
17653Target reinterpret_bits(const Source source)
17654{
17655 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
17656
17657 Target target;
17658 std::memcpy(&target, &source, sizeof(Source));
17659 return target;
17660}
17661
17662struct diyfp // f * 2^e
17663{
17664 static constexpr int kPrecision = 64; // = q
17665
17666 std::uint64_t f = 0;
17667 int e = 0;
17668
17669 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
17670
17675 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
17676 {
17677 JSON_ASSERT(x.e == y.e);
17678 JSON_ASSERT(x.f >= y.f);
17679
17680 return {x.f - y.f, x.e};
17681 }
17682
17687 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17688 {
17689 static_assert(kPrecision == 64, "internal error");
17690
17691 // Computes:
17692 // f = round((x.f * y.f) / 2^q)
17693 // e = x.e + y.e + q
17694
17695 // Emulate the 64-bit * 64-bit multiplication:
17696 //
17697 // p = u * v
17698 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17699 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17700 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17701 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17702 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17703 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17704 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17705 //
17706 // (Since Q might be larger than 2^32 - 1)
17707 //
17708 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17709 //
17710 // (Q_hi + H does not overflow a 64-bit int)
17711 //
17712 // = p_lo + 2^64 p_hi
17713
17714 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17715 const std::uint64_t u_hi = x.f >> 32u;
17716 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17717 const std::uint64_t v_hi = y.f >> 32u;
17718
17719 const std::uint64_t p0 = u_lo * v_lo;
17720 const std::uint64_t p1 = u_lo * v_hi;
17721 const std::uint64_t p2 = u_hi * v_lo;
17722 const std::uint64_t p3 = u_hi * v_hi;
17723
17724 const std::uint64_t p0_hi = p0 >> 32u;
17725 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17726 const std::uint64_t p1_hi = p1 >> 32u;
17727 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17728 const std::uint64_t p2_hi = p2 >> 32u;
17729
17730 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17731
17732 // The full product might now be computed as
17733 //
17734 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17735 // p_lo = p0_lo + (Q << 32)
17736 //
17737 // But in this particular case here, the full p_lo is not required.
17738 // Effectively we only need to add the highest bit in p_lo to p_hi (and
17739 // Q_hi + 1 does not overflow).
17740
17741 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17742
17743 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17744
17745 return {h, x.e + y.e + 64};
17746 }
17747
17752 static diyfp normalize(diyfp x) noexcept
17753 {
17754 JSON_ASSERT(x.f != 0);
17755
17756 while ((x.f >> 63u) == 0)
17757 {
17758 x.f <<= 1u;
17759 x.e--;
17760 }
17761
17762 return x;
17763 }
17764
17769 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17770 {
17771 const int delta = x.e - target_exponent;
17772
17773 JSON_ASSERT(delta >= 0);
17774 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17775
17776 return {x.f << delta, target_exponent};
17777 }
17778};
17779
17786
17793template<typename FloatType>
17795{
17796 JSON_ASSERT(std::isfinite(value));
17797 JSON_ASSERT(value > 0);
17798
17799 // Convert the IEEE representation into a diyfp.
17800 //
17801 // If v is denormal:
17802 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17803 // If v is normalized:
17804 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17805
17806 static_assert(std::numeric_limits<FloatType>::is_iec559,
17807 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17808
17809 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17810 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17811 constexpr int kMinExp = 1 - kBias;
17812 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17813
17814 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17815
17816 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17817 const std::uint64_t E = bits >> (kPrecision - 1);
17818 const std::uint64_t F = bits & (kHiddenBit - 1);
17819
17820 const bool is_denormal = E == 0;
17821 const diyfp v = is_denormal
17822 ? diyfp(F, kMinExp)
17823 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17824
17825 // Compute the boundaries m- and m+ of the floating-point value
17826 // v = f * 2^e.
17827 //
17828 // Determine v- and v+, the floating-point predecessor and successor if v,
17829 // respectively.
17830 //
17831 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17832 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17833 //
17834 // v+ = v + 2^e
17835 //
17836 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17837 // between m- and m+ round to v, regardless of how the input rounding
17838 // algorithm breaks ties.
17839 //
17840 // ---+-------------+-------------+-------------+-------------+--- (A)
17841 // v- m- v m+ v+
17842 //
17843 // -----------------+------+------+-------------+-------------+--- (B)
17844 // v- m- v m+ v+
17845
17846 const bool lower_boundary_is_closer = F == 0 && E > 1;
17847 const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
17848 const diyfp m_minus = lower_boundary_is_closer
17849 ? diyfp((4 * v.f) - 1, v.e - 2) // (B)
17850 : diyfp((2 * v.f) - 1, v.e - 1); // (A)
17851
17852 // Determine the normalized w+ = m+.
17853 const diyfp w_plus = diyfp::normalize(m_plus);
17854
17855 // Determine w- = m- such that e_(w-) = e_(w+).
17856 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17857
17858 return {diyfp::normalize(v), w_minus, w_plus};
17859}
17860
17861// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17862// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17863// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17864//
17865// alpha <= e = e_c + e_w + q <= gamma
17866//
17867// or
17868//
17869// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17870// <= f_c * f_w * 2^gamma
17871//
17872// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17873//
17874// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17875//
17876// or
17877//
17878// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17879//
17880// The choice of (alpha,gamma) determines the size of the table and the form of
17881// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17882// in practice:
17883//
17884// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17885// processed independently: An integral part p1, and a fractional part p2:
17886//
17887// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17888// = (f div 2^-e) + (f mod 2^-e) * 2^e
17889// = p1 + p2 * 2^e
17890//
17891// The conversion of p1 into decimal form requires a series of divisions and
17892// modulos by (a power of) 10. These operations are faster for 32-bit than for
17893// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17894// achieved by choosing
17895//
17896// -e >= 32 or e <= -32 := gamma
17897//
17898// In order to convert the fractional part
17899//
17900// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17901//
17902// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17903// d[-i] are extracted in order:
17904//
17905// (10 * p2) div 2^-e = d[-1]
17906// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17907//
17908// The multiplication by 10 must not overflow. It is sufficient to choose
17909//
17910// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17911//
17912// Since p2 = f mod 2^-e < 2^-e,
17913//
17914// -e <= 60 or e >= -60 := alpha
17915
17916constexpr int kAlpha = -60;
17917constexpr int kGamma = -32;
17918
17919struct cached_power // c = f * 2^e ~= 10^k
17920{
17921 std::uint64_t f;
17922 int e;
17923 int k;
17924};
17925
17934{
17935 // Now
17936 //
17937 // alpha <= e_c + e + q <= gamma (1)
17938 // ==> f_c * 2^alpha <= c * 2^e * 2^q
17939 //
17940 // and since the c's are normalized, 2^(q-1) <= f_c,
17941 //
17942 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
17943 // ==> 2^(alpha - e - 1) <= c
17944 //
17945 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
17946 //
17947 // k = ceil( log_10( 2^(alpha - e - 1) ) )
17948 // = ceil( (alpha - e - 1) * log_10(2) )
17949 //
17950 // From the paper:
17951 // "In theory the result of the procedure could be wrong since c is rounded,
17952 // and the computation itself is approximated [...]. In practice, however,
17953 // this simple function is sufficient."
17954 //
17955 // For IEEE double precision floating-point numbers converted into
17956 // normalized diyfp's w = f * 2^e, with q = 64,
17957 //
17958 // e >= -1022 (min IEEE exponent)
17959 // -52 (p - 1)
17960 // -52 (p - 1, possibly normalize denormal IEEE numbers)
17961 // -11 (normalize the diyfp)
17962 // = -1137
17963 //
17964 // and
17965 //
17966 // e <= +1023 (max IEEE exponent)
17967 // -52 (p - 1)
17968 // -11 (normalize the diyfp)
17969 // = 960
17970 //
17971 // This binary exponent range [-1137,960] results in a decimal exponent
17972 // range [-307,324]. One does not need to store a cached power for each
17973 // k in this range. For each such k it suffices to find a cached power
17974 // such that the exponent of the product lies in [alpha,gamma].
17975 // This implies that the difference of the decimal exponents of adjacent
17976 // table entries must be less than or equal to
17977 //
17978 // floor( (gamma - alpha) * log_10(2) ) = 8.
17979 //
17980 // (A smaller distance gamma-alpha would require a larger table.)
17981
17982 // NB:
17983 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
17984
17985 constexpr int kCachedPowersMinDecExp = -300;
17986 constexpr int kCachedPowersDecStep = 8;
17987
17988 static constexpr std::array<cached_power, 79> kCachedPowers =
17989 {
17990 {
17991 { 0xAB70FE17C79AC6CA, -1060, -300 },
17992 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
17993 { 0xBE5691EF416BD60C, -1007, -284 },
17994 { 0x8DD01FAD907FFC3C, -980, -276 },
17995 { 0xD3515C2831559A83, -954, -268 },
17996 { 0x9D71AC8FADA6C9B5, -927, -260 },
17997 { 0xEA9C227723EE8BCB, -901, -252 },
17998 { 0xAECC49914078536D, -874, -244 },
17999 { 0x823C12795DB6CE57, -847, -236 },
18000 { 0xC21094364DFB5637, -821, -228 },
18001 { 0x9096EA6F3848984F, -794, -220 },
18002 { 0xD77485CB25823AC7, -768, -212 },
18003 { 0xA086CFCD97BF97F4, -741, -204 },
18004 { 0xEF340A98172AACE5, -715, -196 },
18005 { 0xB23867FB2A35B28E, -688, -188 },
18006 { 0x84C8D4DFD2C63F3B, -661, -180 },
18007 { 0xC5DD44271AD3CDBA, -635, -172 },
18008 { 0x936B9FCEBB25C996, -608, -164 },
18009 { 0xDBAC6C247D62A584, -582, -156 },
18010 { 0xA3AB66580D5FDAF6, -555, -148 },
18011 { 0xF3E2F893DEC3F126, -529, -140 },
18012 { 0xB5B5ADA8AAFF80B8, -502, -132 },
18013 { 0x87625F056C7C4A8B, -475, -124 },
18014 { 0xC9BCFF6034C13053, -449, -116 },
18015 { 0x964E858C91BA2655, -422, -108 },
18016 { 0xDFF9772470297EBD, -396, -100 },
18017 { 0xA6DFBD9FB8E5B88F, -369, -92 },
18018 { 0xF8A95FCF88747D94, -343, -84 },
18019 { 0xB94470938FA89BCF, -316, -76 },
18020 { 0x8A08F0F8BF0F156B, -289, -68 },
18021 { 0xCDB02555653131B6, -263, -60 },
18022 { 0x993FE2C6D07B7FAC, -236, -52 },
18023 { 0xE45C10C42A2B3B06, -210, -44 },
18024 { 0xAA242499697392D3, -183, -36 },
18025 { 0xFD87B5F28300CA0E, -157, -28 },
18026 { 0xBCE5086492111AEB, -130, -20 },
18027 { 0x8CBCCC096F5088CC, -103, -12 },
18028 { 0xD1B71758E219652C, -77, -4 },
18029 { 0x9C40000000000000, -50, 4 },
18030 { 0xE8D4A51000000000, -24, 12 },
18031 { 0xAD78EBC5AC620000, 3, 20 },
18032 { 0x813F3978F8940984, 30, 28 },
18033 { 0xC097CE7BC90715B3, 56, 36 },
18034 { 0x8F7E32CE7BEA5C70, 83, 44 },
18035 { 0xD5D238A4ABE98068, 109, 52 },
18036 { 0x9F4F2726179A2245, 136, 60 },
18037 { 0xED63A231D4C4FB27, 162, 68 },
18038 { 0xB0DE65388CC8ADA8, 189, 76 },
18039 { 0x83C7088E1AAB65DB, 216, 84 },
18040 { 0xC45D1DF942711D9A, 242, 92 },
18041 { 0x924D692CA61BE758, 269, 100 },
18042 { 0xDA01EE641A708DEA, 295, 108 },
18043 { 0xA26DA3999AEF774A, 322, 116 },
18044 { 0xF209787BB47D6B85, 348, 124 },
18045 { 0xB454E4A179DD1877, 375, 132 },
18046 { 0x865B86925B9BC5C2, 402, 140 },
18047 { 0xC83553C5C8965D3D, 428, 148 },
18048 { 0x952AB45CFA97A0B3, 455, 156 },
18049 { 0xDE469FBD99A05FE3, 481, 164 },
18050 { 0xA59BC234DB398C25, 508, 172 },
18051 { 0xF6C69A72A3989F5C, 534, 180 },
18052 { 0xB7DCBF5354E9BECE, 561, 188 },
18053 { 0x88FCF317F22241E2, 588, 196 },
18054 { 0xCC20CE9BD35C78A5, 614, 204 },
18055 { 0x98165AF37B2153DF, 641, 212 },
18056 { 0xE2A0B5DC971F303A, 667, 220 },
18057 { 0xA8D9D1535CE3B396, 694, 228 },
18058 { 0xFB9B7CD9A4A7443C, 720, 236 },
18059 { 0xBB764C4CA7A44410, 747, 244 },
18060 { 0x8BAB8EEFB6409C1A, 774, 252 },
18061 { 0xD01FEF10A657842C, 800, 260 },
18062 { 0x9B10A4E5E9913129, 827, 268 },
18063 { 0xE7109BFBA19C0C9D, 853, 276 },
18064 { 0xAC2820D9623BF429, 880, 284 },
18065 { 0x80444B5E7AA7CF85, 907, 292 },
18066 { 0xBF21E44003ACDD2D, 933, 300 },
18067 { 0x8E679C2F5E44FF8F, 960, 308 },
18068 { 0xD433179D9C8CB841, 986, 316 },
18069 { 0x9E19DB92B4E31BA9, 1013, 324 },
18070 }
18071 };
18072
18073 // This computation gives exactly the same results for k as
18074 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
18075 // for |e| <= 1500, but doesn't require floating-point operations.
18076 // NB: log_10(2) ~= 78913 / 2^18
18077 JSON_ASSERT(e >= -1500);
18078 JSON_ASSERT(e <= 1500);
18079 const int f = kAlpha - e - 1;
18080 const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
18081
18082 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
18083 JSON_ASSERT(index >= 0);
18084 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
18085
18086 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
18087 JSON_ASSERT(kAlpha <= cached.e + e + 64);
18088 JSON_ASSERT(kGamma >= cached.e + e + 64);
18089
18090 return cached;
18091}
18092
18097inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
18098{
18099 // LCOV_EXCL_START
18100 if (n >= 1000000000)
18101 {
18102 pow10 = 1000000000;
18103 return 10;
18104 }
18105 // LCOV_EXCL_STOP
18106 if (n >= 100000000)
18107 {
18108 pow10 = 100000000;
18109 return 9;
18110 }
18111 if (n >= 10000000)
18112 {
18113 pow10 = 10000000;
18114 return 8;
18115 }
18116 if (n >= 1000000)
18117 {
18118 pow10 = 1000000;
18119 return 7;
18120 }
18121 if (n >= 100000)
18122 {
18123 pow10 = 100000;
18124 return 6;
18125 }
18126 if (n >= 10000)
18127 {
18128 pow10 = 10000;
18129 return 5;
18130 }
18131 if (n >= 1000)
18132 {
18133 pow10 = 1000;
18134 return 4;
18135 }
18136 if (n >= 100)
18137 {
18138 pow10 = 100;
18139 return 3;
18140 }
18141 if (n >= 10)
18142 {
18143 pow10 = 10;
18144 return 2;
18145 }
18146
18147 pow10 = 1;
18148 return 1;
18149}
18150
18151inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
18152 std::uint64_t rest, std::uint64_t ten_k)
18153{
18154 JSON_ASSERT(len >= 1);
18155 JSON_ASSERT(dist <= delta);
18156 JSON_ASSERT(rest <= delta);
18157 JSON_ASSERT(ten_k > 0);
18158
18159 // <--------------------------- delta ---->
18160 // <---- dist --------->
18161 // --------------[------------------+-------------------]--------------
18162 // M- w M+
18163 //
18164 // ten_k
18165 // <------>
18166 // <---- rest ---->
18167 // --------------[------------------+----+--------------]--------------
18168 // w V
18169 // = buf * 10^k
18170 //
18171 // ten_k represents a unit-in-the-last-place in the decimal representation
18172 // stored in buf.
18173 // Decrement buf by ten_k while this takes buf closer to w.
18174
18175 // The tests are written in this order to avoid overflow in unsigned
18176 // integer arithmetic.
18177
18178 while (rest < dist
18179 && delta - rest >= ten_k
18180 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
18181 {
18182 JSON_ASSERT(buf[len - 1] != '0');
18183 buf[len - 1]--;
18184 rest += ten_k;
18185 }
18186}
18187
18192inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
18193 diyfp M_minus, diyfp w, diyfp M_plus)
18194{
18195 static_assert(kAlpha >= -60, "internal error");
18196 static_assert(kGamma <= -32, "internal error");
18197
18198 // Generates the digits (and the exponent) of a decimal floating-point
18199 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
18200 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
18201 //
18202 // <--------------------------- delta ---->
18203 // <---- dist --------->
18204 // --------------[------------------+-------------------]--------------
18205 // M- w M+
18206 //
18207 // Grisu2 generates the digits of M+ from left to right and stops as soon as
18208 // V is in [M-,M+].
18209
18210 JSON_ASSERT(M_plus.e >= kAlpha);
18211 JSON_ASSERT(M_plus.e <= kGamma);
18212
18213 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
18214 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
18215
18216 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
18217 //
18218 // M+ = f * 2^e
18219 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
18220 // = ((p1 ) * 2^-e + (p2 )) * 2^e
18221 // = p1 + p2 * 2^e
18222
18223 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
18224
18225 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.)
18226 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
18227
18228 // 1)
18229 //
18230 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
18231
18232 JSON_ASSERT(p1 > 0);
18233
18234 std::uint32_t pow10{};
18235 const int k = find_largest_pow10(p1, pow10);
18236
18237 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
18238 //
18239 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
18240 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
18241 //
18242 // M+ = p1 + p2 * 2^e
18243 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
18244 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
18245 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
18246 //
18247 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
18248 //
18249 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
18250 //
18251 // but stop as soon as
18252 //
18253 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
18254
18255 int n = k;
18256 while (n > 0)
18257 {
18258 // Invariants:
18259 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
18260 // pow10 = 10^(n-1) <= p1 < 10^n
18261 //
18262 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
18263 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
18264 //
18265 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
18266 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
18267 //
18268 JSON_ASSERT(d <= 9);
18269 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18270 //
18271 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
18272 //
18273 p1 = r;
18274 n--;
18275 //
18276 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
18277 // pow10 = 10^n
18278 //
18279
18280 // Now check if enough digits have been generated.
18281 // Compute
18282 //
18283 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
18284 //
18285 // Note:
18286 // Since rest and delta share the same exponent e, it suffices to
18287 // compare the significands.
18288 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
18289 if (rest <= delta)
18290 {
18291 // V = buffer * 10^n, with M- <= V <= M+.
18292
18293 decimal_exponent += n;
18294
18295 // We may now just stop. But instead look if the buffer could be
18296 // decremented to bring V closer to w.
18297 //
18298 // pow10 = 10^n is now 1 ulp in the decimal representation V.
18299 // The rounding procedure works with diyfp's with an implicit
18300 // exponent of e.
18301 //
18302 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
18303 //
18304 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
18305 grisu2_round(buffer, length, dist, delta, rest, ten_n);
18306
18307 return;
18308 }
18309
18310 pow10 /= 10;
18311 //
18312 // pow10 = 10^(n-1) <= p1 < 10^n
18313 // Invariants restored.
18314 }
18315
18316 // 2)
18317 //
18318 // The digits of the integral part have been generated:
18319 //
18320 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
18321 // = buffer + p2 * 2^e
18322 //
18323 // Now generate the digits of the fractional part p2 * 2^e.
18324 //
18325 // Note:
18326 // No decimal point is generated: the exponent is adjusted instead.
18327 //
18328 // p2 actually represents the fraction
18329 //
18330 // p2 * 2^e
18331 // = p2 / 2^-e
18332 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
18333 //
18334 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
18335 //
18336 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
18337 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
18338 //
18339 // using
18340 //
18341 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
18342 // = ( d) * 2^-e + ( r)
18343 //
18344 // or
18345 // 10^m * p2 * 2^e = d + r * 2^e
18346 //
18347 // i.e.
18348 //
18349 // M+ = buffer + p2 * 2^e
18350 // = buffer + 10^-m * (d + r * 2^e)
18351 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
18352 //
18353 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
18354
18355 JSON_ASSERT(p2 > delta);
18356
18357 int m = 0;
18358 for (;;)
18359 {
18360 // Invariant:
18361 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
18362 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
18363 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
18364 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
18365 //
18366 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
18367 p2 *= 10;
18368 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
18369 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
18370 //
18371 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
18372 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
18373 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
18374 //
18375 JSON_ASSERT(d <= 9);
18376 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18377 //
18378 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
18379 //
18380 p2 = r;
18381 m++;
18382 //
18383 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
18384 // Invariant restored.
18385
18386 // Check if enough digits have been generated.
18387 //
18388 // 10^-m * p2 * 2^e <= delta * 2^e
18389 // p2 * 2^e <= 10^m * delta * 2^e
18390 // p2 <= 10^m * delta
18391 delta *= 10;
18392 dist *= 10;
18393 if (p2 <= delta)
18394 {
18395 break;
18396 }
18397 }
18398
18399 // V = buffer * 10^-m, with M- <= V <= M+.
18400
18401 decimal_exponent -= m;
18402
18403 // 1 ulp in the decimal representation is now 10^-m.
18404 // Since delta and dist are now scaled by 10^m, we need to do the
18405 // same with ulp in order to keep the units in sync.
18406 //
18407 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
18408 //
18409 const std::uint64_t ten_m = one.f;
18410 grisu2_round(buffer, length, dist, delta, p2, ten_m);
18411
18412 // By construction this algorithm generates the shortest possible decimal
18413 // number (Loitsch, Theorem 6.2) which rounds back to w.
18414 // For an input number of precision p, at least
18415 //
18416 // N = 1 + ceil(p * log_10(2))
18417 //
18418 // decimal digits are sufficient to identify all binary floating-point
18419 // numbers (Matula, "In-and-Out conversions").
18420 // This implies that the algorithm does not produce more than N decimal
18421 // digits.
18422 //
18423 // N = 17 for p = 53 (IEEE double precision)
18424 // N = 9 for p = 24 (IEEE single precision)
18425}
18426
18433inline void grisu2(char* buf, int& len, int& decimal_exponent,
18434 diyfp m_minus, diyfp v, diyfp m_plus)
18435{
18436 JSON_ASSERT(m_plus.e == m_minus.e);
18437 JSON_ASSERT(m_plus.e == v.e);
18438
18439 // --------(-----------------------+-----------------------)-------- (A)
18440 // m- v m+
18441 //
18442 // --------------------(-----------+-----------------------)-------- (B)
18443 // m- v m+
18444 //
18445 // First scale v (and m- and m+) such that the exponent is in the range
18446 // [alpha, gamma].
18447
18448 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
18449
18450 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
18451
18452 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
18453 const diyfp w = diyfp::mul(v, c_minus_k);
18454 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
18455 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
18456
18457 // ----(---+---)---------------(---+---)---------------(---+---)----
18458 // w- w w+
18459 // = c*m- = c*v = c*m+
18460 //
18461 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
18462 // w+ are now off by a small amount.
18463 // In fact:
18464 //
18465 // w - v * 10^k < 1 ulp
18466 //
18467 // To account for this inaccuracy, add resp. subtract 1 ulp.
18468 //
18469 // --------+---[---------------(---+---)---------------]---+--------
18470 // w- M- w M+ w+
18471 //
18472 // Now any number in [M-, M+] (bounds included) will round to w when input,
18473 // regardless of how the input rounding algorithm breaks ties.
18474 //
18475 // And digit_gen generates the shortest possible such number in [M-, M+].
18476 // Note that this does not mean that Grisu2 always generates the shortest
18477 // possible number in the interval (m-, m+).
18478 const diyfp M_minus(w_minus.f + 1, w_minus.e);
18479 const diyfp M_plus (w_plus.f - 1, w_plus.e );
18480
18481 decimal_exponent = -cached.k; // = -(-k) = k
18482
18483 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
18484}
18485
18491template<typename FloatType>
18493void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
18494{
18495 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
18496 "internal error: not enough precision");
18497
18498 JSON_ASSERT(std::isfinite(value));
18499 JSON_ASSERT(value > 0);
18500
18501 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
18502 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
18503 // decimal representations are not exactly "short".
18504 //
18505 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
18506 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
18507 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
18508 // does.
18509 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
18510 // representation using the corresponding std::from_chars function recovers value exactly". That
18511 // indicates that single precision floating-point numbers should be recovered using
18512 // 'std::strtof'.
18513 //
18514 // NB: If the neighbors are computed for single-precision numbers, there is a single float
18515 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
18516 // value is off by 1 ulp.
18517#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
18518 const boundaries w = compute_boundaries(static_cast<double>(value));
18519#else
18521#endif
18522
18523 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
18524}
18525
18533inline char* append_exponent(char* buf, int e)
18534{
18535 JSON_ASSERT(e > -1000);
18536 JSON_ASSERT(e < 1000);
18537
18538 if (e < 0)
18539 {
18540 e = -e;
18541 *buf++ = '-';
18542 }
18543 else
18544 {
18545 *buf++ = '+';
18546 }
18547
18548 auto k = static_cast<std::uint32_t>(e);
18549 if (k < 10)
18550 {
18551 // Always print at least two digits in the exponent.
18552 // This is for compatibility with printf("%g").
18553 *buf++ = '0';
18554 *buf++ = static_cast<char>('0' + k);
18555 }
18556 else if (k < 100)
18557 {
18558 *buf++ = static_cast<char>('0' + (k / 10));
18559 k %= 10;
18560 *buf++ = static_cast<char>('0' + k);
18561 }
18562 else
18563 {
18564 *buf++ = static_cast<char>('0' + (k / 100));
18565 k %= 100;
18566 *buf++ = static_cast<char>('0' + (k / 10));
18567 k %= 10;
18568 *buf++ = static_cast<char>('0' + k);
18569 }
18570
18571 return buf;
18572}
18573
18585inline char* format_buffer(char* buf, int len, int decimal_exponent,
18586 int min_exp, int max_exp)
18587{
18588 JSON_ASSERT(min_exp < 0);
18589 JSON_ASSERT(max_exp > 0);
18590
18591 const int k = len;
18592 const int n = len + decimal_exponent;
18593
18594 // v = buf * 10^(n-k)
18595 // k is the length of the buffer (number of decimal digits)
18596 // n is the position of the decimal point relative to the start of the buffer.
18597
18598 if (k <= n && n <= max_exp)
18599 {
18600 // digits[000]
18601 // len <= max_exp + 2
18602
18603 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
18604 // Make it look like a floating-point number (#362, #378)
18605 buf[n + 0] = '.';
18606 buf[n + 1] = '0';
18607 return buf + (static_cast<size_t>(n) + 2);
18608 }
18609
18610 if (0 < n && n <= max_exp)
18611 {
18612 // dig.its
18613 // len <= max_digits10 + 1
18614
18615 JSON_ASSERT(k > n);
18616
18617 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
18618 buf[n] = '.';
18619 return buf + (static_cast<size_t>(k) + 1U);
18620 }
18621
18622 if (min_exp < n && n <= 0)
18623 {
18624 // 0.[000]digits
18625 // len <= 2 + (-min_exp - 1) + max_digits10
18626
18627 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
18628 buf[0] = '0';
18629 buf[1] = '.';
18630 std::memset(buf + 2, '0', static_cast<size_t>(-n));
18631 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
18632 }
18633
18634 if (k == 1)
18635 {
18636 // dE+123
18637 // len <= 1 + 5
18638
18639 buf += 1;
18640 }
18641 else
18642 {
18643 // d.igitsE+123
18644 // len <= max_digits10 + 1 + 5
18645
18646 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
18647 buf[1] = '.';
18648 buf += 1 + static_cast<size_t>(k);
18649 }
18650
18651 *buf++ = 'e';
18652 return append_exponent(buf, n - 1);
18653}
18654
18655} // namespace dtoa_impl
18656
18667template<typename FloatType>
18670char* to_chars(char* first, const char* last, FloatType value)
18671{
18672 static_cast<void>(last); // maybe unused - fix warning
18673 JSON_ASSERT(std::isfinite(value));
18674
18675 // Use signbit(value) instead of (value < 0) since signbit works for -0.
18676 if (std::signbit(value))
18677 {
18678 value = -value;
18679 *first++ = '-';
18680 }
18681
18682#ifdef __GNUC__
18683#pragma GCC diagnostic push
18684#pragma GCC diagnostic ignored "-Wfloat-equal"
18685#endif
18686 if (value == 0) // +-0
18687 {
18688 *first++ = '0';
18689 // Make it look like a floating-point number (#362, #378)
18690 *first++ = '.';
18691 *first++ = '0';
18692 return first;
18693 }
18694#ifdef __GNUC__
18695#pragma GCC diagnostic pop
18696#endif
18697
18698 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18699
18700 // Compute v = buffer * 10^decimal_exponent.
18701 // The decimal digits are stored in the buffer, which needs to be interpreted
18702 // as an unsigned decimal integer.
18703 // len is the length of the buffer, i.e. the number of decimal digits.
18704 int len = 0;
18705 int decimal_exponent = 0;
18706 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18707
18708 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18709
18710 // Format the buffer like printf("%.*g", prec, value)
18711 constexpr int kMinExp = -4;
18712 // Use digits10 here to increase compatibility with version 2.
18713 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18714
18715 JSON_ASSERT(last - first >= kMaxExp + 2);
18716 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18717 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18718
18719 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18720}
18721
18722} // namespace detail
18724
18725// #include <nlohmann/detail/exceptions.hpp>
18726
18727// #include <nlohmann/detail/macro_scope.hpp>
18728
18729// #include <nlohmann/detail/meta/cpp_future.hpp>
18730
18731// #include <nlohmann/detail/output/binary_writer.hpp>
18732
18733// #include <nlohmann/detail/output/output_adapters.hpp>
18734
18735// #include <nlohmann/detail/string_concat.hpp>
18736
18737// #include <nlohmann/detail/value_t.hpp>
18738
18739
18741namespace detail
18742{
18743
18745// serialization //
18747
18750{
18754};
18755
18756template<typename BasicJsonType>
18758{
18759 using string_t = typename BasicJsonType::string_t;
18760 using number_float_t = typename BasicJsonType::number_float_t;
18761 using number_integer_t = typename BasicJsonType::number_integer_t;
18762 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18763 using binary_char_t = typename BasicJsonType::binary_t::value_type;
18764 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18765 static constexpr std::uint8_t UTF8_REJECT = 1;
18766
18767 public:
18775 : o(std::move(s))
18776 , loc(std::localeconv())
18777 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18778 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18779 , indent_char(ichar)
18781 , error_handler(error_handler_)
18782 {}
18783
18784 // delete because of pointer members
18785 serializer(const serializer&) = delete;
18789 ~serializer() = default;
18790
18813 void dump(const BasicJsonType& val,
18814 const bool pretty_print,
18815 const bool ensure_ascii,
18816 const unsigned int indent_step,
18817 const unsigned int current_indent = 0)
18818 {
18819 switch (val.m_data.m_type)
18820 {
18821 case value_t::object:
18822 {
18823 if (val.m_data.m_value.object->empty())
18824 {
18825 o->write_characters("{}", 2);
18826 return;
18827 }
18828
18829 if (pretty_print)
18830 {
18831 o->write_characters("{\n", 2);
18832
18833 // variable to hold indentation for recursive calls
18834 const auto new_indent = current_indent + indent_step;
18835 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18836 {
18837 indent_string.resize(indent_string.size() * 2, ' ');
18838 }
18839
18840 // first n-1 elements
18841 auto i = val.m_data.m_value.object->cbegin();
18842 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18843 {
18844 o->write_characters(indent_string.c_str(), new_indent);
18845 o->write_character('\"');
18846 dump_escaped(i->first, ensure_ascii);
18847 o->write_characters("\": ", 3);
18848 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18849 o->write_characters(",\n", 2);
18850 }
18851
18852 // last element
18853 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18854 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18855 o->write_characters(indent_string.c_str(), new_indent);
18856 o->write_character('\"');
18857 dump_escaped(i->first, ensure_ascii);
18858 o->write_characters("\": ", 3);
18859 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18860
18861 o->write_character('\n');
18862 o->write_characters(indent_string.c_str(), current_indent);
18863 o->write_character('}');
18864 }
18865 else
18866 {
18867 o->write_character('{');
18868
18869 // first n-1 elements
18870 auto i = val.m_data.m_value.object->cbegin();
18871 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18872 {
18873 o->write_character('\"');
18874 dump_escaped(i->first, ensure_ascii);
18875 o->write_characters("\":", 2);
18876 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18877 o->write_character(',');
18878 }
18879
18880 // last element
18881 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18882 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18883 o->write_character('\"');
18884 dump_escaped(i->first, ensure_ascii);
18885 o->write_characters("\":", 2);
18886 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18887
18888 o->write_character('}');
18889 }
18890
18891 return;
18892 }
18893
18894 case value_t::array:
18895 {
18896 if (val.m_data.m_value.array->empty())
18897 {
18898 o->write_characters("[]", 2);
18899 return;
18900 }
18901
18902 if (pretty_print)
18903 {
18904 o->write_characters("[\n", 2);
18905
18906 // variable to hold indentation for recursive calls
18907 const auto new_indent = current_indent + indent_step;
18908 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18909 {
18910 indent_string.resize(indent_string.size() * 2, ' ');
18911 }
18912
18913 // first n-1 elements
18914 for (auto i = val.m_data.m_value.array->cbegin();
18915 i != val.m_data.m_value.array->cend() - 1; ++i)
18916 {
18917 o->write_characters(indent_string.c_str(), new_indent);
18918 dump(*i, true, ensure_ascii, indent_step, new_indent);
18919 o->write_characters(",\n", 2);
18920 }
18921
18922 // last element
18923 JSON_ASSERT(!val.m_data.m_value.array->empty());
18924 o->write_characters(indent_string.c_str(), new_indent);
18925 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18926
18927 o->write_character('\n');
18928 o->write_characters(indent_string.c_str(), current_indent);
18929 o->write_character(']');
18930 }
18931 else
18932 {
18933 o->write_character('[');
18934
18935 // first n-1 elements
18936 for (auto i = val.m_data.m_value.array->cbegin();
18937 i != val.m_data.m_value.array->cend() - 1; ++i)
18938 {
18939 dump(*i, false, ensure_ascii, indent_step, current_indent);
18940 o->write_character(',');
18941 }
18942
18943 // last element
18944 JSON_ASSERT(!val.m_data.m_value.array->empty());
18945 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
18946
18947 o->write_character(']');
18948 }
18949
18950 return;
18951 }
18952
18953 case value_t::string:
18954 {
18955 o->write_character('\"');
18956 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
18957 o->write_character('\"');
18958 return;
18959 }
18960
18961 case value_t::binary:
18962 {
18963 if (pretty_print)
18964 {
18965 o->write_characters("{\n", 2);
18966
18967 // variable to hold indentation for recursive calls
18968 const auto new_indent = current_indent + indent_step;
18969 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18970 {
18971 indent_string.resize(indent_string.size() * 2, ' ');
18972 }
18973
18974 o->write_characters(indent_string.c_str(), new_indent);
18975
18976 o->write_characters("\"bytes\": [", 10);
18977
18978 if (!val.m_data.m_value.binary->empty())
18979 {
18980 for (auto i = val.m_data.m_value.binary->cbegin();
18981 i != val.m_data.m_value.binary->cend() - 1; ++i)
18982 {
18983 dump_integer(*i);
18984 o->write_characters(", ", 2);
18985 }
18986 dump_integer(val.m_data.m_value.binary->back());
18987 }
18988
18989 o->write_characters("],\n", 3);
18990 o->write_characters(indent_string.c_str(), new_indent);
18991
18992 o->write_characters("\"subtype\": ", 11);
18993 if (val.m_data.m_value.binary->has_subtype())
18994 {
18995 dump_integer(val.m_data.m_value.binary->subtype());
18996 }
18997 else
18998 {
18999 o->write_characters("null", 4);
19000 }
19001 o->write_character('\n');
19002 o->write_characters(indent_string.c_str(), current_indent);
19003 o->write_character('}');
19004 }
19005 else
19006 {
19007 o->write_characters("{\"bytes\":[", 10);
19008
19009 if (!val.m_data.m_value.binary->empty())
19010 {
19011 for (auto i = val.m_data.m_value.binary->cbegin();
19012 i != val.m_data.m_value.binary->cend() - 1; ++i)
19013 {
19014 dump_integer(*i);
19015 o->write_character(',');
19016 }
19017 dump_integer(val.m_data.m_value.binary->back());
19018 }
19019
19020 o->write_characters("],\"subtype\":", 12);
19021 if (val.m_data.m_value.binary->has_subtype())
19022 {
19023 dump_integer(val.m_data.m_value.binary->subtype());
19024 o->write_character('}');
19025 }
19026 else
19027 {
19028 o->write_characters("null}", 5);
19029 }
19030 }
19031 return;
19032 }
19033
19034 case value_t::boolean:
19035 {
19036 if (val.m_data.m_value.boolean)
19037 {
19038 o->write_characters("true", 4);
19039 }
19040 else
19041 {
19042 o->write_characters("false", 5);
19043 }
19044 return;
19045 }
19046
19048 {
19049 dump_integer(val.m_data.m_value.number_integer);
19050 return;
19051 }
19052
19054 {
19055 dump_integer(val.m_data.m_value.number_unsigned);
19056 return;
19057 }
19058
19060 {
19061 dump_float(val.m_data.m_value.number_float);
19062 return;
19063 }
19064
19065 case value_t::discarded:
19066 {
19067 o->write_characters("<discarded>", 11);
19068 return;
19069 }
19070
19071 case value_t::null:
19072 {
19073 o->write_characters("null", 4);
19074 return;
19075 }
19076
19077 default: // LCOV_EXCL_LINE
19078 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19079 }
19080 }
19081
19097 void dump_escaped(const string_t& s, const bool ensure_ascii)
19098 {
19099 std::uint32_t codepoint{};
19100 std::uint8_t state = UTF8_ACCEPT;
19101 std::size_t bytes = 0; // number of bytes written to string_buffer
19102
19103 // number of bytes written at the point of the last valid byte
19105 std::size_t undumped_chars = 0;
19106
19107 for (std::size_t i = 0; i < s.size(); ++i)
19108 {
19109 const auto byte = static_cast<std::uint8_t>(s[i]);
19110
19111 switch (decode(state, codepoint, byte))
19112 {
19113 case UTF8_ACCEPT: // decode found a new code point
19114 {
19115 switch (codepoint)
19116 {
19117 case 0x08: // backspace
19118 {
19119 string_buffer[bytes++] = '\\';
19120 string_buffer[bytes++] = 'b';
19121 break;
19122 }
19123
19124 case 0x09: // horizontal tab
19125 {
19126 string_buffer[bytes++] = '\\';
19127 string_buffer[bytes++] = 't';
19128 break;
19129 }
19130
19131 case 0x0A: // newline
19132 {
19133 string_buffer[bytes++] = '\\';
19134 string_buffer[bytes++] = 'n';
19135 break;
19136 }
19137
19138 case 0x0C: // formfeed
19139 {
19140 string_buffer[bytes++] = '\\';
19141 string_buffer[bytes++] = 'f';
19142 break;
19143 }
19144
19145 case 0x0D: // carriage return
19146 {
19147 string_buffer[bytes++] = '\\';
19148 string_buffer[bytes++] = 'r';
19149 break;
19150 }
19151
19152 case 0x22: // quotation mark
19153 {
19154 string_buffer[bytes++] = '\\';
19155 string_buffer[bytes++] = '\"';
19156 break;
19157 }
19158
19159 case 0x5C: // reverse solidus
19160 {
19161 string_buffer[bytes++] = '\\';
19162 string_buffer[bytes++] = '\\';
19163 break;
19164 }
19165
19166 default:
19167 {
19168 // escape control characters (0x00..0x1F) or, if
19169 // ensure_ascii parameter is used, non-ASCII characters
19170 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
19171 {
19172 if (codepoint <= 0xFFFF)
19173 {
19174 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19175 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
19176 static_cast<std::uint16_t>(codepoint)));
19177 bytes += 6;
19178 }
19179 else
19180 {
19181 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19182 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
19183 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
19184 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
19185 bytes += 12;
19186 }
19187 }
19188 else
19189 {
19190 // copy byte to buffer (all previous bytes
19191 // been copied have in default case above)
19192 string_buffer[bytes++] = s[i];
19193 }
19194 break;
19195 }
19196 }
19197
19198 // write buffer and reset index; there must be 13 bytes
19199 // left, as this is the maximal number of bytes to be
19200 // written ("\uxxxx\uxxxx\0") for one code point
19201 if (string_buffer.size() - bytes < 13)
19202 {
19203 o->write_characters(string_buffer.data(), bytes);
19204 bytes = 0;
19205 }
19206
19207 // remember the byte position of this accept
19209 undumped_chars = 0;
19210 break;
19211 }
19212
19213 case UTF8_REJECT: // decode found invalid UTF-8 byte
19214 {
19215 switch (error_handler)
19216 {
19218 {
19219 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
19220 }
19221
19224 {
19225 // in case we saw this character the first time, we
19226 // would like to read it again, because the byte
19227 // may be OK for itself, but just not OK for the
19228 // previous sequence
19229 if (undumped_chars > 0)
19230 {
19231 --i;
19232 }
19233
19234 // reset length buffer to the last accepted index;
19235 // thus removing/ignoring the invalid characters
19237
19239 {
19240 // add a replacement character
19241 if (ensure_ascii)
19242 {
19243 string_buffer[bytes++] = '\\';
19244 string_buffer[bytes++] = 'u';
19245 string_buffer[bytes++] = 'f';
19246 string_buffer[bytes++] = 'f';
19247 string_buffer[bytes++] = 'f';
19248 string_buffer[bytes++] = 'd';
19249 }
19250 else
19251 {
19255 }
19256
19257 // write buffer and reset index; there must be 13 bytes
19258 // left, as this is the maximal number of bytes to be
19259 // written ("\uxxxx\uxxxx\0") for one code point
19260 if (string_buffer.size() - bytes < 13)
19261 {
19262 o->write_characters(string_buffer.data(), bytes);
19263 bytes = 0;
19264 }
19265
19267 }
19268
19269 undumped_chars = 0;
19270
19271 // continue processing the string
19273 break;
19274 }
19275
19276 default: // LCOV_EXCL_LINE
19277 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19278 }
19279 break;
19280 }
19281
19282 default: // decode found yet incomplete multi-byte code point
19283 {
19284 if (!ensure_ascii)
19285 {
19286 // code point will not be escaped - copy byte to buffer
19287 string_buffer[bytes++] = s[i];
19288 }
19290 break;
19291 }
19292 }
19293 }
19294
19295 // we finished processing the string
19297 {
19298 // write buffer
19299 if (bytes > 0)
19300 {
19301 o->write_characters(string_buffer.data(), bytes);
19302 }
19303 }
19304 else
19305 {
19306 // we finish reading, but do not accept: string was incomplete
19307 switch (error_handler)
19308 {
19310 {
19311 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));
19312 }
19313
19315 {
19316 // write all accepted bytes
19317 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19318 break;
19319 }
19320
19322 {
19323 // write all accepted bytes
19324 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19325 // add a replacement character
19326 if (ensure_ascii)
19327 {
19328 o->write_characters("\\ufffd", 6);
19329 }
19330 else
19331 {
19332 o->write_characters("\xEF\xBF\xBD", 3);
19333 }
19334 break;
19335 }
19336
19337 default: // LCOV_EXCL_LINE
19338 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19339 }
19340 }
19341 }
19342
19343 private:
19352 unsigned int count_digits(number_unsigned_t x) noexcept
19353 {
19354 unsigned int n_digits = 1;
19355 for (;;)
19356 {
19357 if (x < 10)
19358 {
19359 return n_digits;
19360 }
19361 if (x < 100)
19362 {
19363 return n_digits + 1;
19364 }
19365 if (x < 1000)
19366 {
19367 return n_digits + 2;
19368 }
19369 if (x < 10000)
19370 {
19371 return n_digits + 3;
19372 }
19373 x = x / 10000u;
19374 n_digits += 4;
19375 }
19376 }
19377
19383 static std::string hex_bytes(std::uint8_t byte)
19384 {
19385 std::string result = "FF";
19386 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
19387 result[0] = nibble_to_hex[byte / 16];
19388 result[1] = nibble_to_hex[byte % 16];
19389 return result;
19390 }
19391
19392 // templates to avoid warnings about useless casts
19393 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
19394 bool is_negative_number(NumberType x)
19395 {
19396 return x < 0;
19397 }
19398
19399 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
19400 bool is_negative_number(NumberType /*unused*/)
19401 {
19402 return false;
19403 }
19404
19414 template < typename NumberType, detail::enable_if_t <
19415 std::is_integral<NumberType>::value ||
19416 std::is_same<NumberType, number_unsigned_t>::value ||
19417 std::is_same<NumberType, number_integer_t>::value ||
19418 std::is_same<NumberType, binary_char_t>::value,
19419 int > = 0 >
19420 void dump_integer(NumberType x)
19421 {
19422 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
19423 {
19424 {
19425 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
19426 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
19427 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
19428 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
19429 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
19430 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
19431 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
19432 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
19433 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
19434 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
19435 }
19436 };
19437
19438 // special case for "0"
19439 if (x == 0)
19440 {
19441 o->write_character('0');
19442 return;
19443 }
19444
19445 // use a pointer to fill the buffer
19446 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19447
19448 number_unsigned_t abs_value;
19449
19450 unsigned int n_chars{};
19451
19452 if (is_negative_number(x))
19453 {
19454 *buffer_ptr = '-';
19455 abs_value = remove_sign(static_cast<number_integer_t>(x));
19456
19457 // account one more byte for the minus sign
19458 n_chars = 1 + count_digits(abs_value);
19459 }
19460 else
19461 {
19462 abs_value = static_cast<number_unsigned_t>(x);
19463 n_chars = count_digits(abs_value);
19464 }
19465
19466 // spare 1 byte for '\0'
19467 JSON_ASSERT(n_chars < number_buffer.size() - 1);
19468
19469 // jump to the end to generate the string from backward,
19470 // so we later avoid reversing the result
19471 buffer_ptr += n_chars;
19472
19473 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
19474 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
19475 while (abs_value >= 100)
19476 {
19477 const auto digits_index = static_cast<unsigned>((abs_value % 100));
19478 abs_value /= 100;
19479 *(--buffer_ptr) = digits_to_99[digits_index][1];
19480 *(--buffer_ptr) = digits_to_99[digits_index][0];
19481 }
19482
19483 if (abs_value >= 10)
19484 {
19485 const auto digits_index = static_cast<unsigned>(abs_value);
19486 *(--buffer_ptr) = digits_to_99[digits_index][1];
19487 *(--buffer_ptr) = digits_to_99[digits_index][0];
19488 }
19489 else
19490 {
19491 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
19492 }
19493
19494 o->write_characters(number_buffer.data(), n_chars);
19495 }
19496
19505 void dump_float(number_float_t x)
19506 {
19507 // NaN / inf
19508 if (!std::isfinite(x))
19509 {
19510 o->write_characters("null", 4);
19511 return;
19512 }
19513
19514 // If number_float_t is an IEEE-754 single or double precision number,
19515 // use the Grisu2 algorithm to produce short numbers which are
19516 // guaranteed to round-trip, using strtof and strtod, resp.
19517 //
19518 // NB: The test below works if <long double> == <double>.
19519 static constexpr bool is_ieee_single_or_double
19520 = (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) ||
19521 (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);
19522
19523 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
19524 }
19525
19526 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
19527 {
19528 auto* begin = number_buffer.data();
19529 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
19530
19531 o->write_characters(begin, static_cast<size_t>(end - begin));
19532 }
19533
19534 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
19535 {
19536 // get number of digits for a float -> text -> float round-trip
19537 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
19538
19539 // the actual conversion
19540 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19541 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
19542
19543 // negative value indicates an error
19544 JSON_ASSERT(len > 0);
19545 // check if buffer was large enough
19546 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
19547
19548 // erase thousands separator
19549 if (thousands_sep != '\0')
19550 {
19551 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
19552 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
19553 std::fill(end, number_buffer.end(), '\0');
19554 JSON_ASSERT((end - number_buffer.begin()) <= len);
19555 len = (end - number_buffer.begin());
19556 }
19557
19558 // convert decimal point to '.'
19559 if (decimal_point != '\0' && decimal_point != '.')
19560 {
19561 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
19562 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
19563 if (dec_pos != number_buffer.end())
19564 {
19565 *dec_pos = '.';
19566 }
19567 }
19568
19569 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
19570
19571 // determine if we need to append ".0"
19572 const bool value_is_int_like =
19573 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
19574 [](char c)
19575 {
19576 return c == '.' || c == 'e';
19577 });
19578
19579 if (value_is_int_like)
19580 {
19581 o->write_characters(".0", 2);
19582 }
19583 }
19584
19606 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
19607 {
19608 static const std::array<std::uint8_t, 400> utf8d =
19609 {
19610 {
19611 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
19612 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
19613 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
19614 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
19615 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
19616 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
19617 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
19618 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
19619 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
19620 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
19621 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
19622 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
19623 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
19624 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
19625 }
19626 };
19627
19628 JSON_ASSERT(byte < utf8d.size());
19629 const std::uint8_t type = utf8d[byte];
19630
19631 codep = (state != UTF8_ACCEPT)
19632 ? (byte & 0x3fu) | (codep << 6u)
19633 : (0xFFu >> type) & (byte);
19634
19635 const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
19636 JSON_ASSERT(index < utf8d.size());
19637 state = utf8d[index];
19638 return state;
19639 }
19640
19641 /*
19642 * Overload to make the compiler happy while it is instantiating
19643 * dump_integer for number_unsigned_t.
19644 * Must never be called.
19645 */
19646 number_unsigned_t remove_sign(number_unsigned_t x)
19647 {
19648 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19649 return x; // LCOV_EXCL_LINE
19650 }
19651
19652 /*
19653 * Helper function for dump_integer
19654 *
19655 * This function takes a negative signed integer and returns its absolute
19656 * value as unsigned integer. The plus/minus shuffling is necessary as we can
19657 * not directly remove the sign of an arbitrary signed integer as the
19658 * absolute values of INT_MIN and INT_MAX are usually not the same. See
19659 * #1708 for details.
19660 */
19661 number_unsigned_t remove_sign(number_integer_t x) noexcept
19662 {
19663 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
19664 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
19665 }
19666
19667 private:
19669 output_adapter_t<char> o = nullptr;
19670
19672 std::array<char, 64> number_buffer{{}};
19673
19675 const std::lconv* loc = nullptr;
19677 const char thousands_sep = '\0';
19679 const char decimal_point = '\0';
19680
19682 std::array<char, 512> string_buffer{{}};
19683
19685 const char indent_char;
19688
19691};
19692
19693} // namespace detail
19695
19696// #include <nlohmann/detail/value_t.hpp>
19697
19698// #include <nlohmann/json_fwd.hpp>
19699
19700// #include <nlohmann/ordered_map.hpp>
19701// __ _____ _____ _____
19702// __| | __| | | | JSON for Modern C++
19703// | | |__ | | | | | | version 3.11.3
19704// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19705//
19706// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
19707// SPDX-License-Identifier: MIT
19708
19709
19710
19711#include <functional> // equal_to, less
19712#include <initializer_list> // initializer_list
19713#include <iterator> // input_iterator_tag, iterator_traits
19714#include <memory> // allocator
19715#include <stdexcept> // for out_of_range
19716#include <type_traits> // enable_if, is_convertible
19717#include <utility> // pair
19718#include <vector> // vector
19719
19720// #include <nlohmann/detail/macro_scope.hpp>
19721
19722// #include <nlohmann/detail/meta/type_traits.hpp>
19723
19724
19726
19729template <class Key, class T, class IgnoredLess = std::less<Key>,
19730 class Allocator = std::allocator<std::pair<const Key, T>>>
19731 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19732{
19733 using key_type = Key;
19734 using mapped_type = T;
19735 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19736 using iterator = typename Container::iterator;
19737 using const_iterator = typename Container::const_iterator;
19738 using size_type = typename Container::size_type;
19739 using value_type = typename Container::value_type;
19740#ifdef JSON_HAS_CPP_14
19741 using key_compare = std::equal_to<>;
19742#else
19743 using key_compare = std::equal_to<Key>;
19744#endif
19745
19746 // Explicit constructors instead of `using Container::Container`
19747 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19748 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19749 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19750 template <class It>
19751 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19752 : Container{first, last, alloc} {}
19753 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19754 : Container{init, alloc} {}
19755
19756 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19757 {
19758 for (auto it = this->begin(); it != this->end(); ++it)
19759 {
19760 if (m_compare(it->first, key))
19761 {
19762 return {it, false};
19763 }
19764 }
19765 Container::emplace_back(key, std::forward<T>(t));
19766 return {std::prev(this->end()), true};
19767 }
19768
19769 template<class KeyType, detail::enable_if_t<
19771 std::pair<iterator, bool> emplace(KeyType && key, T && t)
19772 {
19773 for (auto it = this->begin(); it != this->end(); ++it)
19774 {
19775 if (m_compare(it->first, key))
19776 {
19777 return {it, false};
19778 }
19779 }
19780 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19781 return {std::prev(this->end()), true};
19782 }
19783
19784 T& operator[](const key_type& key)
19785 {
19786 return emplace(key, T{}).first->second;
19787 }
19788
19789 template<class KeyType, detail::enable_if_t<
19791 T & operator[](KeyType && key)
19792 {
19793 return emplace(std::forward<KeyType>(key), T{}).first->second;
19794 }
19795
19796 const T& operator[](const key_type& key) const
19797 {
19798 return at(key);
19799 }
19800
19801 template<class KeyType, detail::enable_if_t<
19803 const T & operator[](KeyType && key) const
19804 {
19805 return at(std::forward<KeyType>(key));
19806 }
19807
19808 T& at(const key_type& key)
19809 {
19810 for (auto it = this->begin(); it != this->end(); ++it)
19811 {
19812 if (m_compare(it->first, key))
19813 {
19814 return it->second;
19815 }
19816 }
19817
19818 JSON_THROW(std::out_of_range("key not found"));
19819 }
19820
19821 template<class KeyType, detail::enable_if_t<
19823 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19824 {
19825 for (auto it = this->begin(); it != this->end(); ++it)
19826 {
19827 if (m_compare(it->first, key))
19828 {
19829 return it->second;
19830 }
19831 }
19832
19833 JSON_THROW(std::out_of_range("key not found"));
19834 }
19835
19836 const T& at(const key_type& key) const
19837 {
19838 for (auto it = this->begin(); it != this->end(); ++it)
19839 {
19840 if (m_compare(it->first, key))
19841 {
19842 return it->second;
19843 }
19844 }
19845
19846 JSON_THROW(std::out_of_range("key not found"));
19847 }
19848
19849 template<class KeyType, detail::enable_if_t<
19851 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19852 {
19853 for (auto it = this->begin(); it != this->end(); ++it)
19854 {
19855 if (m_compare(it->first, key))
19856 {
19857 return it->second;
19858 }
19859 }
19860
19861 JSON_THROW(std::out_of_range("key not found"));
19862 }
19863
19865 {
19866 for (auto it = this->begin(); it != this->end(); ++it)
19867 {
19868 if (m_compare(it->first, key))
19869 {
19870 // Since we cannot move const Keys, re-construct them in place
19871 for (auto next = it; ++next != this->end(); ++it)
19872 {
19873 it->~value_type(); // Destroy but keep allocation
19874 new (&*it) value_type{std::move(*next)};
19875 }
19876 Container::pop_back();
19877 return 1;
19878 }
19879 }
19880 return 0;
19881 }
19882
19883 template<class KeyType, detail::enable_if_t<
19885 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19886 {
19887 for (auto it = this->begin(); it != this->end(); ++it)
19888 {
19889 if (m_compare(it->first, key))
19890 {
19891 // Since we cannot move const Keys, re-construct them in place
19892 for (auto next = it; ++next != this->end(); ++it)
19893 {
19894 it->~value_type(); // Destroy but keep allocation
19895 new (&*it) value_type{std::move(*next)};
19896 }
19897 Container::pop_back();
19898 return 1;
19899 }
19900 }
19901 return 0;
19902 }
19903
19905 {
19906 return erase(pos, std::next(pos));
19907 }
19908
19910 {
19911 if (first == last)
19912 {
19913 return first;
19914 }
19915
19916 const auto elements_affected = std::distance(first, last);
19917 const auto offset = std::distance(Container::begin(), first);
19918
19919 // This is the start situation. We need to delete elements_affected
19920 // elements (3 in this example: e, f, g), and need to return an
19921 // iterator past the last deleted element (h in this example).
19922 // Note that offset is the distance from the start of the vector
19923 // to first. We will need this later.
19924
19925 // [ a, b, c, d, e, f, g, h, i, j ]
19926 // ^ ^
19927 // first last
19928
19929 // Since we cannot move const Keys, we re-construct them in place.
19930 // We start at first and re-construct (viz. copy) the elements from
19931 // the back of the vector. Example for first iteration:
19932
19933 // ,--------.
19934 // v | destroy e and re-construct with h
19935 // [ a, b, c, d, e, f, g, h, i, j ]
19936 // ^ ^
19937 // it it + elements_affected
19938
19939 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19940 {
19941 it->~value_type(); // destroy but keep allocation
19942 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
19943 }
19944
19945 // [ a, b, c, d, h, i, j, h, i, j ]
19946 // ^ ^
19947 // first last
19948
19949 // remove the unneeded elements at the end of the vector
19950 Container::resize(this->size() - static_cast<size_type>(elements_affected));
19951
19952 // [ a, b, c, d, h, i, j ]
19953 // ^ ^
19954 // first last
19955
19956 // first is now pointing past the last deleted element, but we cannot
19957 // use this iterator, because it may have been invalidated by the
19958 // resize call. Instead, we can return begin() + offset.
19959 return Container::begin() + offset;
19960 }
19961
19962 size_type count(const key_type& key) const
19963 {
19964 for (auto it = this->begin(); it != this->end(); ++it)
19965 {
19966 if (m_compare(it->first, key))
19967 {
19968 return 1;
19969 }
19970 }
19971 return 0;
19972 }
19973
19974 template<class KeyType, detail::enable_if_t<
19976 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19977 {
19978 for (auto it = this->begin(); it != this->end(); ++it)
19979 {
19980 if (m_compare(it->first, key))
19981 {
19982 return 1;
19983 }
19984 }
19985 return 0;
19986 }
19987
19989 {
19990 for (auto it = this->begin(); it != this->end(); ++it)
19991 {
19992 if (m_compare(it->first, key))
19993 {
19994 return it;
19995 }
19996 }
19997 return Container::end();
19998 }
19999
20000 template<class KeyType, detail::enable_if_t<
20002 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
20003 {
20004 for (auto it = this->begin(); it != this->end(); ++it)
20005 {
20006 if (m_compare(it->first, key))
20007 {
20008 return it;
20009 }
20010 }
20011 return Container::end();
20012 }
20013
20014 const_iterator find(const key_type& key) const
20015 {
20016 for (auto it = this->begin(); it != this->end(); ++it)
20017 {
20018 if (m_compare(it->first, key))
20019 {
20020 return it;
20021 }
20022 }
20023 return Container::end();
20024 }
20025
20026 std::pair<iterator, bool> insert( value_type&& value )
20027 {
20028 return emplace(value.first, std::move(value.second));
20029 }
20030
20031 std::pair<iterator, bool> insert( const value_type& value )
20032 {
20033 for (auto it = this->begin(); it != this->end(); ++it)
20034 {
20035 if (m_compare(it->first, value.first))
20036 {
20037 return {it, false};
20038 }
20039 }
20040 Container::push_back(value);
20041 return {--this->end(), true};
20042 }
20043
20044 template<typename InputIt>
20045 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
20046 std::input_iterator_tag>::value>::type;
20047
20048 template<typename InputIt, typename = require_input_iter<InputIt>>
20049 void insert(InputIt first, InputIt last)
20050 {
20051 for (auto it = first; it != last; ++it)
20052 {
20053 insert(*it);
20054 }
20055 }
20056
20057private:
20059};
20060
20062
20063
20064#if defined(JSON_HAS_CPP_17)
20065 #if JSON_HAS_STATIC_RTTI
20066 #include <any>
20067 #endif
20068 #include <string_view>
20069#endif
20070
20077
20097class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
20098 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
20099{
20100 private:
20101 template<detail::value_t> friend struct detail::external_constructor;
20102
20103 template<typename>
20104 friend class ::nlohmann::json_pointer;
20105 // can be restored when json_pointer backwards compatibility is removed
20106 // friend ::nlohmann::json_pointer<StringType>;
20107
20108 template<typename BasicJsonType, typename InputType>
20109 friend class ::nlohmann::detail::parser;
20110 friend ::nlohmann::detail::serializer<basic_json>;
20111 template<typename BasicJsonType>
20112 friend class ::nlohmann::detail::iter_impl;
20113 template<typename BasicJsonType, typename CharType>
20114 friend class ::nlohmann::detail::binary_writer;
20115 template<typename BasicJsonType, typename InputType, typename SAX>
20116 friend class ::nlohmann::detail::binary_reader;
20117 template<typename BasicJsonType, typename InputAdapterType>
20118 friend class ::nlohmann::detail::json_sax_dom_parser;
20119 template<typename BasicJsonType, typename InputAdapterType>
20120 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
20121 friend class ::nlohmann::detail::exception;
20122
20125 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
20126
20128 // convenience aliases for types residing in namespace detail;
20129 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
20130
20131 template<typename InputAdapterType>
20132 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
20133 InputAdapterType adapter,
20135 const bool allow_exceptions = true,
20136 const bool ignore_comments = false
20137 )
20138 {
20139 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
20140 std::move(cb), allow_exceptions, ignore_comments);
20141 }
20142
20143 private:
20144 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
20145 template<typename BasicJsonType>
20146 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
20147 template<typename BasicJsonType>
20148 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
20149 template<typename Iterator>
20150 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
20151 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
20152
20153 template<typename CharType>
20154 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
20155
20156 template<typename InputType>
20157 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
20158 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
20159
20161 using serializer = ::nlohmann::detail::serializer<basic_json>;
20162
20163 public:
20166 using json_pointer = ::nlohmann::json_pointer<StringType>;
20167 template<typename T, typename SFINAE>
20168 using json_serializer = JSONSerializer<T, SFINAE>;
20176 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
20177
20181
20183 // exceptions //
20185
20189
20196
20198
20200 // container types //
20202
20207
20210
20215
20217 using difference_type = std::ptrdiff_t;
20219 using size_type = std::size_t;
20220
20222 using allocator_type = AllocatorType<basic_json>;
20223
20225 using pointer = typename std::allocator_traits<allocator_type>::pointer;
20227 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
20228
20237
20239
20243 {
20244 return allocator_type();
20245 }
20246
20251 {
20252 basic_json result;
20253
20254 result["copyright"] = "(C) 2013-2023 Niels Lohmann";
20255 result["name"] = "JSON for Modern C++";
20256 result["url"] = "https://github.com/nlohmann/json";
20257 result["version"]["string"] =
20258 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
20259 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
20260 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
20261 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
20262 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
20263 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
20264
20265#ifdef _WIN32
20266 result["platform"] = "win32";
20267#elif defined __linux__
20268 result["platform"] = "linux";
20269#elif defined __APPLE__
20270 result["platform"] = "apple";
20271#elif defined __unix__
20272 result["platform"] = "unix";
20273#else
20274 result["platform"] = "unknown";
20275#endif
20276
20277#if defined(__ICC) || defined(__INTEL_COMPILER)
20278 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
20279#elif defined(__clang__)
20280 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
20281#elif defined(__GNUC__) || defined(__GNUG__)
20282 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
20283 std::to_string(__GNUC__), '.',
20284 std::to_string(__GNUC_MINOR__), '.',
20285 std::to_string(__GNUC_PATCHLEVEL__))
20286 }
20287 };
20288#elif defined(__HP_cc) || defined(__HP_aCC)
20289 result["compiler"] = "hp"
20290#elif defined(__IBMCPP__)
20291 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
20292#elif defined(_MSC_VER)
20293 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
20294#elif defined(__PGI)
20295 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
20296#elif defined(__SUNPRO_CC)
20297 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
20298#else
20299 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
20300#endif
20301
20302#if defined(_MSVC_LANG)
20303 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
20304#elif defined(__cplusplus)
20305 result["compiler"]["c++"] = std::to_string(__cplusplus);
20306#else
20307 result["compiler"]["c++"] = "unknown";
20308#endif
20309 return result;
20310 }
20311
20313 // JSON value data types //
20315
20320
20325#if defined(JSON_HAS_CPP_14)
20326 // use of transparent comparator avoids unnecessary repeated construction of temporaries
20327 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
20328 using default_object_comparator_t = std::less<>;
20329#else
20330 using default_object_comparator_t = std::less<StringType>;
20331#endif
20332
20335 using object_t = ObjectType<StringType,
20336 basic_json,
20338 AllocatorType<std::pair<const StringType,
20339 basic_json>>>;
20340
20343 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
20344
20347 using string_t = StringType;
20348
20351 using boolean_t = BooleanType;
20352
20355 using number_integer_t = NumberIntegerType;
20356
20359 using number_unsigned_t = NumberUnsignedType;
20360
20363 using number_float_t = NumberFloatType;
20364
20367 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
20368
20372
20374
20375 private:
20376
20378 template<typename T, typename... Args>
20380 static T* create(Args&& ... args)
20381 {
20382 AllocatorType<T> alloc;
20383 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
20384
20385 auto deleter = [&](T * obj)
20386 {
20387 AllocatorTraits::deallocate(alloc, obj, 1);
20388 };
20389 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
20390 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
20391 JSON_ASSERT(obj != nullptr);
20392 return obj.release();
20393 }
20394
20396 // JSON value storage //
20398
20425 union json_value
20426 {
20443
20445 json_value() = default;
20447 json_value(boolean_t v) noexcept : boolean(v) {}
20456 {
20457 switch (t)
20458 {
20459 case value_t::object:
20460 {
20461 object = create<object_t>();
20462 break;
20463 }
20464
20465 case value_t::array:
20466 {
20468 break;
20469 }
20470
20471 case value_t::string:
20472 {
20473 string = create<string_t>("");
20474 break;
20475 }
20476
20477 case value_t::binary:
20478 {
20480 break;
20481 }
20482
20483 case value_t::boolean:
20484 {
20485 boolean = static_cast<boolean_t>(false);
20486 break;
20487 }
20488
20489 case value_t::number_integer:
20490 {
20491 number_integer = static_cast<number_integer_t>(0);
20492 break;
20493 }
20494
20495 case value_t::number_unsigned:
20496 {
20497 number_unsigned = static_cast<number_unsigned_t>(0);
20498 break;
20499 }
20500
20501 case value_t::number_float:
20502 {
20503 number_float = static_cast<number_float_t>(0.0);
20504 break;
20505 }
20506
20507 case value_t::null:
20508 {
20509 object = nullptr; // silence warning, see #821
20510 break;
20511 }
20512
20513 case value_t::discarded:
20514 default:
20515 {
20516 object = nullptr; // silence warning, see #821
20517 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
20518 {
20519 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE
20520 }
20521 break;
20522 }
20523 }
20524 }
20525
20528
20531
20534
20537
20540
20543
20545 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
20546
20548 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
20549
20552
20555
20557 {
20558 if (
20559 (t == value_t::object && object == nullptr) ||
20560 (t == value_t::array && array == nullptr) ||
20561 (t == value_t::string && string == nullptr) ||
20562 (t == value_t::binary && binary == nullptr)
20563 )
20564 {
20565 //not initialized (e.g. due to exception in the ctor)
20566 return;
20567 }
20568 if (t == value_t::array || t == value_t::object)
20569 {
20570 // flatten the current json_value to a heap-allocated stack
20571 std::vector<basic_json> stack;
20572
20573 // move the top-level items to stack
20574 if (t == value_t::array)
20575 {
20576 stack.reserve(array->size());
20577 std::move(array->begin(), array->end(), std::back_inserter(stack));
20578 }
20579 else
20580 {
20581 stack.reserve(object->size());
20582 for (auto&& it : *object)
20583 {
20584 stack.push_back(std::move(it.second));
20585 }
20586 }
20587
20588 while (!stack.empty())
20589 {
20590 // move the last item to local variable to be processed
20591 basic_json current_item(std::move(stack.back()));
20592 stack.pop_back();
20593
20594 // if current_item is array/object, move
20595 // its children to the stack to be processed later
20596 if (current_item.is_array())
20597 {
20598 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
20599
20600 current_item.m_data.m_value.array->clear();
20601 }
20602 else if (current_item.is_object())
20603 {
20604 for (auto&& it : *current_item.m_data.m_value.object)
20605 {
20606 stack.push_back(std::move(it.second));
20607 }
20608
20609 current_item.m_data.m_value.object->clear();
20610 }
20611
20612 // it's now safe that current_item get destructed
20613 // since it doesn't have any children
20614 }
20615 }
20616
20617 switch (t)
20618 {
20619 case value_t::object:
20620 {
20621 AllocatorType<object_t> alloc;
20622 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
20623 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
20624 break;
20625 }
20626
20627 case value_t::array:
20628 {
20629 AllocatorType<array_t> alloc;
20630 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
20631 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
20632 break;
20633 }
20634
20635 case value_t::string:
20636 {
20637 AllocatorType<string_t> alloc;
20638 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
20639 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
20640 break;
20641 }
20642
20643 case value_t::binary:
20644 {
20645 AllocatorType<binary_t> alloc;
20646 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
20647 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
20648 break;
20649 }
20650
20651 case value_t::null:
20652 case value_t::boolean:
20653 case value_t::number_integer:
20654 case value_t::number_unsigned:
20655 case value_t::number_float:
20656 case value_t::discarded:
20657 default:
20658 {
20659 break;
20660 }
20661 }
20662 }
20663 };
20664
20665 private:
20684 void assert_invariant(bool check_parents = true) const noexcept
20685 {
20686 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20687 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20688 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20689 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20690
20691#if JSON_DIAGNOSTICS
20692 JSON_TRY
20693 {
20694 // cppcheck-suppress assertWithSideEffect
20695 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20696 {
20697 return j.m_parent == this;
20698 }));
20699 }
20700 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20701#endif
20702 static_cast<void>(check_parents);
20703 }
20704
20706 {
20707#if JSON_DIAGNOSTICS
20708 switch (m_data.m_type)
20709 {
20710 case value_t::array:
20711 {
20712 for (auto& element : *m_data.m_value.array)
20713 {
20714 element.m_parent = this;
20715 }
20716 break;
20717 }
20718
20719 case value_t::object:
20720 {
20721 for (auto& element : *m_data.m_value.object)
20722 {
20723 element.second.m_parent = this;
20724 }
20725 break;
20726 }
20727
20728 case value_t::null:
20729 case value_t::string:
20730 case value_t::boolean:
20731 case value_t::number_integer:
20732 case value_t::number_unsigned:
20733 case value_t::number_float:
20734 case value_t::binary:
20735 case value_t::discarded:
20736 default:
20737 break;
20738 }
20739#endif
20740 }
20741
20742 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20743 {
20744#if JSON_DIAGNOSTICS
20745 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20746 {
20747 (it + i)->m_parent = this;
20748 }
20749#else
20750 static_cast<void>(count_set_parents);
20751#endif
20752 return it;
20753 }
20754
20755 reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size())
20756 {
20757#if JSON_DIAGNOSTICS
20758 if (old_capacity != detail::unknown_size())
20759 {
20760 // see https://github.com/nlohmann/json/issues/2838
20761 JSON_ASSERT(type() == value_t::array);
20762 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20763 {
20764 // capacity has changed: update all parents
20765 set_parents();
20766 return j;
20767 }
20768 }
20769
20770 // ordered_json uses a vector internally, so pointers could have
20771 // been invalidated; see https://github.com/nlohmann/json/issues/2962
20772#ifdef JSON_HEDLEY_MSVC_VERSION
20773#pragma warning(push )
20774#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20775#endif
20777 {
20778 set_parents();
20779 return j;
20780 }
20781#ifdef JSON_HEDLEY_MSVC_VERSION
20782#pragma warning( pop )
20783#endif
20784
20785 j.m_parent = this;
20786#else
20787 static_cast<void>(j);
20788 static_cast<void>(old_capacity);
20789#endif
20790 return j;
20791 }
20792
20793 public:
20795 // JSON parser callback //
20797
20801
20805
20807 // constructors //
20809
20814
20818 : m_data(v)
20819 {
20821 }
20822
20825 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20826 : basic_json(value_t::null)
20827 {
20829 }
20830
20833 template < typename CompatibleType,
20837 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20838 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20839 std::forward<CompatibleType>(val))))
20840 {
20841 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20842 set_parents();
20844 }
20845
20848 template < typename BasicJsonType,
20850 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20851 basic_json(const BasicJsonType& val)
20852#if JSON_DIAGNOSTIC_POSITIONS
20853 : start_position(val.start_pos()),
20854 end_position(val.end_pos())
20855#endif
20856 {
20857 using other_boolean_t = typename BasicJsonType::boolean_t;
20858 using other_number_float_t = typename BasicJsonType::number_float_t;
20859 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20860 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20861 using other_string_t = typename BasicJsonType::string_t;
20862 using other_object_t = typename BasicJsonType::object_t;
20863 using other_array_t = typename BasicJsonType::array_t;
20864 using other_binary_t = typename BasicJsonType::binary_t;
20865
20866 switch (val.type())
20867 {
20868 case value_t::boolean:
20869 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20870 break;
20871 case value_t::number_float:
20872 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20873 break;
20874 case value_t::number_integer:
20875 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20876 break;
20877 case value_t::number_unsigned:
20878 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20879 break;
20880 case value_t::string:
20881 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20882 break;
20883 case value_t::object:
20884 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20885 break;
20886 case value_t::array:
20887 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20888 break;
20889 case value_t::binary:
20890 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20891 break;
20892 case value_t::null:
20893 *this = nullptr;
20894 break;
20895 case value_t::discarded:
20896 m_data.m_type = value_t::discarded;
20897 break;
20898 default: // LCOV_EXCL_LINE
20899 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20900 }
20901 JSON_ASSERT(m_data.m_type == val.type());
20902
20903 set_parents();
20905 }
20906
20910 bool type_deduction = true,
20911 value_t manual_type = value_t::array)
20912 {
20913 // check if each element is an array with two elements whose first
20914 // element is a string
20915 bool is_an_object = std::all_of(init.begin(), init.end(),
20916 [](const detail::json_ref<basic_json>& element_ref)
20917 {
20918 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
20919 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
20920 // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
20921 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
20922 });
20923
20924 // adjust type if type deduction is not wanted
20925 if (!type_deduction)
20926 {
20927 // if array is wanted, do not create an object though possible
20928 if (manual_type == value_t::array)
20929 {
20930 is_an_object = false;
20931 }
20932
20933 // if object is wanted but impossible, throw an exception
20934 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20935 {
20936 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
20937 }
20938 }
20939
20940 if (is_an_object)
20941 {
20942 // the initializer list is a list of pairs -> create object
20943 m_data.m_type = value_t::object;
20944 m_data.m_value = value_t::object;
20945
20946 for (auto& element_ref : init)
20947 {
20948 auto element = element_ref.moved_or_copied();
20949 m_data.m_value.object->emplace(
20950 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
20951 std::move((*element.m_data.m_value.array)[1]));
20952 }
20953 }
20954 else
20955 {
20956 // the initializer list describes an array -> create array
20957 m_data.m_type = value_t::array;
20958 m_data.m_value.array = create<array_t>(init.begin(), init.end());
20959 }
20960
20961 set_parents();
20963 }
20964
20968 static basic_json binary(const typename binary_t::container_type& init)
20969 {
20970 auto res = basic_json();
20971 res.m_data.m_type = value_t::binary;
20972 res.m_data.m_value = init;
20973 return res;
20974 }
20975
20979 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
20980 {
20981 auto res = basic_json();
20982 res.m_data.m_type = value_t::binary;
20983 res.m_data.m_value = binary_t(init, subtype);
20984 return res;
20985 }
20986
20990 static basic_json binary(typename binary_t::container_type&& init)
20991 {
20992 auto res = basic_json();
20993 res.m_data.m_type = value_t::binary;
20994 res.m_data.m_value = std::move(init);
20995 return res;
20996 }
20997
21001 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
21002 {
21003 auto res = basic_json();
21004 res.m_data.m_type = value_t::binary;
21005 res.m_data.m_value = binary_t(std::move(init), subtype);
21006 return res;
21007 }
21008
21013 {
21014 return basic_json(init, false, value_t::array);
21015 }
21016
21021 {
21022 return basic_json(init, false, value_t::object);
21023 }
21024
21028 m_data{cnt, val}
21029 {
21030 set_parents();
21032 }
21033
21036 template < class InputIT, typename std::enable_if <
21037 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
21038 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
21039 basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
21040 {
21041 JSON_ASSERT(first.m_object != nullptr);
21042 JSON_ASSERT(last.m_object != nullptr);
21043
21044 // make sure iterator fits the current value
21045 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
21046 {
21047 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
21048 }
21049
21050 // copy type from first iterator
21051 m_data.m_type = first.m_object->m_data.m_type;
21052
21053 // check if iterator range is complete for primitive values
21054 switch (m_data.m_type)
21055 {
21056 case value_t::boolean:
21057 case value_t::number_float:
21058 case value_t::number_integer:
21059 case value_t::number_unsigned:
21060 case value_t::string:
21061 {
21062 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
21063 || !last.m_it.primitive_iterator.is_end()))
21064 {
21065 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
21066 }
21067 break;
21068 }
21069
21070 case value_t::null:
21071 case value_t::object:
21072 case value_t::array:
21073 case value_t::binary:
21074 case value_t::discarded:
21075 default:
21076 break;
21077 }
21078
21079 switch (m_data.m_type)
21080 {
21081 case value_t::number_integer:
21082 {
21083 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
21084 break;
21085 }
21086
21087 case value_t::number_unsigned:
21088 {
21089 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
21090 break;
21091 }
21092
21093 case value_t::number_float:
21094 {
21095 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
21096 break;
21097 }
21098
21099 case value_t::boolean:
21100 {
21101 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
21102 break;
21103 }
21104
21105 case value_t::string:
21106 {
21107 m_data.m_value = *first.m_object->m_data.m_value.string;
21108 break;
21109 }
21110
21111 case value_t::object:
21112 {
21113 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
21114 last.m_it.object_iterator);
21115 break;
21116 }
21117
21118 case value_t::array:
21119 {
21120 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
21121 last.m_it.array_iterator);
21122 break;
21123 }
21124
21125 case value_t::binary:
21126 {
21127 m_data.m_value = *first.m_object->m_data.m_value.binary;
21128 break;
21129 }
21130
21131 case value_t::null:
21132 case value_t::discarded:
21133 default:
21134 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
21135 }
21136
21137 set_parents();
21139 }
21140
21142 // other constructors and destructor //
21144
21145 template<typename JsonRef,
21147 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
21148 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
21149
21153 : json_base_class_t(other)
21155 , start_position(other.start_position)
21156 , end_position(other.end_position)
21157#endif
21158 {
21159 m_data.m_type = other.m_data.m_type;
21160 // check of passed value is valid
21161 other.assert_invariant();
21162
21163 switch (m_data.m_type)
21164 {
21165 case value_t::object:
21166 {
21167 m_data.m_value = *other.m_data.m_value.object;
21168 break;
21169 }
21170
21171 case value_t::array:
21172 {
21173 m_data.m_value = *other.m_data.m_value.array;
21174 break;
21175 }
21176
21177 case value_t::string:
21178 {
21179 m_data.m_value = *other.m_data.m_value.string;
21180 break;
21181 }
21182
21183 case value_t::boolean:
21184 {
21185 m_data.m_value = other.m_data.m_value.boolean;
21186 break;
21187 }
21188
21189 case value_t::number_integer:
21190 {
21191 m_data.m_value = other.m_data.m_value.number_integer;
21192 break;
21193 }
21194
21195 case value_t::number_unsigned:
21196 {
21197 m_data.m_value = other.m_data.m_value.number_unsigned;
21198 break;
21199 }
21200
21201 case value_t::number_float:
21202 {
21203 m_data.m_value = other.m_data.m_value.number_float;
21204 break;
21205 }
21206
21207 case value_t::binary:
21208 {
21209 m_data.m_value = *other.m_data.m_value.binary;
21210 break;
21211 }
21212
21213 case value_t::null:
21214 case value_t::discarded:
21215 default:
21216 break;
21217 }
21218
21219 set_parents();
21220 assert_invariant();
21221 }
21222
21225 basic_json(basic_json&& other) noexcept
21226 : json_base_class_t(std::forward<json_base_class_t>(other)),
21227 m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
21228#if JSON_DIAGNOSTIC_POSITIONS
21229 , start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
21230 , end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
21231#endif
21232 {
21233 // check that passed value is valid
21234 other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
21235
21236 // invalidate payload
21237 other.m_data.m_type = value_t::null;
21238 other.m_data.m_value = {};
21239
21240#if JSON_DIAGNOSTIC_POSITIONS
21241 other.start_position = std::string::npos;
21242 other.end_position = std::string::npos;
21243#endif
21244
21245 set_parents();
21247 }
21248
21252 std::is_nothrow_move_constructible<value_t>::value&&
21253 std::is_nothrow_move_assignable<value_t>::value&&
21254 std::is_nothrow_move_constructible<json_value>::value&&
21255 std::is_nothrow_move_assignable<json_value>::value&&
21256 std::is_nothrow_move_assignable<json_base_class_t>::value
21257 )
21258 {
21259 // check that passed value is valid
21260 other.assert_invariant();
21261
21262 using std::swap;
21263 swap(m_data.m_type, other.m_data.m_type);
21264 swap(m_data.m_value, other.m_data.m_value);
21265
21266#if JSON_DIAGNOSTIC_POSITIONS
21267 swap(start_position, other.start_position);
21268 swap(end_position, other.end_position);
21269#endif
21270
21271 json_base_class_t::operator=(std::move(other));
21272
21273 set_parents();
21275 return *this;
21276 }
21277
21280 ~basic_json() noexcept
21281 {
21282 assert_invariant(false);
21283 }
21284
21286
21287 public:
21289 // object inspection //
21291
21295
21298 string_t dump(const int indent = -1,
21299 const char indent_char = ' ',
21300 const bool ensure_ascii = false,
21301 const error_handler_t error_handler = error_handler_t::strict) const
21302 {
21303 string_t result;
21304 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
21305
21306 if (indent >= 0)
21307 {
21308 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
21309 }
21310 else
21311 {
21312 s.dump(*this, false, ensure_ascii, 0);
21313 }
21314
21315 return result;
21316 }
21317
21320 constexpr value_t type() const noexcept
21321 {
21322 return m_data.m_type;
21323 }
21324
21327 constexpr bool is_primitive() const noexcept
21328 {
21329 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
21330 }
21331
21334 constexpr bool is_structured() const noexcept
21335 {
21336 return is_array() || is_object();
21337 }
21338
21341 constexpr bool is_null() const noexcept
21342 {
21343 return m_data.m_type == value_t::null;
21344 }
21345
21348 constexpr bool is_boolean() const noexcept
21349 {
21350 return m_data.m_type == value_t::boolean;
21351 }
21352
21355 constexpr bool is_number() const noexcept
21356 {
21357 return is_number_integer() || is_number_float();
21358 }
21359
21362 constexpr bool is_number_integer() const noexcept
21363 {
21364 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
21365 }
21366
21369 constexpr bool is_number_unsigned() const noexcept
21370 {
21371 return m_data.m_type == value_t::number_unsigned;
21372 }
21373
21376 constexpr bool is_number_float() const noexcept
21377 {
21378 return m_data.m_type == value_t::number_float;
21379 }
21380
21383 constexpr bool is_object() const noexcept
21384 {
21385 return m_data.m_type == value_t::object;
21386 }
21387
21390 constexpr bool is_array() const noexcept
21391 {
21392 return m_data.m_type == value_t::array;
21393 }
21394
21397 constexpr bool is_string() const noexcept
21398 {
21399 return m_data.m_type == value_t::string;
21400 }
21401
21404 constexpr bool is_binary() const noexcept
21405 {
21406 return m_data.m_type == value_t::binary;
21407 }
21408
21411 constexpr bool is_discarded() const noexcept
21412 {
21413 return m_data.m_type == value_t::discarded;
21414 }
21415
21418 constexpr operator value_t() const noexcept
21419 {
21420 return m_data.m_type;
21421 }
21422
21424
21425 private:
21427 // value access //
21429
21431 boolean_t get_impl(boolean_t* /*unused*/) const
21432 {
21434 {
21435 return m_data.m_value.boolean;
21436 }
21437
21438 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
21439 }
21440
21442 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
21443 {
21444 return is_object() ? m_data.m_value.object : nullptr;
21445 }
21446
21448 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
21449 {
21450 return is_object() ? m_data.m_value.object : nullptr;
21451 }
21452
21454 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
21455 {
21456 return is_array() ? m_data.m_value.array : nullptr;
21457 }
21458
21460 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
21461 {
21462 return is_array() ? m_data.m_value.array : nullptr;
21463 }
21464
21466 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
21467 {
21468 return is_string() ? m_data.m_value.string : nullptr;
21469 }
21470
21472 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
21473 {
21474 return is_string() ? m_data.m_value.string : nullptr;
21475 }
21476
21478 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
21479 {
21480 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21481 }
21482
21484 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
21485 {
21486 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21487 }
21488
21491 {
21492 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21493 }
21494
21496 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
21497 {
21498 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21499 }
21500
21503 {
21504 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21505 }
21506
21508 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
21509 {
21510 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21511 }
21512
21515 {
21516 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21517 }
21518
21520 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
21521 {
21522 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21523 }
21524
21526 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
21527 {
21528 return is_binary() ? m_data.m_value.binary : nullptr;
21529 }
21530
21532 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
21533 {
21534 return is_binary() ? m_data.m_value.binary : nullptr;
21535 }
21536
21548 template<typename ReferenceType, typename ThisType>
21549 static ReferenceType get_ref_impl(ThisType& obj)
21550 {
21551 // delegate the call to get_ptr<>()
21553
21554 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
21555 {
21556 return *ptr;
21557 }
21558
21559 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
21560 }
21561
21562 public:
21566
21569 template<typename PointerType, typename std::enable_if<
21570 std::is_pointer<PointerType>::value, int>::type = 0>
21571 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21572 {
21573 // delegate the call to get_impl_ptr<>()
21574 return get_impl_ptr(static_cast<PointerType>(nullptr));
21575 }
21576
21579 template < typename PointerType, typename std::enable_if <
21580 std::is_pointer<PointerType>::value&&
21581 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
21582 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21583 {
21584 // delegate the call to get_impl_ptr<>() const
21585 return get_impl_ptr(static_cast<PointerType>(nullptr));
21586 }
21587
21588 private:
21627 template < typename ValueType,
21631 int > = 0 >
21632 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
21633 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
21634 {
21635 auto ret = ValueType();
21636 JSONSerializer<ValueType>::from_json(*this, ret);
21637 return ret;
21638 }
21639
21670 template < typename ValueType,
21673 int > = 0 >
21674 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
21675 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
21676 {
21677 return JSONSerializer<ValueType>::from_json(*this);
21678 }
21679
21695 template < typename BasicJsonType,
21698 int > = 0 >
21699 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
21700 {
21701 return *this;
21702 }
21703
21718 template<typename BasicJsonType,
21720 std::is_same<BasicJsonType, basic_json_t>::value,
21721 int> = 0>
21723 {
21724 return *this;
21725 }
21726
21731 template<typename PointerType,
21733 std::is_pointer<PointerType>::value,
21734 int> = 0>
21735 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21736 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21737 {
21738 // delegate the call to get_ptr
21739 return get_ptr<PointerType>();
21740 }
21741
21742 public:
21766 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21767#if defined(JSON_HAS_CPP_14)
21768 constexpr
21769#endif
21770 auto get() const noexcept(
21771 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21772 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21773 {
21774 // we cannot static_assert on ValueTypeCV being non-const, because
21775 // there is support for get<const basic_json_t>(), which is why we
21776 // still need the uncvref
21777 static_assert(!std::is_reference<ValueTypeCV>::value,
21778 "get() cannot be used with reference types, you might want to use get_ref()");
21779 return get_impl<ValueType>(detail::priority_tag<4> {});
21780 }
21781
21809 template<typename PointerType, typename std::enable_if<
21810 std::is_pointer<PointerType>::value, int>::type = 0>
21811 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21812 {
21813 // delegate the call to get_ptr
21814 return get_ptr<PointerType>();
21815 }
21816
21819 template < typename ValueType,
21823 int > = 0 >
21824 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21825 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21826 {
21827 JSONSerializer<ValueType>::from_json(*this, v);
21828 return v;
21829 }
21830
21831 // specialization to allow calling get_to with a basic_json value
21832 // see https://github.com/nlohmann/json/issues/2175
21833 template<typename ValueType,
21836 int> = 0>
21837 ValueType & get_to(ValueType& v) const
21838 {
21839 v = *this;
21840 return v;
21841 }
21842
21843 template <
21844 typename T, std::size_t N,
21845 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21848 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21849 noexcept(noexcept(JSONSerializer<Array>::from_json(
21850 std::declval<const basic_json_t&>(), v)))
21851 {
21852 JSONSerializer<Array>::from_json(*this, v);
21853 return v;
21854 }
21855
21858 template<typename ReferenceType, typename std::enable_if<
21859 std::is_reference<ReferenceType>::value, int>::type = 0>
21860 ReferenceType get_ref()
21861 {
21862 // delegate call to get_ref_impl
21863 return get_ref_impl<ReferenceType>(*this);
21864 }
21865
21868 template < typename ReferenceType, typename std::enable_if <
21869 std::is_reference<ReferenceType>::value&&
21870 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21871 ReferenceType get_ref() const
21872 {
21873 // delegate call to get_ref_impl
21874 return get_ref_impl<ReferenceType>(*this);
21875 }
21876
21906 template < typename ValueType, typename std::enable_if <
21914#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21916#endif
21917#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
21919#endif
21921 >::value, int >::type = 0 >
21922 JSON_EXPLICIT operator ValueType() const
21923 {
21924 // delegate the call to get<>() const
21925 return get<ValueType>();
21926 }
21927
21931 {
21932 if (!is_binary())
21933 {
21934 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21935 }
21936
21937 return *get_ptr<binary_t*>();
21938 }
21939
21942 const binary_t& get_binary() const
21943 {
21944 if (!is_binary())
21945 {
21946 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21947 }
21948
21949 return *get_ptr<const binary_t*>();
21950 }
21951
21953
21955 // element access //
21957
21961
21965 {
21966 // at only works for arrays
21968 {
21969 JSON_TRY
21970 {
21971 return set_parent(m_data.m_value.array->at(idx));
21972 }
21973 JSON_CATCH (std::out_of_range&)
21974 {
21975 // create better exception explanation
21976 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21977 } // cppcheck-suppress[missingReturn]
21978 }
21979 else
21980 {
21981 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21982 }
21983 }
21984
21988 {
21989 // at only works for arrays
21991 {
21992 JSON_TRY
21993 {
21994 return m_data.m_value.array->at(idx);
21995 }
21996 JSON_CATCH (std::out_of_range&)
21997 {
21998 // create better exception explanation
21999 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22000 } // cppcheck-suppress[missingReturn]
22001 }
22002 else
22003 {
22004 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22005 }
22006 }
22007
22010 reference at(const typename object_t::key_type& key)
22011 {
22012 // at only works for objects
22014 {
22015 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22016 }
22017
22018 auto it = m_data.m_value.object->find(key);
22019 if (it == m_data.m_value.object->end())
22020 {
22021 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22022 }
22023 return set_parent(it->second);
22024 }
22025
22028 template<class KeyType, detail::enable_if_t<
22030 reference at(KeyType && key)
22031 {
22032 // at only works for objects
22034 {
22035 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22036 }
22037
22038 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22039 if (it == m_data.m_value.object->end())
22040 {
22041 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22042 }
22043 return set_parent(it->second);
22044 }
22045
22048 const_reference at(const typename object_t::key_type& key) const
22049 {
22050 // at only works for objects
22052 {
22053 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22054 }
22055
22056 auto it = m_data.m_value.object->find(key);
22057 if (it == m_data.m_value.object->end())
22058 {
22059 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22060 }
22061 return it->second;
22062 }
22063
22066 template<class KeyType, detail::enable_if_t<
22068 const_reference at(KeyType && key) const
22069 {
22070 // at only works for objects
22072 {
22073 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22074 }
22075
22076 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22077 if (it == m_data.m_value.object->end())
22078 {
22079 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22080 }
22081 return it->second;
22082 }
22083
22087 {
22088 // implicitly convert null value to an empty array
22089 if (is_null())
22090 {
22091 m_data.m_type = value_t::array;
22092 m_data.m_value.array = create<array_t>();
22094 }
22095
22096 // operator[] only works for arrays
22098 {
22099 // fill up array with null values if given idx is outside range
22100 if (idx >= m_data.m_value.array->size())
22101 {
22102#if JSON_DIAGNOSTICS
22103 // remember array size & capacity before resizing
22104 const auto old_size = m_data.m_value.array->size();
22105 const auto old_capacity = m_data.m_value.array->capacity();
22106#endif
22107 m_data.m_value.array->resize(idx + 1);
22108
22109#if JSON_DIAGNOSTICS
22110 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
22111 {
22112 // capacity has changed: update all parents
22113 set_parents();
22114 }
22115 else
22116 {
22117 // set parent for values added above
22118 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
22119 }
22120#endif
22122 }
22123
22124 return m_data.m_value.array->operator[](idx);
22125 }
22126
22127 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22128 }
22129
22133 {
22134 // const operator[] only works for arrays
22136 {
22137 return m_data.m_value.array->operator[](idx);
22138 }
22139
22140 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22141 }
22142
22145 reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
22146 {
22147 // implicitly convert null value to an empty object
22148 if (is_null())
22149 {
22150 m_data.m_type = value_t::object;
22151 m_data.m_value.object = create<object_t>();
22153 }
22154
22155 // operator[] only works for objects
22157 {
22158 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
22159 return set_parent(result.first->second);
22160 }
22161
22162 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22163 }
22164
22167 const_reference operator[](const typename object_t::key_type& key) const
22168 {
22169 // const operator[] only works for objects
22171 {
22172 auto it = m_data.m_value.object->find(key);
22173 JSON_ASSERT(it != m_data.m_value.object->end());
22174 return it->second;
22175 }
22176
22177 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22178 }
22179
22180 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
22181 // (they seemingly cannot be constrained to resolve the ambiguity)
22182 template<typename T>
22184 {
22185 return operator[](typename object_t::key_type(key));
22186 }
22187
22188 template<typename T>
22190 {
22191 return operator[](typename object_t::key_type(key));
22192 }
22193
22196 template<class KeyType, detail::enable_if_t<
22199 {
22200 // implicitly convert null value to an empty object
22201 if (is_null())
22202 {
22203 m_data.m_type = value_t::object;
22204 m_data.m_value.object = create<object_t>();
22206 }
22207
22208 // operator[] only works for objects
22210 {
22211 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
22212 return set_parent(result.first->second);
22213 }
22214
22215 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22216 }
22217
22220 template<class KeyType, detail::enable_if_t<
22223 {
22224 // const operator[] only works for objects
22226 {
22227 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22228 JSON_ASSERT(it != m_data.m_value.object->end());
22229 return it->second;
22230 }
22231
22232 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22233 }
22234
22235 private:
22236 template<typename KeyType>
22238 object_comparator_t, const typename object_t::key_type&, KeyType >;
22239
22240 template<typename ValueType>
22241 using value_return_type = std::conditional <
22243 string_t, typename std::decay<ValueType>::type >;
22244
22245 public:
22248 template < class ValueType, detail::enable_if_t <
22251 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22252 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
22253 {
22254 // value only works for objects
22256 {
22257 // if key is found, return value and given default value otherwise
22258 const auto it = find(key);
22259 if (it != end())
22260 {
22261 return it->template get<ValueType>();
22262 }
22263
22264 return default_value;
22265 }
22266
22267 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22268 }
22269
22272 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22276 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22277 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
22278 {
22279 // value only works for objects
22281 {
22282 // if key is found, return value and given default value otherwise
22283 const auto it = find(key);
22284 if (it != end())
22285 {
22286 return it->template get<ReturnType>();
22287 }
22288
22289 return std::forward<ValueType>(default_value);
22290 }
22291
22292 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22293 }
22294
22297 template < class ValueType, class KeyType, detail::enable_if_t <
22300 && is_comparable_with_object_key<KeyType>::value
22302 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22303 ValueType value(KeyType && key, const ValueType& default_value) const
22304 {
22305 // value only works for objects
22307 {
22308 // if key is found, return value and given default value otherwise
22309 const auto it = find(std::forward<KeyType>(key));
22310 if (it != end())
22311 {
22312 return it->template get<ValueType>();
22313 }
22314
22315 return default_value;
22316 }
22317
22318 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22319 }
22320
22323 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
22327 && is_comparable_with_object_key<KeyType>::value
22329 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22330 ReturnType value(KeyType && key, ValueType && default_value) const
22331 {
22332 // value only works for objects
22334 {
22335 // if key is found, return value and given default value otherwise
22336 const auto it = find(std::forward<KeyType>(key));
22337 if (it != end())
22338 {
22339 return it->template get<ReturnType>();
22340 }
22341
22342 return std::forward<ValueType>(default_value);
22343 }
22344
22345 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22346 }
22347
22350 template < class ValueType, detail::enable_if_t <
22352 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22353 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
22354 {
22355 // value only works for objects
22357 {
22358 // if pointer resolves a value, return it or use default value
22359 JSON_TRY
22360 {
22361 return ptr.get_checked(this).template get<ValueType>();
22362 }
22364 {
22365 return default_value;
22366 }
22367 }
22368
22369 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22370 }
22371
22374 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22377 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22378 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
22379 {
22380 // value only works for objects
22382 {
22383 // if pointer resolves a value, return it or use default value
22384 JSON_TRY
22385 {
22386 return ptr.get_checked(this).template get<ReturnType>();
22387 }
22389 {
22390 return std::forward<ValueType>(default_value);
22391 }
22392 }
22393
22394 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22395 }
22396
22397 template < class ValueType, class BasicJsonType, detail::enable_if_t <
22400 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22401 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22402 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
22403 {
22404 return value(ptr.convert(), default_value);
22405 }
22406
22407 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
22411 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22412 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22413 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
22414 {
22415 return value(ptr.convert(), std::forward<ValueType>(default_value));
22416 }
22417
22421 {
22422 return *begin();
22423 }
22424
22428 {
22429 return *cbegin();
22430 }
22431
22435 {
22436 auto tmp = end();
22437 --tmp;
22438 return *tmp;
22439 }
22440
22444 {
22445 auto tmp = cend();
22446 --tmp;
22447 return *tmp;
22448 }
22449
22452 template < class IteratorType, detail::enable_if_t <
22453 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22454 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22455 IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
22456 {
22457 // make sure iterator fits the current value
22458 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
22459 {
22460 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22461 }
22462
22463 IteratorType result = end();
22464
22465 switch (m_data.m_type)
22466 {
22467 case value_t::boolean:
22468 case value_t::number_float:
22469 case value_t::number_integer:
22470 case value_t::number_unsigned:
22471 case value_t::string:
22472 case value_t::binary:
22473 {
22474 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
22475 {
22476 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
22477 }
22478
22479 if (is_string())
22480 {
22481 AllocatorType<string_t> alloc;
22482 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22483 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22484 m_data.m_value.string = nullptr;
22485 }
22486 else if (is_binary())
22487 {
22488 AllocatorType<binary_t> alloc;
22489 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22490 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22491 m_data.m_value.binary = nullptr;
22492 }
22493
22494 m_data.m_type = value_t::null;
22496 break;
22497 }
22498
22499 case value_t::object:
22500 {
22501 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
22502 break;
22503 }
22504
22505 case value_t::array:
22506 {
22507 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
22508 break;
22509 }
22510
22511 case value_t::null:
22512 case value_t::discarded:
22513 default:
22514 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22515 }
22516
22517 return result;
22518 }
22519
22522 template < class IteratorType, detail::enable_if_t <
22523 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22524 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22525 IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
22526 {
22527 // make sure iterator fits the current value
22528 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
22529 {
22530 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
22531 }
22532
22533 IteratorType result = end();
22534
22535 switch (m_data.m_type)
22536 {
22537 case value_t::boolean:
22538 case value_t::number_float:
22539 case value_t::number_integer:
22540 case value_t::number_unsigned:
22541 case value_t::string:
22542 case value_t::binary:
22543 {
22544 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
22545 || !last.m_it.primitive_iterator.is_end()))
22546 {
22547 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
22548 }
22549
22550 if (is_string())
22551 {
22552 AllocatorType<string_t> alloc;
22553 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22554 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22555 m_data.m_value.string = nullptr;
22556 }
22557 else if (is_binary())
22558 {
22559 AllocatorType<binary_t> alloc;
22560 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22561 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22562 m_data.m_value.binary = nullptr;
22563 }
22564
22565 m_data.m_type = value_t::null;
22567 break;
22568 }
22569
22570 case value_t::object:
22571 {
22572 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
22573 last.m_it.object_iterator);
22574 break;
22575 }
22576
22577 case value_t::array:
22578 {
22579 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
22580 last.m_it.array_iterator);
22581 break;
22582 }
22583
22584 case value_t::null:
22585 case value_t::discarded:
22586 default:
22587 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22588 }
22589
22590 return result;
22591 }
22592
22593 private:
22594 template < typename KeyType, detail::enable_if_t <
22597 {
22598 // this erase only works for objects
22600 {
22601 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22602 }
22603
22604 return m_data.m_value.object->erase(std::forward<KeyType>(key));
22605 }
22606
22607 template < typename KeyType, detail::enable_if_t <
22610 {
22611 // this erase only works for objects
22613 {
22614 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22615 }
22616
22617 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22618 if (it != m_data.m_value.object->end())
22619 {
22620 m_data.m_value.object->erase(it);
22621 return 1;
22622 }
22623 return 0;
22624 }
22625
22626 public:
22627
22630 size_type erase(const typename object_t::key_type& key)
22631 {
22632 // the indirection via erase_internal() is added to avoid making this
22633 // function a template and thus de-rank it during overload resolution
22634 return erase_internal(key);
22635 }
22636
22639 template<class KeyType, detail::enable_if_t<
22641 size_type erase(KeyType && key)
22642 {
22643 return erase_internal(std::forward<KeyType>(key));
22644 }
22645
22648 void erase(const size_type idx)
22649 {
22650 // this erase only works for arrays
22652 {
22653 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
22654 {
22655 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22656 }
22657
22658 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
22659 }
22660 else
22661 {
22662 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22663 }
22664 }
22665
22667
22669 // lookup //
22671
22674
22677 iterator find(const typename object_t::key_type& key)
22678 {
22679 auto result = end();
22680
22681 if (is_object())
22682 {
22683 result.m_it.object_iterator = m_data.m_value.object->find(key);
22684 }
22685
22686 return result;
22687 }
22688
22691 const_iterator find(const typename object_t::key_type& key) const
22692 {
22693 auto result = cend();
22694
22695 if (is_object())
22696 {
22697 result.m_it.object_iterator = m_data.m_value.object->find(key);
22698 }
22699
22700 return result;
22701 }
22702
22705 template<class KeyType, detail::enable_if_t<
22707 iterator find(KeyType && key)
22708 {
22709 auto result = end();
22710
22711 if (is_object())
22712 {
22713 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22714 }
22715
22716 return result;
22717 }
22718
22721 template<class KeyType, detail::enable_if_t<
22723 const_iterator find(KeyType && key) const
22724 {
22725 auto result = cend();
22726
22727 if (is_object())
22728 {
22729 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22730 }
22731
22732 return result;
22733 }
22734
22737 size_type count(const typename object_t::key_type& key) const
22738 {
22739 // return 0 for all nonobject types
22740 return is_object() ? m_data.m_value.object->count(key) : 0;
22741 }
22742
22745 template<class KeyType, detail::enable_if_t<
22747 size_type count(KeyType && key) const
22748 {
22749 // return 0 for all nonobject types
22750 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22751 }
22752
22755 bool contains(const typename object_t::key_type& key) const
22756 {
22757 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22758 }
22759
22762 template<class KeyType, detail::enable_if_t<
22764 bool contains(KeyType && key) const
22765 {
22766 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22767 }
22768
22771 bool contains(const json_pointer& ptr) const
22772 {
22773 return ptr.contains(this);
22774 }
22775
22776 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22777 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22778 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22779 {
22780 return ptr.contains(this);
22781 }
22782
22784
22786 // iterators //
22788
22791
22794 iterator begin() noexcept
22795 {
22796 iterator result(this);
22797 result.set_begin();
22798 return result;
22799 }
22800
22803 const_iterator begin() const noexcept
22804 {
22805 return cbegin();
22806 }
22807
22810 const_iterator cbegin() const noexcept
22811 {
22812 const_iterator result(this);
22813 result.set_begin();
22814 return result;
22815 }
22816
22819 iterator end() noexcept
22820 {
22821 iterator result(this);
22822 result.set_end();
22823 return result;
22824 }
22825
22828 const_iterator end() const noexcept
22829 {
22830 return cend();
22831 }
22832
22835 const_iterator cend() const noexcept
22836 {
22837 const_iterator result(this);
22838 result.set_end();
22839 return result;
22840 }
22841
22845 {
22846 return reverse_iterator(end());
22847 }
22848
22852 {
22853 return crbegin();
22854 }
22855
22859 {
22860 return reverse_iterator(begin());
22861 }
22862
22866 {
22867 return crend();
22868 }
22869
22873 {
22874 return const_reverse_iterator(cend());
22875 }
22876
22880 {
22882 }
22883
22884 public:
22890 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22892 {
22893 return ref.items();
22894 }
22895
22901 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22903 {
22904 return ref.items();
22905 }
22906
22910 {
22911 return iteration_proxy<iterator>(*this);
22912 }
22913
22917 {
22918 return iteration_proxy<const_iterator>(*this);
22919 }
22920
22922
22924 // capacity //
22926
22929
22932 bool empty() const noexcept
22933 {
22934 switch (m_data.m_type)
22935 {
22936 case value_t::null:
22937 {
22938 // null values are empty
22939 return true;
22940 }
22941
22942 case value_t::array:
22943 {
22944 // delegate call to array_t::empty()
22945 return m_data.m_value.array->empty();
22946 }
22947
22948 case value_t::object:
22949 {
22950 // delegate call to object_t::empty()
22951 return m_data.m_value.object->empty();
22952 }
22953
22954 case value_t::string:
22955 case value_t::boolean:
22956 case value_t::number_integer:
22957 case value_t::number_unsigned:
22958 case value_t::number_float:
22959 case value_t::binary:
22960 case value_t::discarded:
22961 default:
22962 {
22963 // all other types are nonempty
22964 return false;
22965 }
22966 }
22967 }
22968
22971 size_type size() const noexcept
22972 {
22973 switch (m_data.m_type)
22974 {
22975 case value_t::null:
22976 {
22977 // null values are empty
22978 return 0;
22979 }
22980
22981 case value_t::array:
22982 {
22983 // delegate call to array_t::size()
22984 return m_data.m_value.array->size();
22985 }
22986
22987 case value_t::object:
22988 {
22989 // delegate call to object_t::size()
22990 return m_data.m_value.object->size();
22991 }
22992
22993 case value_t::string:
22994 case value_t::boolean:
22995 case value_t::number_integer:
22996 case value_t::number_unsigned:
22997 case value_t::number_float:
22998 case value_t::binary:
22999 case value_t::discarded:
23000 default:
23001 {
23002 // all other types have size 1
23003 return 1;
23004 }
23005 }
23006 }
23007
23010 size_type max_size() const noexcept
23011 {
23012 switch (m_data.m_type)
23013 {
23014 case value_t::array:
23015 {
23016 // delegate call to array_t::max_size()
23017 return m_data.m_value.array->max_size();
23018 }
23019
23020 case value_t::object:
23021 {
23022 // delegate call to object_t::max_size()
23023 return m_data.m_value.object->max_size();
23024 }
23025
23026 case value_t::null:
23027 case value_t::string:
23028 case value_t::boolean:
23029 case value_t::number_integer:
23030 case value_t::number_unsigned:
23031 case value_t::number_float:
23032 case value_t::binary:
23033 case value_t::discarded:
23034 default:
23035 {
23036 // all other types have max_size() == size()
23037 return size();
23038 }
23039 }
23040 }
23041
23043
23045 // modifiers //
23047
23050
23053 void clear() noexcept
23054 {
23055 switch (m_data.m_type)
23056 {
23057 case value_t::number_integer:
23058 {
23059 m_data.m_value.number_integer = 0;
23060 break;
23061 }
23062
23063 case value_t::number_unsigned:
23064 {
23065 m_data.m_value.number_unsigned = 0;
23066 break;
23067 }
23068
23069 case value_t::number_float:
23070 {
23071 m_data.m_value.number_float = 0.0;
23072 break;
23073 }
23074
23075 case value_t::boolean:
23076 {
23077 m_data.m_value.boolean = false;
23078 break;
23079 }
23080
23081 case value_t::string:
23082 {
23083 m_data.m_value.string->clear();
23084 break;
23085 }
23086
23087 case value_t::binary:
23088 {
23089 m_data.m_value.binary->clear();
23090 break;
23091 }
23092
23093 case value_t::array:
23094 {
23095 m_data.m_value.array->clear();
23096 break;
23097 }
23098
23099 case value_t::object:
23100 {
23101 m_data.m_value.object->clear();
23102 break;
23103 }
23104
23105 case value_t::null:
23106 case value_t::discarded:
23107 default:
23108 break;
23109 }
23110 }
23111
23115 {
23116 // push_back only works for null objects or arrays
23117 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23118 {
23119 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23120 }
23121
23122 // transform null object into an array
23123 if (is_null())
23124 {
23125 m_data.m_type = value_t::array;
23126 m_data.m_value = value_t::array;
23128 }
23129
23130 // add element to array (move semantics)
23131 const auto old_capacity = m_data.m_value.array->capacity();
23132 m_data.m_value.array->push_back(std::move(val));
23133 set_parent(m_data.m_value.array->back(), old_capacity);
23134 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
23135 }
23136
23140 {
23141 push_back(std::move(val));
23142 return *this;
23143 }
23144
23147 void push_back(const basic_json& val)
23148 {
23149 // push_back only works for null objects or arrays
23150 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23151 {
23152 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23153 }
23154
23155 // transform null object into an array
23156 if (is_null())
23157 {
23158 m_data.m_type = value_t::array;
23159 m_data.m_value = value_t::array;
23161 }
23162
23163 // add element to array
23164 const auto old_capacity = m_data.m_value.array->capacity();
23165 m_data.m_value.array->push_back(val);
23166 set_parent(m_data.m_value.array->back(), old_capacity);
23167 }
23168
23172 {
23173 push_back(val);
23174 return *this;
23175 }
23176
23179 void push_back(const typename object_t::value_type& val)
23180 {
23181 // push_back only works for null objects or objects
23182 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23183 {
23184 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23185 }
23186
23187 // transform null object into an object
23188 if (is_null())
23189 {
23190 m_data.m_type = value_t::object;
23191 m_data.m_value = value_t::object;
23193 }
23194
23195 // add element to object
23196 auto res = m_data.m_value.object->insert(val);
23197 set_parent(res.first->second);
23198 }
23199
23202 reference operator+=(const typename object_t::value_type& val)
23203 {
23204 push_back(val);
23205 return *this;
23206 }
23207
23211 {
23212 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
23213 {
23214 basic_json&& key = init.begin()->moved_or_copied();
23215 push_back(typename object_t::value_type(
23216 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
23217 }
23218 else
23219 {
23220 push_back(basic_json(init));
23221 }
23222 }
23223
23227 {
23228 push_back(init);
23229 return *this;
23230 }
23231
23234 template<class... Args>
23235 reference emplace_back(Args&& ... args)
23236 {
23237 // emplace_back only works for null objects or arrays
23238 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23239 {
23240 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
23241 }
23242
23243 // transform null object into an array
23244 if (is_null())
23245 {
23246 m_data.m_type = value_t::array;
23247 m_data.m_value = value_t::array;
23249 }
23250
23251 // add element to array (perfect forwarding)
23252 const auto old_capacity = m_data.m_value.array->capacity();
23253 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
23254 return set_parent(m_data.m_value.array->back(), old_capacity);
23255 }
23256
23259 template<class... Args>
23260 std::pair<iterator, bool> emplace(Args&& ... args)
23261 {
23262 // emplace only works for null objects or arrays
23263 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23264 {
23265 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
23266 }
23267
23268 // transform null object into an object
23269 if (is_null())
23270 {
23271 m_data.m_type = value_t::object;
23272 m_data.m_value = value_t::object;
23274 }
23275
23276 // add element to array (perfect forwarding)
23277 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
23278 set_parent(res.first->second);
23279
23280 // create result iterator and set iterator to the result of emplace
23281 auto it = begin();
23282 it.m_it.object_iterator = res.first;
23283
23284 // return pair of iterator and boolean
23285 return {it, res.second};
23286 }
23287
23291 template<typename... Args>
23292 iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
23293 {
23294 iterator result(this);
23295 JSON_ASSERT(m_data.m_value.array != nullptr);
23296
23297 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
23298 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
23299 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
23300
23301 // This could have been written as:
23302 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
23303 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
23304
23305 set_parents();
23306 return result;
23307 }
23308
23311 iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23312 {
23313 // insert only works for arrays
23315 {
23316 // check if iterator pos fits to this JSON value
23317 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23318 {
23319 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23320 }
23321
23322 // insert to array and return iterator
23323 return insert_iterator(pos, val);
23324 }
23325
23326 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23327 }
23328
23331 iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
23332 {
23333 return insert(pos, val);
23334 }
23335
23338 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23339 {
23340 // insert only works for arrays
23342 {
23343 // check if iterator pos fits to this JSON value
23344 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23345 {
23346 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23347 }
23348
23349 // insert to array and return iterator
23350 return insert_iterator(pos, cnt, val);
23351 }
23352
23353 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23354 }
23355
23358 iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23359 {
23360 // insert only works for arrays
23362 {
23363 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23364 }
23365
23366 // check if iterator pos fits to this JSON value
23367 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23368 {
23369 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23370 }
23371
23372 // check if range iterators belong to the same JSON object
23373 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23374 {
23375 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23376 }
23377
23378 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
23379 {
23380 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
23381 }
23382
23383 // insert to array and return iterator
23384 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
23385 }
23386
23389 iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
23390 {
23391 // insert only works for arrays
23393 {
23394 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23395 }
23396
23397 // check if iterator pos fits to this JSON value
23398 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23399 {
23400 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23401 }
23402
23403 // insert to array and return iterator
23404 return insert_iterator(pos, ilist.begin(), ilist.end());
23405 }
23406
23409 void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23410 {
23411 // insert only works for objects
23413 {
23414 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23415 }
23416
23417 // check if range iterators belong to the same JSON object
23418 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23419 {
23420 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23421 }
23422
23423 // passed iterators must belong to objects
23424 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23425 {
23426 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
23427 }
23428
23429 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
23430 set_parents();
23431 }
23432
23435 void update(const_reference j, bool merge_objects = false)
23436 {
23437 update(j.begin(), j.end(), merge_objects);
23438 }
23439
23442 void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
23443 {
23444 // implicitly convert null value to an empty object
23445 if (is_null())
23446 {
23447 m_data.m_type = value_t::object;
23448 m_data.m_value.object = create<object_t>();
23450 }
23451
23453 {
23454 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
23455 }
23456
23457 // check if range iterators belong to the same JSON object
23458 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23459 {
23460 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23461 }
23462
23463 // passed iterators must belong to objects
23464 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23465 {
23466 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
23467 }
23468
23469 for (auto it = first; it != last; ++it)
23470 {
23471 if (merge_objects && it.value().is_object())
23472 {
23473 auto it2 = m_data.m_value.object->find(it.key());
23474 if (it2 != m_data.m_value.object->end())
23475 {
23476 it2->second.update(it.value(), true);
23477 continue;
23478 }
23479 }
23480 m_data.m_value.object->operator[](it.key()) = it.value();
23481#if JSON_DIAGNOSTICS
23482 m_data.m_value.object->operator[](it.key()).m_parent = this;
23483#endif
23484 }
23485 }
23486
23489 void swap(reference other) noexcept (
23490 std::is_nothrow_move_constructible<value_t>::value&&
23491 std::is_nothrow_move_assignable<value_t>::value&&
23492 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23493 std::is_nothrow_move_assignable<json_value>::value
23494 )
23495 {
23496 std::swap(m_data.m_type, other.m_data.m_type);
23497 std::swap(m_data.m_value, other.m_data.m_value);
23498
23499 set_parents();
23500 other.set_parents();
23502 }
23503
23506 friend void swap(reference left, reference right) noexcept (
23507 std::is_nothrow_move_constructible<value_t>::value&&
23508 std::is_nothrow_move_assignable<value_t>::value&&
23509 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23510 std::is_nothrow_move_assignable<json_value>::value
23511 )
23512 {
23513 left.swap(right);
23514 }
23515
23518 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23519 {
23520 // swap only works for arrays
23522 {
23523 using std::swap;
23524 swap(*(m_data.m_value.array), other);
23525 }
23526 else
23527 {
23528 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
23529 }
23530 }
23531
23534 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23535 {
23536 // swap only works for objects
23538 {
23539 using std::swap;
23540 swap(*(m_data.m_value.object), other);
23541 }
23542 else
23543 {
23544 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
23545 }
23546 }
23547
23550 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23551 {
23552 // swap only works for strings
23554 {
23555 using std::swap;
23556 swap(*(m_data.m_value.string), other);
23557 }
23558 else
23559 {
23560 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
23561 }
23562 }
23563
23566 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23567 {
23568 // swap only works for strings
23570 {
23571 using std::swap;
23572 swap(*(m_data.m_value.binary), other);
23573 }
23574 else
23575 {
23576 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
23577 }
23578 }
23579
23582 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
23583 {
23584 // swap only works for strings
23586 {
23587 using std::swap;
23588 swap(*(m_data.m_value.binary), other);
23589 }
23590 else
23591 {
23592 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
23593 }
23594 }
23595
23597
23599 // lexicographical comparison operators //
23601
23604
23605 // note parentheses around operands are necessary; see
23606 // https://github.com/nlohmann/json/issues/1530
23607#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
23608 const auto lhs_type = lhs.type(); \
23609 const auto rhs_type = rhs.type(); \
23610 \
23611 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
23612 { \
23613 switch (lhs_type) \
23614 { \
23615 case value_t::array: \
23616 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
23617 \
23618 case value_t::object: \
23619 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
23620 \
23621 case value_t::null: \
23622 return (null_result); \
23623 \
23624 case value_t::string: \
23625 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
23626 \
23627 case value_t::boolean: \
23628 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
23629 \
23630 case value_t::number_integer: \
23631 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
23632 \
23633 case value_t::number_unsigned: \
23634 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
23635 \
23636 case value_t::number_float: \
23637 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
23638 \
23639 case value_t::binary: \
23640 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
23641 \
23642 case value_t::discarded: \
23643 default: \
23644 return (unordered_result); \
23645 } \
23646 } \
23647 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
23648 { \
23649 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
23650 } \
23651 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
23652 { \
23653 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
23654 } \
23655 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
23656 { \
23657 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
23658 } \
23659 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
23660 { \
23661 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
23662 } \
23663 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
23664 { \
23665 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
23666 } \
23667 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
23668 { \
23669 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
23670 } \
23671 else if(compares_unordered(lhs, rhs))\
23672 {\
23673 return (unordered_result);\
23674 }\
23675 \
23676 return (default_result);
23677
23679 // returns true if:
23680 // - any operand is NaN and the other operand is of number type
23681 // - any operand is discarded
23682 // in legacy mode, discarded values are considered ordered if
23683 // an operation is computed as an odd number of inverses of others
23684 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
23685 {
23686 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
23687 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
23688 {
23689 return true;
23690 }
23691#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23692 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
23693#else
23694 static_cast<void>(inverse);
23695 return lhs.is_discarded() || rhs.is_discarded();
23696#endif
23697 }
23698
23699 private:
23700 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
23701 {
23702 return compares_unordered(*this, rhs, inverse);
23703 }
23704
23705 public:
23706#if JSON_HAS_THREE_WAY_COMPARISON
23709 bool operator==(const_reference rhs) const noexcept
23710 {
23711#ifdef __GNUC__
23712#pragma GCC diagnostic push
23713#pragma GCC diagnostic ignored "-Wfloat-equal"
23714#endif
23715 const_reference lhs = *this;
23716 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23717#ifdef __GNUC__
23718#pragma GCC diagnostic pop
23719#endif
23720 }
23721
23724 template<typename ScalarType>
23725 requires std::is_scalar_v<ScalarType>
23726 bool operator==(ScalarType rhs) const noexcept
23727 {
23728 return *this == basic_json(rhs);
23729 }
23730
23733 bool operator!=(const_reference rhs) const noexcept
23734 {
23735 if (compares_unordered(rhs, true))
23736 {
23737 return false;
23738 }
23739 return !operator==(rhs);
23740 }
23741
23744 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23745 {
23746 const_reference lhs = *this;
23747 // default_result is used if we cannot compare values. In that case,
23748 // we compare types.
23749 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23750 std::partial_ordering::equivalent,
23751 std::partial_ordering::unordered,
23752 lhs_type <=> rhs_type) // *NOPAD*
23753 }
23754
23757 template<typename ScalarType>
23758 requires std::is_scalar_v<ScalarType>
23759 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23760 {
23761 return *this <=> basic_json(rhs); // *NOPAD*
23762 }
23763
23764#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23765 // all operators that are computed as an odd number of inverses of others
23766 // need to be overloaded to emulate the legacy comparison behavior
23767
23771 bool operator<=(const_reference rhs) const noexcept
23772 {
23773 if (compares_unordered(rhs, true))
23774 {
23775 return false;
23776 }
23777 return !(rhs < *this);
23778 }
23779
23782 template<typename ScalarType>
23783 requires std::is_scalar_v<ScalarType>
23784 bool operator<=(ScalarType rhs) const noexcept
23785 {
23786 return *this <= basic_json(rhs);
23787 }
23788
23792 bool operator>=(const_reference rhs) const noexcept
23793 {
23794 if (compares_unordered(rhs, true))
23795 {
23796 return false;
23797 }
23798 return !(*this < rhs);
23799 }
23800
23803 template<typename ScalarType>
23804 requires std::is_scalar_v<ScalarType>
23805 bool operator>=(ScalarType rhs) const noexcept
23806 {
23807 return *this >= basic_json(rhs);
23808 }
23809#endif
23810#else
23813 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23814 {
23815#ifdef __GNUC__
23816#pragma GCC diagnostic push
23817#pragma GCC diagnostic ignored "-Wfloat-equal"
23818#endif
23819 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23820#ifdef __GNUC__
23821#pragma GCC diagnostic pop
23822#endif
23823 }
23824
23827 template<typename ScalarType, typename std::enable_if<
23828 std::is_scalar<ScalarType>::value, int>::type = 0>
23829 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23830 {
23831 return lhs == basic_json(rhs);
23832 }
23833
23836 template<typename ScalarType, typename std::enable_if<
23837 std::is_scalar<ScalarType>::value, int>::type = 0>
23838 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23839 {
23840 return basic_json(lhs) == rhs;
23841 }
23842
23845 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23846 {
23847 if (compares_unordered(lhs, rhs, true))
23848 {
23849 return false;
23850 }
23851 return !(lhs == rhs);
23852 }
23853
23856 template<typename ScalarType, typename std::enable_if<
23857 std::is_scalar<ScalarType>::value, int>::type = 0>
23858 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23859 {
23860 return lhs != basic_json(rhs);
23861 }
23862
23865 template<typename ScalarType, typename std::enable_if<
23866 std::is_scalar<ScalarType>::value, int>::type = 0>
23867 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23868 {
23869 return basic_json(lhs) != rhs;
23870 }
23871
23874 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23875 {
23876 // default_result is used if we cannot compare values. In that case,
23877 // we compare types. Note we have to call the operator explicitly,
23878 // because MSVC has problems otherwise.
23879 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23880 }
23881
23884 template<typename ScalarType, typename std::enable_if<
23885 std::is_scalar<ScalarType>::value, int>::type = 0>
23886 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23887 {
23888 return lhs < basic_json(rhs);
23889 }
23890
23893 template<typename ScalarType, typename std::enable_if<
23894 std::is_scalar<ScalarType>::value, int>::type = 0>
23895 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23896 {
23897 return basic_json(lhs) < rhs;
23898 }
23899
23902 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23903 {
23904 if (compares_unordered(lhs, rhs, true))
23905 {
23906 return false;
23907 }
23908 return !(rhs < lhs);
23909 }
23910
23913 template<typename ScalarType, typename std::enable_if<
23914 std::is_scalar<ScalarType>::value, int>::type = 0>
23915 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23916 {
23917 return lhs <= basic_json(rhs);
23918 }
23919
23922 template<typename ScalarType, typename std::enable_if<
23923 std::is_scalar<ScalarType>::value, int>::type = 0>
23924 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23925 {
23926 return basic_json(lhs) <= rhs;
23927 }
23928
23931 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
23932 {
23933 // double inverse
23934 if (compares_unordered(lhs, rhs))
23935 {
23936 return false;
23937 }
23938 return !(lhs <= rhs);
23939 }
23940
23943 template<typename ScalarType, typename std::enable_if<
23944 std::is_scalar<ScalarType>::value, int>::type = 0>
23945 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
23946 {
23947 return lhs > basic_json(rhs);
23948 }
23949
23952 template<typename ScalarType, typename std::enable_if<
23953 std::is_scalar<ScalarType>::value, int>::type = 0>
23954 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
23955 {
23956 return basic_json(lhs) > rhs;
23957 }
23958
23961 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
23962 {
23963 if (compares_unordered(lhs, rhs, true))
23964 {
23965 return false;
23966 }
23967 return !(lhs < rhs);
23968 }
23969
23972 template<typename ScalarType, typename std::enable_if<
23973 std::is_scalar<ScalarType>::value, int>::type = 0>
23974 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
23975 {
23976 return lhs >= basic_json(rhs);
23977 }
23978
23981 template<typename ScalarType, typename std::enable_if<
23982 std::is_scalar<ScalarType>::value, int>::type = 0>
23983 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
23984 {
23985 return basic_json(lhs) >= rhs;
23986 }
23987#endif
23988
23989#undef JSON_IMPLEMENT_OPERATOR
23990
23992
23994 // serialization //
23996
23999#ifndef JSON_NO_IO
24002 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
24003 {
24004 // read width member and use it as indentation parameter if nonzero
24005 const bool pretty_print = o.width() > 0;
24006 const auto indentation = pretty_print ? o.width() : 0;
24007
24008 // reset width to 0 for subsequent calls to this stream
24009 o.width(0);
24010
24011 // do the actual serialization
24012 serializer s(detail::output_adapter<char>(o), o.fill());
24013 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
24014 return o;
24015 }
24016
24023 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
24024 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
24025 {
24026 return o << j;
24027 }
24028#endif // JSON_NO_IO
24030
24032 // deserialization //
24034
24037
24040 template<typename InputType>
24042 static basic_json parse(InputType&& i,
24043 parser_callback_t cb = nullptr,
24044 const bool allow_exceptions = true,
24045 const bool ignore_comments = false)
24046 {
24047 basic_json result;
24048 parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved,accessForwarded]
24049 return result;
24050 }
24051
24054 template<typename IteratorType>
24056 static basic_json parse(IteratorType first,
24057 IteratorType last,
24058 parser_callback_t cb = nullptr,
24059 const bool allow_exceptions = true,
24060 const bool ignore_comments = false)
24061 {
24062 basic_json result;
24063 parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved]
24064 return result;
24065 }
24066
24068 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
24069 static basic_json parse(detail::span_input_adapter&& i,
24070 parser_callback_t cb = nullptr,
24071 const bool allow_exceptions = true,
24072 const bool ignore_comments = false)
24073 {
24074 basic_json result;
24075 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved]
24076 return result;
24077 }
24078
24081 template<typename InputType>
24082 static bool accept(InputType&& i,
24083 const bool ignore_comments = false)
24084 {
24085 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
24086 }
24087
24090 template<typename IteratorType>
24091 static bool accept(IteratorType first, IteratorType last,
24092 const bool ignore_comments = false)
24093 {
24094 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
24095 }
24096
24098 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
24099 static bool accept(detail::span_input_adapter&& i,
24100 const bool ignore_comments = false)
24101 {
24102 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
24103 }
24104
24107 template <typename InputType, typename SAX>
24109 static bool sax_parse(InputType&& i, SAX* sax,
24111 const bool strict = true,
24112 const bool ignore_comments = false)
24113 {
24114 auto ia = detail::input_adapter(std::forward<InputType>(i));
24115 return format == input_format_t::json
24116 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
24117 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24118 }
24119
24122 template<class IteratorType, class SAX>
24124 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
24126 const bool strict = true,
24127 const bool ignore_comments = false)
24128 {
24129 auto ia = detail::input_adapter(std::move(first), std::move(last));
24130 return format == input_format_t::json
24131 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
24132 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24133 }
24134
24140 template <typename SAX>
24141 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
24143 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
24145 const bool strict = true,
24146 const bool ignore_comments = false)
24147 {
24148 auto ia = i.get();
24149 return format == input_format_t::json
24150 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24151 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
24152 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24153 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24154 }
24155#ifndef JSON_NO_IO
24162 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
24163 friend std::istream& operator<<(basic_json& j, std::istream& i)
24164 {
24165 return operator>>(i, j);
24166 }
24167
24170 friend std::istream& operator>>(std::istream& i, basic_json& j)
24171 {
24172 parser(detail::input_adapter(i)).parse(false, j);
24173 return i;
24174 }
24175#endif // JSON_NO_IO
24177
24179 // convenience functions //
24181
24185 const char* type_name() const noexcept
24186 {
24187 switch (m_data.m_type)
24188 {
24189 case value_t::null:
24190 return "null";
24191 case value_t::object:
24192 return "object";
24193 case value_t::array:
24194 return "array";
24195 case value_t::string:
24196 return "string";
24197 case value_t::boolean:
24198 return "boolean";
24199 case value_t::binary:
24200 return "binary";
24201 case value_t::discarded:
24202 return "discarded";
24203 case value_t::number_integer:
24204 case value_t::number_unsigned:
24205 case value_t::number_float:
24206 default:
24207 return "number";
24208 }
24209 }
24210
24213 // member variables //
24215
24216 struct data
24217 {
24219 value_t m_type = value_t::null;
24220
24223
24224 data(const value_t v)
24225 : m_type(v), m_value(v)
24226 {
24227 }
24228
24229 data(size_type cnt, const basic_json& val)
24230 : m_type(value_t::array)
24231 {
24232 m_value.array = create<array_t>(cnt, val);
24233 }
24234
24235 data() noexcept = default;
24236 data(data&&) noexcept = default;
24237 data(const data&) noexcept = delete;
24238 data& operator=(data&&) noexcept = delete;
24239 data& operator=(const data&) noexcept = delete;
24240
24241 ~data() noexcept
24242 {
24243 m_value.destroy(m_type);
24244 }
24245 };
24246
24248
24249#if JSON_DIAGNOSTICS
24251 basic_json* m_parent = nullptr;
24252#endif
24253
24254#if JSON_DIAGNOSTIC_POSITIONS
24256 std::size_t start_position = std::string::npos;
24258 std::size_t end_position = std::string::npos;
24259 public:
24260 constexpr std::size_t start_pos() const noexcept
24261 {
24262 return start_position;
24263 }
24264
24265 constexpr std::size_t end_pos() const noexcept
24266 {
24267 return end_position;
24268 }
24269#endif
24270
24272 // binary serialization/deserialization //
24274
24277
24278 public:
24281 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
24282 {
24283 std::vector<std::uint8_t> result;
24284 to_cbor(j, result);
24285 return result;
24286 }
24287
24291 {
24292 binary_writer<std::uint8_t>(o).write_cbor(j);
24293 }
24294
24298 {
24299 binary_writer<char>(o).write_cbor(j);
24300 }
24301
24304 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
24305 {
24306 std::vector<std::uint8_t> result;
24307 to_msgpack(j, result);
24308 return result;
24309 }
24310
24314 {
24315 binary_writer<std::uint8_t>(o).write_msgpack(j);
24316 }
24317
24321 {
24322 binary_writer<char>(o).write_msgpack(j);
24323 }
24324
24327 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
24328 const bool use_size = false,
24329 const bool use_type = false)
24330 {
24331 std::vector<std::uint8_t> result;
24332 to_ubjson(j, result, use_size, use_type);
24333 return result;
24334 }
24335
24339 const bool use_size = false, const bool use_type = false)
24340 {
24341 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
24342 }
24343
24347 const bool use_size = false, const bool use_type = false)
24348 {
24349 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
24350 }
24351
24354 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
24355 const bool use_size = false,
24356 const bool use_type = false,
24357 const bjdata_version_t version = bjdata_version_t::draft2)
24358 {
24359 std::vector<std::uint8_t> result;
24360 to_bjdata(j, result, use_size, use_type, version);
24361 return result;
24362 }
24363
24367 const bool use_size = false, const bool use_type = false,
24368 const bjdata_version_t version = bjdata_version_t::draft2)
24369 {
24370 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true, version);
24371 }
24372
24376 const bool use_size = false, const bool use_type = false,
24377 const bjdata_version_t version = bjdata_version_t::draft2)
24378 {
24379 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true, version);
24380 }
24381
24384 static std::vector<std::uint8_t> to_bson(const basic_json& j)
24385 {
24386 std::vector<std::uint8_t> result;
24387 to_bson(j, result);
24388 return result;
24389 }
24390
24394 {
24395 binary_writer<std::uint8_t>(o).write_bson(j);
24396 }
24397
24401 {
24402 binary_writer<char>(o).write_bson(j);
24403 }
24404
24407 template<typename InputType>
24409 static basic_json from_cbor(InputType&& i,
24410 const bool strict = true,
24411 const bool allow_exceptions = true,
24412 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24413 {
24414 basic_json result;
24415 auto ia = detail::input_adapter(std::forward<InputType>(i));
24416 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24417 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]
24418 return res ? result : basic_json(value_t::discarded);
24419 }
24420
24423 template<typename IteratorType>
24425 static basic_json from_cbor(IteratorType first, IteratorType last,
24426 const bool strict = true,
24427 const bool allow_exceptions = true,
24428 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24429 {
24430 basic_json result;
24431 auto ia = detail::input_adapter(std::move(first), std::move(last));
24432 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24433 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]
24434 return res ? result : basic_json(value_t::discarded);
24435 }
24436
24437 template<typename T>
24439 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24440 static basic_json from_cbor(const T* ptr, std::size_t len,
24441 const bool strict = true,
24442 const bool allow_exceptions = true,
24443 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24444 {
24445 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
24446 }
24447
24449 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24450 static basic_json from_cbor(detail::span_input_adapter&& i,
24451 const bool strict = true,
24452 const bool allow_exceptions = true,
24453 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24454 {
24455 basic_json result;
24456 auto ia = i.get();
24457 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24458 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24459 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]
24460 return res ? result : basic_json(value_t::discarded);
24461 }
24462
24465 template<typename InputType>
24467 static basic_json from_msgpack(InputType&& i,
24468 const bool strict = true,
24469 const bool allow_exceptions = true)
24470 {
24471 basic_json result;
24472 auto ia = detail::input_adapter(std::forward<InputType>(i));
24473 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24474 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]
24475 return res ? result : basic_json(value_t::discarded);
24476 }
24477
24480 template<typename IteratorType>
24482 static basic_json from_msgpack(IteratorType first, IteratorType last,
24483 const bool strict = true,
24484 const bool allow_exceptions = true)
24485 {
24486 basic_json result;
24487 auto ia = detail::input_adapter(std::move(first), std::move(last));
24488 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24489 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
24490 return res ? result : basic_json(value_t::discarded);
24491 }
24492
24493 template<typename T>
24495 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24496 static basic_json from_msgpack(const T* ptr, std::size_t len,
24497 const bool strict = true,
24498 const bool allow_exceptions = true)
24499 {
24500 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
24501 }
24502
24504 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24505 static basic_json from_msgpack(detail::span_input_adapter&& i,
24506 const bool strict = true,
24507 const bool allow_exceptions = true)
24508 {
24509 basic_json result;
24510 auto ia = i.get();
24511 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24512 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24513 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]
24514 return res ? result : basic_json(value_t::discarded);
24515 }
24516
24519 template<typename InputType>
24521 static basic_json from_ubjson(InputType&& i,
24522 const bool strict = true,
24523 const bool allow_exceptions = true)
24524 {
24525 basic_json result;
24526 auto ia = detail::input_adapter(std::forward<InputType>(i));
24527 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24528 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]
24529 return res ? result : basic_json(value_t::discarded);
24530 }
24531
24534 template<typename IteratorType>
24536 static basic_json from_ubjson(IteratorType first, IteratorType last,
24537 const bool strict = true,
24538 const bool allow_exceptions = true)
24539 {
24540 basic_json result;
24541 auto ia = detail::input_adapter(std::move(first), std::move(last));
24542 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24543 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
24544 return res ? result : basic_json(value_t::discarded);
24545 }
24546
24547 template<typename T>
24549 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24550 static basic_json from_ubjson(const T* ptr, std::size_t len,
24551 const bool strict = true,
24552 const bool allow_exceptions = true)
24553 {
24554 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24555 }
24556
24558 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24559 static basic_json from_ubjson(detail::span_input_adapter&& i,
24560 const bool strict = true,
24561 const bool allow_exceptions = true)
24562 {
24563 basic_json result;
24564 auto ia = i.get();
24565 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24566 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24567 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]
24568 return res ? result : basic_json(value_t::discarded);
24569 }
24570
24573 template<typename InputType>
24575 static basic_json from_bjdata(InputType&& i,
24576 const bool strict = true,
24577 const bool allow_exceptions = true)
24578 {
24579 basic_json result;
24580 auto ia = detail::input_adapter(std::forward<InputType>(i));
24581 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24582 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]
24583 return res ? result : basic_json(value_t::discarded);
24584 }
24585
24588 template<typename IteratorType>
24590 static basic_json from_bjdata(IteratorType first, IteratorType last,
24591 const bool strict = true,
24592 const bool allow_exceptions = true)
24593 {
24594 basic_json result;
24595 auto ia = detail::input_adapter(std::move(first), std::move(last));
24596 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24597 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
24598 return res ? result : basic_json(value_t::discarded);
24599 }
24600
24603 template<typename InputType>
24605 static basic_json from_bson(InputType&& i,
24606 const bool strict = true,
24607 const bool allow_exceptions = true)
24608 {
24609 basic_json result;
24610 auto ia = detail::input_adapter(std::forward<InputType>(i));
24611 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24612 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
24613 return res ? result : basic_json(value_t::discarded);
24614 }
24615
24618 template<typename IteratorType>
24620 static basic_json from_bson(IteratorType first, IteratorType last,
24621 const bool strict = true,
24622 const bool allow_exceptions = true)
24623 {
24624 basic_json result;
24625 auto ia = detail::input_adapter(std::move(first), std::move(last));
24626 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24627 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
24628 return res ? result : basic_json(value_t::discarded);
24629 }
24630
24631 template<typename T>
24633 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24634 static basic_json from_bson(const T* ptr, std::size_t len,
24635 const bool strict = true,
24636 const bool allow_exceptions = true)
24637 {
24638 return from_bson(ptr, ptr + len, strict, allow_exceptions);
24639 }
24640
24642 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24643 static basic_json from_bson(detail::span_input_adapter&& i,
24644 const bool strict = true,
24645 const bool allow_exceptions = true)
24646 {
24647 basic_json result;
24648 auto ia = i.get();
24649 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24650 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24651 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]
24652 return res ? result : basic_json(value_t::discarded);
24653 }
24654
24655
24657 // JSON Pointer support //
24659
24662
24666 {
24667 return ptr.get_unchecked(this);
24668 }
24669
24670 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24671 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24672 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24673 {
24674 return ptr.get_unchecked(this);
24675 }
24676
24680 {
24681 return ptr.get_unchecked(this);
24682 }
24683
24684 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24685 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24686 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24687 {
24688 return ptr.get_unchecked(this);
24689 }
24690
24694 {
24695 return ptr.get_checked(this);
24696 }
24697
24698 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24699 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24700 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24701 {
24702 return ptr.get_checked(this);
24703 }
24704
24708 {
24709 return ptr.get_checked(this);
24710 }
24711
24712 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24713 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24714 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24715 {
24716 return ptr.get_checked(this);
24717 }
24718
24722 {
24723 basic_json result(value_t::object);
24724 json_pointer::flatten("", *this, result);
24725 return result;
24726 }
24727
24731 {
24732 return json_pointer::unflatten(*this);
24733 }
24734
24736
24738 // JSON Patch functions //
24740
24743
24746 void patch_inplace(const basic_json& json_patch)
24747 {
24748 basic_json& result = *this;
24749 // the valid JSON Patch operations
24750 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24751
24752 const auto get_op = [](const string_t& op)
24753 {
24754 if (op == "add")
24755 {
24756 return patch_operations::add;
24757 }
24758 if (op == "remove")
24759 {
24760 return patch_operations::remove;
24761 }
24762 if (op == "replace")
24763 {
24764 return patch_operations::replace;
24765 }
24766 if (op == "move")
24767 {
24768 return patch_operations::move;
24769 }
24770 if (op == "copy")
24771 {
24772 return patch_operations::copy;
24773 }
24774 if (op == "test")
24775 {
24776 return patch_operations::test;
24777 }
24778
24779 return patch_operations::invalid;
24780 };
24781
24782 // wrapper for "add" operation; add value at ptr
24783 const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
24784 {
24785 // adding to the root of the target document means replacing it
24786 if (ptr.empty())
24787 {
24788 result = val;
24789 return;
24790 }
24791
24792 // make sure the top element of the pointer exists
24793 json_pointer const top_pointer = ptr.top();
24794 if (top_pointer != ptr)
24795 {
24796 result.at(top_pointer);
24797 }
24798
24799 // get reference to parent of JSON pointer ptr
24800 const auto last_path = ptr.back();
24801 ptr.pop_back();
24802 // parent must exist when performing patch add per RFC6902 specs
24803 basic_json& parent = result.at(ptr);
24804
24805 switch (parent.m_data.m_type)
24806 {
24807 case value_t::null:
24808 case value_t::object:
24809 {
24810 // use operator[] to add value
24811 parent[last_path] = val;
24812 break;
24813 }
24814
24815 case value_t::array:
24816 {
24817 if (last_path == "-")
24818 {
24819 // special case: append to back
24820 parent.push_back(val);
24821 }
24822 else
24823 {
24824 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24825 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24826 {
24827 // avoid undefined behavior
24828 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24829 }
24830
24831 // default case: insert add offset
24832 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24833 }
24834 break;
24835 }
24836
24837 // if there exists a parent it cannot be primitive
24838 case value_t::string: // LCOV_EXCL_LINE
24839 case value_t::boolean: // LCOV_EXCL_LINE
24840 case value_t::number_integer: // LCOV_EXCL_LINE
24841 case value_t::number_unsigned: // LCOV_EXCL_LINE
24842 case value_t::number_float: // LCOV_EXCL_LINE
24843 case value_t::binary: // LCOV_EXCL_LINE
24844 case value_t::discarded: // LCOV_EXCL_LINE
24845 default: // LCOV_EXCL_LINE
24846 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24847 }
24848 };
24849
24850 // wrapper for "remove" operation; remove value at ptr
24851 const auto operation_remove = [this, & result](json_pointer & ptr)
24852 {
24853 // get reference to parent of JSON pointer ptr
24854 const auto last_path = ptr.back();
24855 ptr.pop_back();
24856 basic_json& parent = result.at(ptr);
24857
24858 // remove child
24859 if (parent.is_object())
24860 {
24861 // perform range check
24862 auto it = parent.find(last_path);
24863 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24864 {
24865 parent.erase(it);
24866 }
24867 else
24868 {
24869 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24870 }
24871 }
24872 else if (parent.is_array())
24873 {
24874 // note erase performs range check
24875 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24876 }
24877 };
24878
24879 // type check: top level value must be an array
24880 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24881 {
24882 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24883 }
24884
24885 // iterate and apply the operations
24886 for (const auto& val : json_patch)
24887 {
24888 // wrapper to get a value for an operation
24889 const auto get_value = [&val](const string_t& op,
24890 const string_t& member,
24891 bool string_type) -> basic_json &
24892 {
24893 // find value
24894 auto it = val.m_data.m_value.object->find(member);
24895
24896 // context-sensitive error message
24897 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
24898
24899 // check if desired value is present
24900 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24901 {
24902 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24903 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24904 }
24905
24906 // check if result is of type string
24907 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24908 {
24909 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24910 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24911 }
24912
24913 // no error: return value
24914 return it->second;
24915 };
24916
24917 // type check: every element of the array must be an object
24918 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24919 {
24920 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24921 }
24922
24923 // collect mandatory members
24924 const auto op = get_value("op", "op", true).template get<string_t>();
24925 const auto path = get_value(op, "path", true).template get<string_t>();
24926 json_pointer ptr(path);
24927
24928 switch (get_op(op))
24929 {
24930 case patch_operations::add:
24931 {
24932 operation_add(ptr, get_value("add", "value", false));
24933 break;
24934 }
24935
24936 case patch_operations::remove:
24937 {
24938 operation_remove(ptr);
24939 break;
24940 }
24941
24942 case patch_operations::replace:
24943 {
24944 // the "path" location must exist - use at()
24945 result.at(ptr) = get_value("replace", "value", false);
24946 break;
24947 }
24948
24949 case patch_operations::move:
24950 {
24951 const auto from_path = get_value("move", "from", true).template get<string_t>();
24952 json_pointer from_ptr(from_path);
24953
24954 // the "from" location must exist - use at()
24955 basic_json const v = result.at(from_ptr);
24956
24957 // The move operation is functionally identical to a
24958 // "remove" operation on the "from" location, followed
24959 // immediately by an "add" operation at the target
24960 // location with the value that was just removed.
24961 operation_remove(from_ptr);
24962 operation_add(ptr, v);
24963 break;
24964 }
24965
24966 case patch_operations::copy:
24967 {
24968 const auto from_path = get_value("copy", "from", true).template get<string_t>();
24969 const json_pointer from_ptr(from_path);
24970
24971 // the "from" location must exist - use at()
24972 basic_json const v = result.at(from_ptr);
24973
24974 // The copy is functionally identical to an "add"
24975 // operation at the target location using the value
24976 // specified in the "from" member.
24977 operation_add(ptr, v);
24978 break;
24979 }
24980
24981 case patch_operations::test:
24982 {
24983 bool success = false;
24984 JSON_TRY
24985 {
24986 // check if "value" matches the one at "path"
24987 // the "path" location must exist - use at()
24988 success = (result.at(ptr) == get_value("test", "value", false));
24989 }
24991 {
24992 // ignore out of range errors: success remains false
24993 }
24994
24995 // throw an exception if test fails
24996 if (JSON_HEDLEY_UNLIKELY(!success))
24997 {
24998 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
24999 }
25000
25001 break;
25002 }
25003
25004 case patch_operations::invalid:
25005 default:
25006 {
25007 // op must be "add", "remove", "replace", "move", "copy", or
25008 // "test"
25009 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
25010 }
25011 }
25012 }
25013 }
25014
25017 basic_json patch(const basic_json& json_patch) const
25018 {
25019 basic_json result = *this;
25020 result.patch_inplace(json_patch);
25021 return result;
25022 }
25023
25027 static basic_json diff(const basic_json& source, const basic_json& target,
25028 const string_t& path = "")
25029 {
25030 // the patch
25031 basic_json result(value_t::array);
25032
25033 // if the values are the same, return empty patch
25034 if (source == target)
25035 {
25036 return result;
25037 }
25038
25039 if (source.type() != target.type())
25040 {
25041 // different types: replace value
25042 result.push_back(
25043 {
25044 {"op", "replace"}, {"path", path}, {"value", target}
25045 });
25046 return result;
25047 }
25048
25049 switch (source.type())
25050 {
25051 case value_t::array:
25052 {
25053 // first pass: traverse common elements
25054 std::size_t i = 0;
25055 while (i < source.size() && i < target.size())
25056 {
25057 // recursive call to compare array values at index i
25058 auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
25059 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25060 ++i;
25061 }
25062
25063 // We now reached the end of at least one array
25064 // in a second pass, traverse the remaining elements
25065
25066 // remove my remaining elements
25067 const auto end_index = static_cast<difference_type>(result.size());
25068 while (i < source.size())
25069 {
25070 // add operations in reverse order to avoid invalid
25071 // indices
25072 result.insert(result.begin() + end_index, object(
25073 {
25074 {"op", "remove"},
25075 {"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
25076 }));
25077 ++i;
25078 }
25079
25080 // add other remaining elements
25081 while (i < target.size())
25082 {
25083 result.push_back(
25084 {
25085 {"op", "add"},
25086 {"path", detail::concat<string_t>(path, "/-")},
25087 {"value", target[i]}
25088 });
25089 ++i;
25090 }
25091
25092 break;
25093 }
25094
25095 case value_t::object:
25096 {
25097 // first pass: traverse this object's elements
25098 for (auto it = source.cbegin(); it != source.cend(); ++it)
25099 {
25100 // escape the key name to be used in a JSON patch
25101 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25102
25103 if (target.find(it.key()) != target.end())
25104 {
25105 // recursive call to compare object values at key it
25106 auto temp_diff = diff(it.value(), target[it.key()], path_key);
25107 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25108 }
25109 else
25110 {
25111 // found a key that is not in o -> remove it
25112 result.push_back(object(
25113 {
25114 {"op", "remove"}, {"path", path_key}
25115 }));
25116 }
25117 }
25118
25119 // second pass: traverse other object's elements
25120 for (auto it = target.cbegin(); it != target.cend(); ++it)
25121 {
25122 if (source.find(it.key()) == source.end())
25123 {
25124 // found a key that is not in this -> add it
25125 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25126 result.push_back(
25127 {
25128 {"op", "add"}, {"path", path_key},
25129 {"value", it.value()}
25130 });
25131 }
25132 }
25133
25134 break;
25135 }
25136
25137 case value_t::null:
25138 case value_t::string:
25139 case value_t::boolean:
25140 case value_t::number_integer:
25141 case value_t::number_unsigned:
25142 case value_t::number_float:
25143 case value_t::binary:
25144 case value_t::discarded:
25145 default:
25146 {
25147 // both primitive type: replace value
25148 result.push_back(
25149 {
25150 {"op", "replace"}, {"path", path}, {"value", target}
25151 });
25152 break;
25153 }
25154 }
25155
25156 return result;
25157 }
25158
25159
25161 // JSON Merge Patch functions //
25163
25166
25169 void merge_patch(const basic_json& apply_patch)
25170 {
25171 if (apply_patch.is_object())
25172 {
25173 if (!is_object())
25174 {
25175 *this = object();
25176 }
25177 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
25178 {
25179 if (it.value().is_null())
25180 {
25181 erase(it.key());
25182 }
25183 else
25184 {
25185 operator[](it.key()).merge_patch(it.value());
25186 }
25187 }
25188 }
25189 else
25190 {
25191 *this = apply_patch;
25192 }
25193 }
25194
25196};
25197
25202{
25203 return j.dump();
25204}
25205
25206inline namespace literals
25207{
25208inline namespace json_literals
25209{
25210
25214#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25215 inline nlohmann::json operator ""_json(const char* s, std::size_t n)
25216#else
25217 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
25218#endif
25219{
25220 return nlohmann::json::parse(s, s + n);
25221}
25222
25226#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25227 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
25228#else
25229 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
25230#endif
25231{
25232 return nlohmann::json::json_pointer(std::string(s, n));
25233}
25234
25235} // namespace json_literals
25236} // namespace literals
25238
25240// nonmember support //
25242
25243namespace std // NOLINT(cert-dcl58-cpp)
25244{
25245
25249struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
25250{
25251 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
25252 {
25253 return nlohmann::detail::hash(j);
25254 }
25255};
25256
25257// specialization for std::less<value_t>
25258template<>
25259struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
25260{
25265 bool operator()(::nlohmann::detail::value_t lhs,
25266 ::nlohmann::detail::value_t rhs) const noexcept
25267 {
25268#if JSON_HAS_THREE_WAY_COMPARISON
25269 return std::is_lt(lhs <=> rhs); // *NOPAD*
25270#else
25271 return ::nlohmann::detail::operator<(lhs, rhs);
25272#endif
25273 }
25274};
25275
25276// C++20 prohibit function specialization in the std namespace.
25277#ifndef JSON_HAS_CPP_20
25278
25282inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
25283 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
25284 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
25285{
25286 j1.swap(j2);
25287}
25288
25289#endif
25290
25291} // namespace std
25292
25293#if JSON_USE_GLOBAL_UDLS
25294 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25295 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25296 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25297 #else
25298 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25299 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25300 #endif
25301#endif
25302
25303// #include <nlohmann/detail/macro_unscope.hpp>
25304// __ _____ _____ _____
25305// __| | __| | | | JSON for Modern C++
25306// | | |__ | | | | | | version 3.11.3
25307// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25308//
25309// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25310// SPDX-License-Identifier: MIT
25311
25312
25313
25314// restore clang diagnostic settings
25315#if defined(__clang__)
25316 #pragma clang diagnostic pop
25317#endif
25318
25319// clean up
25320#undef JSON_ASSERT
25321#undef JSON_INTERNAL_CATCH
25322#undef JSON_THROW
25323#undef JSON_PRIVATE_UNLESS_TESTED
25324#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
25325#undef NLOHMANN_BASIC_JSON_TPL
25326#undef JSON_EXPLICIT
25327#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
25328#undef JSON_INLINE_VARIABLE
25329#undef JSON_NO_UNIQUE_ADDRESS
25330#undef JSON_DISABLE_ENUM_SERIALIZATION
25331#undef JSON_USE_GLOBAL_UDLS
25332
25333#ifndef JSON_TEST_KEEP_MACROS
25334 #undef JSON_CATCH
25335 #undef JSON_TRY
25336 #undef JSON_HAS_CPP_11
25337 #undef JSON_HAS_CPP_14
25338 #undef JSON_HAS_CPP_17
25339 #undef JSON_HAS_CPP_20
25340 #undef JSON_HAS_FILESYSTEM
25341 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
25342 #undef JSON_HAS_THREE_WAY_COMPARISON
25343 #undef JSON_HAS_RANGES
25344 #undef JSON_HAS_STATIC_RTTI
25345 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
25346#endif
25347
25348// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
25349// __ _____ _____ _____
25350// __| | __| | | | JSON for Modern C++
25351// | | |__ | | | | | | version 3.11.3
25352// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25353//
25354// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25355// SPDX-License-Identifier: MIT
25356
25357
25358
25359#undef JSON_HEDLEY_ALWAYS_INLINE
25360#undef JSON_HEDLEY_ARM_VERSION
25361#undef JSON_HEDLEY_ARM_VERSION_CHECK
25362#undef JSON_HEDLEY_ARRAY_PARAM
25363#undef JSON_HEDLEY_ASSUME
25364#undef JSON_HEDLEY_BEGIN_C_DECLS
25365#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
25366#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
25367#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
25368#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
25369#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
25370#undef JSON_HEDLEY_CLANG_HAS_FEATURE
25371#undef JSON_HEDLEY_CLANG_HAS_WARNING
25372#undef JSON_HEDLEY_COMPCERT_VERSION
25373#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
25374#undef JSON_HEDLEY_CONCAT
25375#undef JSON_HEDLEY_CONCAT3
25376#undef JSON_HEDLEY_CONCAT3_EX
25377#undef JSON_HEDLEY_CONCAT_EX
25378#undef JSON_HEDLEY_CONST
25379#undef JSON_HEDLEY_CONSTEXPR
25380#undef JSON_HEDLEY_CONST_CAST
25381#undef JSON_HEDLEY_CPP_CAST
25382#undef JSON_HEDLEY_CRAY_VERSION
25383#undef JSON_HEDLEY_CRAY_VERSION_CHECK
25384#undef JSON_HEDLEY_C_DECL
25385#undef JSON_HEDLEY_DEPRECATED
25386#undef JSON_HEDLEY_DEPRECATED_FOR
25387#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
25388#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
25389#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
25390#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
25391#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
25392#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
25393#undef JSON_HEDLEY_DIAGNOSTIC_POP
25394#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
25395#undef JSON_HEDLEY_DMC_VERSION
25396#undef JSON_HEDLEY_DMC_VERSION_CHECK
25397#undef JSON_HEDLEY_EMPTY_BASES
25398#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
25399#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
25400#undef JSON_HEDLEY_END_C_DECLS
25401#undef JSON_HEDLEY_FLAGS
25402#undef JSON_HEDLEY_FLAGS_CAST
25403#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
25404#undef JSON_HEDLEY_GCC_HAS_BUILTIN
25405#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
25406#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
25407#undef JSON_HEDLEY_GCC_HAS_EXTENSION
25408#undef JSON_HEDLEY_GCC_HAS_FEATURE
25409#undef JSON_HEDLEY_GCC_HAS_WARNING
25410#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
25411#undef JSON_HEDLEY_GCC_VERSION
25412#undef JSON_HEDLEY_GCC_VERSION_CHECK
25413#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
25414#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
25415#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
25416#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
25417#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
25418#undef JSON_HEDLEY_GNUC_HAS_FEATURE
25419#undef JSON_HEDLEY_GNUC_HAS_WARNING
25420#undef JSON_HEDLEY_GNUC_VERSION
25421#undef JSON_HEDLEY_GNUC_VERSION_CHECK
25422#undef JSON_HEDLEY_HAS_ATTRIBUTE
25423#undef JSON_HEDLEY_HAS_BUILTIN
25424#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
25425#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
25426#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
25427#undef JSON_HEDLEY_HAS_EXTENSION
25428#undef JSON_HEDLEY_HAS_FEATURE
25429#undef JSON_HEDLEY_HAS_WARNING
25430#undef JSON_HEDLEY_IAR_VERSION
25431#undef JSON_HEDLEY_IAR_VERSION_CHECK
25432#undef JSON_HEDLEY_IBM_VERSION
25433#undef JSON_HEDLEY_IBM_VERSION_CHECK
25434#undef JSON_HEDLEY_IMPORT
25435#undef JSON_HEDLEY_INLINE
25436#undef JSON_HEDLEY_INTEL_CL_VERSION
25437#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
25438#undef JSON_HEDLEY_INTEL_VERSION
25439#undef JSON_HEDLEY_INTEL_VERSION_CHECK
25440#undef JSON_HEDLEY_IS_CONSTANT
25441#undef JSON_HEDLEY_IS_CONSTEXPR_
25442#undef JSON_HEDLEY_LIKELY
25443#undef JSON_HEDLEY_MALLOC
25444#undef JSON_HEDLEY_MCST_LCC_VERSION
25445#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
25446#undef JSON_HEDLEY_MESSAGE
25447#undef JSON_HEDLEY_MSVC_VERSION
25448#undef JSON_HEDLEY_MSVC_VERSION_CHECK
25449#undef JSON_HEDLEY_NEVER_INLINE
25450#undef JSON_HEDLEY_NON_NULL
25451#undef JSON_HEDLEY_NO_ESCAPE
25452#undef JSON_HEDLEY_NO_RETURN
25453#undef JSON_HEDLEY_NO_THROW
25454#undef JSON_HEDLEY_NULL
25455#undef JSON_HEDLEY_PELLES_VERSION
25456#undef JSON_HEDLEY_PELLES_VERSION_CHECK
25457#undef JSON_HEDLEY_PGI_VERSION
25458#undef JSON_HEDLEY_PGI_VERSION_CHECK
25459#undef JSON_HEDLEY_PREDICT
25460#undef JSON_HEDLEY_PRINTF_FORMAT
25461#undef JSON_HEDLEY_PRIVATE
25462#undef JSON_HEDLEY_PUBLIC
25463#undef JSON_HEDLEY_PURE
25464#undef JSON_HEDLEY_REINTERPRET_CAST
25465#undef JSON_HEDLEY_REQUIRE
25466#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
25467#undef JSON_HEDLEY_REQUIRE_MSG
25468#undef JSON_HEDLEY_RESTRICT
25469#undef JSON_HEDLEY_RETURNS_NON_NULL
25470#undef JSON_HEDLEY_SENTINEL
25471#undef JSON_HEDLEY_STATIC_ASSERT
25472#undef JSON_HEDLEY_STATIC_CAST
25473#undef JSON_HEDLEY_STRINGIFY
25474#undef JSON_HEDLEY_STRINGIFY_EX
25475#undef JSON_HEDLEY_SUNPRO_VERSION
25476#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
25477#undef JSON_HEDLEY_TINYC_VERSION
25478#undef JSON_HEDLEY_TINYC_VERSION_CHECK
25479#undef JSON_HEDLEY_TI_ARMCL_VERSION
25480#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
25481#undef JSON_HEDLEY_TI_CL2000_VERSION
25482#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
25483#undef JSON_HEDLEY_TI_CL430_VERSION
25484#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
25485#undef JSON_HEDLEY_TI_CL6X_VERSION
25486#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
25487#undef JSON_HEDLEY_TI_CL7X_VERSION
25488#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
25489#undef JSON_HEDLEY_TI_CLPRU_VERSION
25490#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
25491#undef JSON_HEDLEY_TI_VERSION
25492#undef JSON_HEDLEY_TI_VERSION_CHECK
25493#undef JSON_HEDLEY_UNAVAILABLE
25494#undef JSON_HEDLEY_UNLIKELY
25495#undef JSON_HEDLEY_UNPREDICTABLE
25496#undef JSON_HEDLEY_UNREACHABLE
25497#undef JSON_HEDLEY_UNREACHABLE_RETURN
25498#undef JSON_HEDLEY_VERSION
25499#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
25500#undef JSON_HEDLEY_VERSION_DECODE_MINOR
25501#undef JSON_HEDLEY_VERSION_DECODE_REVISION
25502#undef JSON_HEDLEY_VERSION_ENCODE
25503#undef JSON_HEDLEY_WARNING
25504#undef JSON_HEDLEY_WARN_UNUSED_RESULT
25505#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
25506#undef JSON_HEDLEY_FALL_THROUGH
25507
25508
25509
25510#endif // INCLUDE_NLOHMANN_JSON_HPP_
namespace for Niels Lohmann
Definition json.hpp:20099
constexpr bool is_string() const noexcept
Definition json.hpp:21397
number_integer_t * get_impl_ptr(number_integer_t *) noexcept
get a pointer to the value (integer number)
Definition json.hpp:21490
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:22630
detail::cbor_tag_handler_t cbor_tag_handler_t
Definition json.hpp:20172
reference operator[](KeyType &&key)
access specified object element
Definition json.hpp:22198
json_value(object_t &&value)
constructor for rvalue objects
Definition json.hpp:20536
size_type size() const noexcept
Definition json.hpp:22971
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:24425
json_value(typename binary_t::container_type &&value)
constructor for rvalue binary arrays
Definition json.hpp:20548
number_unsigned_t number_unsigned
Definition json.hpp:20440
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
Definition json.hpp:21770
::nlohmann::detail::iteration_proxy< Iterator > iteration_proxy
Definition json.hpp:20150
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22828
reference back()
access the last element
Definition json.hpp:22434
basic_json value_type
Definition json.hpp:20209
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:20837
detail::parse_error parse_error
Definition json.hpp:20191
number_float_t number_float
Definition json.hpp:20442
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22844
detail::input_format_t input_format_t
Definition json.hpp:20178
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition json.hpp:25017
json_value(const array_t &value)
constructor for arrays
Definition json.hpp:20539
array_t * get_impl_ptr(array_t *) noexcept
get a pointer to the value (array)
Definition json.hpp:21454
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
Definition json.hpp:24185
const_reference front() const
access the first element
Definition json.hpp:22427
constexpr bool is_array() const noexcept
return whether value is an array
Definition json.hpp:21390
number_float_t * get_impl_ptr(number_float_t *) noexcept
get a pointer to the value (floating-point number)
Definition json.hpp:21514
std::conditional< detail::is_c_string_uncvref< ValueType >::value, string_t, typename std::decay< ValueType >::type > value_return_type
Definition json.hpp:22241
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
Definition json.hpp:23489
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22378
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22747
constexpr const number_integer_t * get_impl_ptr(const number_integer_t *) const noexcept
get a pointer to the value (integer number)
Definition json.hpp:21496
iter_impl< const basic_json > const_iterator
Definition json.hpp:20232
constexpr bool is_number_integer() const noexcept
Definition json.hpp:21362
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
Definition json.hpp:20236
data(size_type cnt, const basic_json &val)
Definition json.hpp:24229
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:24620
::nlohmann::detail::json_base_class< void > json_base_class_t
Definition json.hpp:20125
basic_json get_impl(detail::priority_tag< 3 >) const
get special-case overload
Definition json.hpp:21722
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24665
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
Definition json.hpp:20227
static JSON_HEDLEY_RETURNS_NON_NULL T * create(Args &&... args)
helper for exception-safe object creation
Definition json.hpp:20380
std::size_t size_type
Definition json.hpp:20219
detail::type_error type_error
Definition json.hpp:20193
constexpr bool is_structured() const noexcept
Definition json.hpp:21334
json_value(boolean_t v) noexcept
constructor for booleans
Definition json.hpp:20447
const_reference operator[](KeyType &&key) const
access specified object element
Definition json.hpp:22222
detail::error_handler_t error_handler_t
Definition json.hpp:20170
boolean_t get_impl(boolean_t *) const
get a boolean (explicit)
Definition json.hpp:21431
const value_type & const_reference
Definition json.hpp:20214
detail::invalid_iterator invalid_iterator
Definition json.hpp:20192
void swap(binary_t &other)
exchanges the values
Definition json.hpp:23566
ReferenceType get_ref()
Definition json.hpp:21860
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.hpp:23010
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:23435
::nlohmann::detail::iter_impl< BasicJsonType > iter_impl
Definition json.hpp:20148
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:21871
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:21411
JSON_PRIVATE_UNLESS_TESTED const_reference rhs
Definition json.hpp:23684
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.hpp:23226
::nlohmann::detail::output_adapter_t< CharType > output_adapter_t
Definition json.hpp:20154
void push_back(basic_json &&val)
add an object to an array
Definition json.hpp:23114
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition json.hpp:22167
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:22916
json_value(number_integer_t v) noexcept
constructor for numbers (integer)
Definition json.hpp:20449
static ReferenceType get_ref_impl(ThisType &obj)
helper function to implement get_ref()
Definition json.hpp:21549
::nlohmann::detail::json_reverse_iterator< Base > json_reverse_iterator
Definition json.hpp:20151
const_reference back() const
access the last element
Definition json.hpp:22443
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:22525
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:23171
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:23506
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:24521
constexpr const string_t * get_impl_ptr(const string_t *) const noexcept
get a pointer to the value (string)
Definition json.hpp:21472
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:20979
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition json.hpp:23338
object_t * get_impl_ptr(object_t *) noexcept
get a pointer to the value (object)
Definition json.hpp:21442
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:24605
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:20242
nlohmann::byte_container_with_subtype< std::vector< std::uint8_t > > binary_t
Definition json.hpp:20367
reference at(KeyType &&key)
access specified object element with bounds checking
Definition json.hpp:22030
iterator end() noexcept
Definition json.hpp:22819
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:21369
json_value(array_t &&value)
constructor for rvalue arrays
Definition json.hpp:20542
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:23442
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition json.hpp:24384
detail::exception exception
Definition json.hpp:20190
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22851
data m_data
Definition json.hpp:24247
void push_back(initializer_list_t init)
add an object to an object
Definition json.hpp:23210
detail::parser_callback_t< basic_json > parser_callback_t
Definition json.hpp:20804
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
Definition json.hpp:21020
ValueType & get_to(ValueType &v) const
Definition json.hpp:21837
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:24320
iterator begin() noexcept
Definition json.hpp:22794
array_t * array
Definition json.hpp:20430
detail::parse_event_t parse_event_t
Definition json.hpp:20800
JSON_PRIVATE_UNLESS_TESTED const_reference bool inverse
Definition json.hpp:23684
void assert_invariant(bool check_parents=true) const noexcept
checks the class invariants
Definition json.hpp:20684
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition json.hpp:22277
void destroy(value_t t)
Definition json.hpp:20556
ValueType get_impl(detail::priority_tag< 0 >) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), std::declval< ValueType & >())))
get a value (explicit)
Definition json.hpp:21632
json_value(string_t &&value)
constructor for rvalue strings
Definition json.hpp:20530
const_iterator cend() const noexcept
Definition json.hpp:22835
constexpr const binary_t * get_impl_ptr(const binary_t *) const noexcept
get a pointer to the value (binary)
Definition json.hpp:21532
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:24575
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24707
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition json.hpp:20990
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:20825
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:24409
constexpr const number_unsigned_t * get_impl_ptr(const number_unsigned_t *) const noexcept
get a pointer to the value (unsigned number)
Definition json.hpp:21508
constexpr const boolean_t * get_impl_ptr(const boolean_t *) const noexcept
get a pointer to the value (boolean)
Definition json.hpp:21484
basic_json flatten() const
return flattened JSON value
Definition json.hpp:24721
constexpr const array_t * get_impl_ptr(const array_t *) const noexcept
get a pointer to the value (array)
Definition json.hpp:21460
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:24536
json_value(number_unsigned_t v) noexcept
constructor for numbers (unsigned)
Definition json.hpp:20451
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition json.hpp:22641
std::vector< basic_json, std::allocator< basic_json > > array_t
Definition json.hpp:20343
::nlohmann::detail::primitive_iterator_t primitive_iterator_t
Definition json.hpp:20144
json_value(const string_t &value)
constructor for strings
Definition json.hpp:20527
nlohmann::ordered_map< std::string, basic_json, default_object_comparator_t, std::allocator< std::pair< const std::string, basic_json > > > object_t
Definition json.hpp:20335
const binary_t & get_binary() const
get a binary value
Definition json.hpp:21942
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition json.hpp:23358
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition json.hpp:24746
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22330
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24679
json_value(number_float_t v) noexcept
constructor for numbers (floating-point)
Definition json.hpp:20453
value_type & reference
Definition json.hpp:20212
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
Definition json.hpp:20176
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition json.hpp:22764
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:24290
::nlohmann::detail::binary_reader< basic_json, InputType > binary_reader
Definition json.hpp:20157
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:24400
iterator find(const typename object_t::key_type &key)
Definition json.hpp:22677
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:20968
BasicJsonType get_impl(detail::priority_tag< 2 >) const
get special-case overload
Definition json.hpp:21699
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:24354
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition json.hpp:22068
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.hpp:20250
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:21027
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition json.hpp:22691
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.hpp:24281
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:22455
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition json.hpp:23311
double number_float_t
Definition json.hpp:20363
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
Definition json.hpp:22252
string_t * string
Definition json.hpp:20432
std::allocator< basic_json > allocator_type
Definition json.hpp:20222
typename std::allocator_traits< allocator_type >::pointer pointer
Definition json.hpp:20225
reference set_parent(reference j, std::size_t old_capacity=detail::unknown_size())
Definition json.hpp:20755
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:21298
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.hpp:25169
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:21824
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:24366
reference operator[](T *key)
Definition json.hpp:22183
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:21964
iterator find(KeyType &&key)
find an element in a JSON object
Definition json.hpp:22707
binary_t * binary
Definition json.hpp:20434
constexpr bool is_number_float() const noexcept
Definition json.hpp:21376
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.hpp:22858
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:24327
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24693
bool boolean_t
Definition json.hpp:20351
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:25027
::nlohmann::detail::internal_iterator< BasicJsonType > internal_iterator
Definition json.hpp:20146
void set_parents()
Definition json.hpp:20705
detail::value_t value_t
Definition json.hpp:20164
size_type erase_internal(KeyType &&key)
Definition json.hpp:22596
std::less< std::string > default_object_comparator_t
Definition json.hpp:20330
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:23202
const_iterator cbegin() const noexcept
Definition json.hpp:22810
constexpr const number_float_t * get_impl_ptr(const number_float_t *) const noexcept
get a pointer to the value (floating-point number)
Definition json.hpp:21520
reference operator[](typename object_t::key_type key)
access specified object element
Definition json.hpp:22145
string_t * get_impl_ptr(string_t *) noexcept
get a pointer to the value (string)
Definition json.hpp:21466
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:21582
~basic_json() noexcept
destructor
Definition json.hpp:21280
detail::is_comparable< object_comparator_t, const typename object_t::key_type &, KeyType > is_comparable_with_object_key
Definition json.hpp:22237
detail::out_of_range out_of_range
Definition json.hpp:20194
json_value(binary_t &&value)
constructor for rvalue binary arrays (internal type)
Definition json.hpp:20554
const_reverse_iterator crend() const noexcept
Definition json.hpp:22879
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:20909
json_value(const object_t &value)
constructor for objects
Definition json.hpp:20533
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.hpp:23582
binary_t & get_binary()
get a binary value
Definition json.hpp:21930
const_iterator begin() const noexcept
returns an iterator to the first element
Definition json.hpp:22803
constexpr bool is_number() const noexcept
Definition json.hpp:21355
number_unsigned_t * get_impl_ptr(number_unsigned_t *) noexcept
get a pointer to the value (unsigned number)
Definition json.hpp:21502
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition json.hpp:23409
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:24467
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:21811
const_reference operator[](T *key) const
Definition json.hpp:22189
data(const value_t v)
Definition json.hpp:24224
reference operator[](size_type idx)
access specified array element
Definition json.hpp:22086
basic_json(const JsonRef &ref)
Definition json.hpp:21148
adl_serializer< T, SFINAE > json_serializer
Definition json.hpp:20168
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:21251
static iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
Definition json.hpp:22891
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:24346
Array get_to(T(&v)[N]) const noexcept(noexcept(JSONSerializer< Array >::from_json(std::declval< const basic_json_t & >(), v)))
Definition json.hpp:21848
std::int64_t number_integer_t
Definition json.hpp:20355
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
Definition json.hpp:21571
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:22048
binary_t * get_impl_ptr(binary_t *) noexcept
get a pointer to the value (binary)
Definition json.hpp:21526
constexpr bool is_binary() const noexcept
Definition json.hpp:21404
void swap(object_t &other)
exchanges the values
Definition json.hpp:23534
iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
Definition json.hpp:20742
constexpr auto get_impl(detail::priority_tag< 4 >) const noexcept -> decltype(std::declval< const basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:21735
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.hpp:24730
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition json.hpp:23389
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:24375
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:21001
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:22909
bool empty() const noexcept
checks whether the container is empty.
Definition json.hpp:22932
void swap(array_t &other)
exchanges the values
Definition json.hpp:23518
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:22648
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:23139
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.hpp:22771
ValueType get_impl(detail::priority_tag< 1 >) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >())))
get a value (explicit); special case
Definition json.hpp:21674
constexpr value_t type() const noexcept
Definition json.hpp:21320
reference emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:23235
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22353
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.hpp:21012
detail::bjdata_version_t bjdata_version_t
Definition json.hpp:20174
data() noexcept=default
std::string string_t
Definition json.hpp:20347
friend class ::nlohmann::detail::parser
Definition json.hpp:20109
void push_back(const basic_json &val)
add an object to an array
Definition json.hpp:23147
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:22303
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:22010
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:24590
json_value m_value
Definition json.hpp:24222
number_integer_t number_integer
Definition json.hpp:20438
const_reverse_iterator crbegin() const noexcept
Definition json.hpp:22872
json_sax< basic_json > json_sax_t
Definition json.hpp:20180
constexpr bool is_boolean() const noexcept
Definition json.hpp:21348
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:22737
reference front()
access the first element
Definition json.hpp:22420
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:21327
constexpr bool is_null() const noexcept
Definition json.hpp:21341
void clear() noexcept
clears the contents
Definition json.hpp:23053
constexpr const object_t * get_impl_ptr(const object_t *) const noexcept
get a pointer to the value (object)
Definition json.hpp:21448
json_value(value_t t)
constructor for empty values of a given type
Definition json.hpp:20455
static ::nlohmann::detail::parser< basic_json, InputAdapterType > parser(InputAdapterType adapter, detail::parser_callback_t< basic_json >cb=nullptr, const bool allow_exceptions=true, const bool ignore_comments=false)
Definition json.hpp:20132
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:24338
detail::other_error other_error
Definition json.hpp:20195
JSON_PRIVATE_UNLESS_TESTED const_reference bool static SAX bool sax_parse(InputType &&i, SAX *sax, input_format_t format=input_format_t::json, const bool strict=true, const bool ignore_comments=false)
Definition json.hpp:24109
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:21225
iter_impl< basic_json > iterator
Definition json.hpp:20230
basic_json(const value_t v)
create an empty value with a given type
Definition json.hpp:20817
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:22132
std::ptrdiff_t difference_type
Definition json.hpp:20217
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition json.hpp:23331
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition json.hpp:22865
std::uint64_t number_unsigned_t
Definition json.hpp:20359
friend std::istream & operator>>(std::istream &i, basic_json &j)
Definition json.hpp:24170
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:24304
void swap(string_t &other)
exchanges the values
Definition json.hpp:23550
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.hpp:20851
NLOHMANN_BASIC_JSON_TPL basic_json_t
Definition json.hpp:20124
boolean_t * get_impl_ptr(boolean_t *) noexcept
get a pointer to the value (boolean)
Definition json.hpp:21478
::nlohmann::detail::binary_writer< basic_json, CharType > binary_writer
Definition json.hpp:20158
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
Definition json.hpp:20234
json_value(const binary_t &value)
constructor for binary arrays (internal type)
Definition json.hpp:20551
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:21987
detail::actual_object_comparator_t< basic_json > object_comparator_t
Definition json.hpp:20371
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:21152
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:23179
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:23260
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:24297
constexpr bool is_object() const noexcept
return whether value is an object
Definition json.hpp:21383
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:24313
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:24482
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition json.hpp:23292
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:21039
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition json.hpp:22755
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:24393
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition json.hpp:22723
boolean_t boolean
Definition json.hpp:20436
json_value(const typename binary_t::container_type &value)
constructor for binary arrays
Definition json.hpp:20545
::nlohmann::json_pointer< std::string > json_pointer
Definition json.hpp:20166
bool operator!=(const byte_container_with_subtype &rhs) const
Definition json.hpp:6219
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.hpp:6185
std::uint64_t subtype_type
Definition json.hpp:6182
bool operator==(const byte_container_with_subtype &rhs) const
Definition json.hpp:6213
BinaryType container_type
Definition json.hpp:6181
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6207
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6195
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.hpp:6234
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.hpp:6200
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.hpp:6241
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.hpp:6190
subtype_type m_subtype
Definition json.hpp:6255
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.hpp:6226
bool m_has_subtype
Definition json.hpp:6256
void clear_subtype() noexcept
clears the binary subtype
Definition json.hpp:6248
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:9831
json_sax_t * sax
the SAX parser
Definition json.hpp:12787
bool get_string(const input_format_t format, const NumberType len, string_t &result)
create a string by reading characters from the input
Definition json.hpp:12649
bool get_ubjson_size_type(std::pair< std::size_t, char_int_type > &result, bool inside_ndarray=false)
determine the type and size for a container
Definition json.hpp:12001
binary_reader(const binary_reader &)=delete
bool parse_bson_array()
Reads an array from the BSON input and passes it to the SAX-parser.
Definition json.hpp:10159
typename BasicJsonType::string_t string_t
Definition json.hpp:9835
std::size_t chars_read
the number of characters read
Definition json.hpp:12778
std::pair< char_int_type, string_t > bjd_type
Definition json.hpp:12814
bool parse_bson_element_list(const bool is_array)
Read a BSON element list (as specified in the BSON-spec)
Definition json.hpp:10121
typename InputAdapterType::char_type char_type
Definition json.hpp:9838
bool parse_msgpack_internal()
Definition json.hpp:10965
std::string get_token_string() const
Definition json.hpp:12719
const bool is_little_endian
whether we can assume little endianness
Definition json.hpp:12781
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9833
bool get_msgpack_string(string_t &result)
reads a MessagePack string
Definition json.hpp:11346
std::string exception_message(const input_format_t format, const std::string &detail, const std::string &context) const
Definition json.hpp:12732
InputAdapterType ia
input adapter
Definition json.hpp:12772
bool get_ubjson_high_precision_number()
Definition json.hpp:12459
bool get_binary(const input_format_t format, const NumberType len, binary_t &result)
create a byte array by reading bytes from the input
Definition json.hpp:12682
binary_reader(binary_reader &&)=default
static void byte_swap(NumberType &number)
Definition json.hpp:12582
char_int_type get_ignore_noop()
Definition json.hpp:12570
bool get_ubjson_value(const char_int_type prefix)
Definition json.hpp:12068
bool get_ubjson_ndarray_size(std::vector< size_t > &dim)
Definition json.hpp:11713
bool parse_bson_element_internal(const char_int_type element_type, const std::size_t element_type_parse_position)
Read a BSON document element of the given element_type.
Definition json.hpp:10035
bool get_msgpack_object(const std::size_t len)
Definition json.hpp:11562
typename char_traits< char_type >::int_type char_int_type
Definition json.hpp:9839
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.hpp:9847
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9836
bool parse_bson_internal()
Reads in a BSON-object and passes it to the SAX-parser.
Definition json.hpp:9931
binary_reader & operator=(const binary_reader &)=delete
bool get_cbor_object(const std::size_t len, const cbor_tag_handler_t tag_handler)
Definition json.hpp:10909
bool get_cbor_binary(binary_t &result)
reads a CBOR byte array
Definition json.hpp:10776
bool get_number(const input_format_t format, NumberType &result)
Definition json.hpp:12619
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9832
bool unexpect_eof(const input_format_t format, const char *context) const
Definition json.hpp:12706
bool get_ubjson_array()
Definition json.hpp:12261
bool get_bson_cstr(string_t &result)
Parses a C-style string from the BSON input.
Definition json.hpp:9956
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:9868
bool get_cbor_array(const std::size_t len, const cbor_tag_handler_t tag_handler)
Definition json.hpp:10871
char_int_type current
the current character
Definition json.hpp:12775
bool get_msgpack_array(const std::size_t len)
Definition json.hpp:11540
char_int_type get()
get next character from the input
Definition json.hpp:12538
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9834
bool get_msgpack_binary(binary_t &result)
reads a MessagePack byte array
Definition json.hpp:11429
bool parse_ubjson_internal(const bool get_char=true)
Definition json.hpp:11599
SAX json_sax_t
Definition json.hpp:9837
bool get_ubjson_size_value(std::size_t &result, bool &is_ndarray, char_int_type prefix=0)
Definition json.hpp:11778
bool parse_cbor_internal(const bool get_char, const cbor_tag_handler_t tag_handler)
Definition json.hpp:10189
bool get_ubjson_object()
Definition json.hpp:12376
const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map
Definition json.hpp:12816
bool get_bson_string(const NumberType len, string_t &result)
Parses a zero-terminated string of length len from the BSON input.
Definition json.hpp:9986
bool get_ubjson_string(string_t &result, const bool get_char=true)
reads a UBJSON string
Definition json.hpp:11618
bool get_to(T &dest, const input_format_t format, const char *context)
get_to read into a primitive type
Definition json.hpp:12553
static JSON_INLINE_VARIABLE constexpr std::size_t npos
Definition json.hpp:12769
bool get_cbor_string(string_t &result)
reads a CBOR string
Definition json.hpp:10680
const input_format_t input_format
input format
Definition json.hpp:12784
bool get_bson_binary(const NumberType len, binary_t &result)
Parses a byte array input of length len from the BSON input.
Definition json.hpp:10008
binary_reader & operator=(binary_reader &&)=default
void write_bson_binary(const string_t &name, const binary_t &value)
Writes a BSON element with key name and binary value value.
Definition json.hpp:16885
void write_bson_boolean(const string_t &name, const bool value)
Writes a BSON element with key name and boolean value value.
Definition json.hpp:16722
void write_bson(const BasicJsonType &j)
Definition json.hpp:15792
typename BasicJsonType::binary_t binary_t
Definition json.hpp:15774
void write_bson_integer(const string_t &name, const std::int64_t value)
Writes a BSON element with key name and integer value.
Definition json.hpp:16782
typename BasicJsonType::string_t string_t
Definition json.hpp:15773
static constexpr CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:17532
static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
Definition json.hpp:16800
void write_ubjson(const BasicJsonType &j, const bool use_count, const bool use_type, const bool add_prefix=true, const bool use_bjdata=false, const bjdata_version_t bjdata_version=bjdata_version_t::draft2)
Definition json.hpp:16472
void write_bson_array(const string_t &name, const typename BasicJsonType::array_t &value)
Writes a BSON element with key name and array value.
Definition json.hpp:16866
static CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:17539
static constexpr CharType get_cbor_float_prefix(double)
Definition json.hpp:17031
void write_bson_string(const string_t &name, const string_t &value)
Writes a BSON element with key name and string value value.
Definition json.hpp:16750
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition json.hpp:15783
static constexpr CharType get_ubjson_float_prefix(double)
Definition json.hpp:17346
void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix, const bool use_bjdata)
Definition json.hpp:17057
static constexpr CharType get_msgpack_float_prefix(double)
Definition json.hpp:17045
void write_bson_element(const string_t &name, const BasicJsonType &j)
Serializes the JSON value j to BSON and associates it with the key name.
Definition json.hpp:16948
static constexpr CharType to_char_type(InputCharType x) noexcept
Definition json.hpp:17561
void write_bson_object(const typename BasicJsonType::object_t &value)
Definition json.hpp:17010
void write_bson_double(const string_t &name, const double value)
Writes a BSON element with key name and double value value.
Definition json.hpp:16732
static std::size_t calc_bson_string_size(const string_t &value)
Definition json.hpp:16742
void write_number(const NumberType n, const bool OutputIsLittleEndian=false)
Definition json.hpp:17482
static std::size_t calc_bson_entry_header_size(const string_t &name, const BasicJsonType &j)
Definition json.hpp:16695
void write_bson_null(const string_t &name)
Writes a BSON element with key name and null value.
Definition json.hpp:16764
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:15775
CharType ubjson_prefix(const BasicJsonType &j, const bool use_bjdata) const noexcept
determine the type prefix of container values
Definition json.hpp:17240
void write_bson_unsigned(const string_t &name, const BasicJsonType &j)
Writes a BSON element with key name and unsigned value.
Definition json.hpp:16810
static constexpr CharType get_ubjson_float_prefix(float)
Definition json.hpp:17341
static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t &value)
Definition json.hpp:16858
bool write_bjdata_ndarray(const typename BasicJsonType::object_t &value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
Definition json.hpp:17354
static std::size_t calc_bson_element_size(const string_t &name, const BasicJsonType &j)
Calculates the size necessary to serialize the JSON value j with its name.
Definition json.hpp:16900
void write_msgpack(const BasicJsonType &j)
Definition json.hpp:16145
static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t &value)
Calculates the size of the BSON serialization of the given JSON-object j.
Definition json.hpp:16995
void write_compact_float(const number_float_t n, detail::input_format_t format)
Definition json.hpp:17498
output_adapter_t< CharType > oa
the output
Definition json.hpp:17571
void write_cbor(const BasicJsonType &j)
Definition json.hpp:15821
static constexpr CharType get_cbor_float_prefix(float)
Definition json.hpp:17026
void write_bson_entry_header(const string_t &name, const std::uint8_t element_type)
Writes the given element_type and name to the output adapter.
Definition json.hpp:16710
void write_bson_object_entry(const string_t &name, const typename BasicJsonType::object_t &value)
Writes a BSON element with key name and object value.
Definition json.hpp:16833
static constexpr CharType get_msgpack_float_prefix(float)
Definition json.hpp:17040
const bool is_little_endian
whether we can assume little endianness
Definition json.hpp:17568
static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t &value)
Definition json.hpp:16843
static std::size_t calc_bson_integer_size(const std::int64_t value)
Definition json.hpp:16772
general exception of the basic_json class
Definition json.hpp:4506
static std::string get_byte_positions(const BasicJsonType *leaf_element)
Definition json.hpp:4611
exception(int id_, const char *what_arg)
Definition json.hpp:4519
const int id
the id of the exception
Definition json.hpp:4515
static std::string diagnostics(std::nullptr_t)
Definition json.hpp:4526
std::runtime_error m
an exception object as storage for error messages
Definition json.hpp:4598
static std::string name(const std::string &ename, int id_)
Definition json.hpp:4521
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:4509
static std::string diagnostics(const BasicJsonType *leaf_element)
Definition json.hpp:4532
Definition json.hpp:6481
char char_type
Definition json.hpp:6483
file_input_adapter(const file_input_adapter &)=delete
std::FILE * m_file
the file pointer to read from
Definition json.hpp:6513
file_input_adapter(std::FILE *f) noexcept
Definition json.hpp:6486
std::char_traits< char >::int_type get_character() noexcept
Definition json.hpp:6499
file_input_adapter(file_input_adapter &&) noexcept=default
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6506
Definition json.hpp:6526
input_stream_adapter & operator=(input_stream_adapter &&)=delete
std::istream * is
the associated input stream
Definition json.hpp:6583
input_stream_adapter(input_stream_adapter &&rhs) noexcept
Definition json.hpp:6549
~input_stream_adapter()
Definition json.hpp:6530
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6571
std::char_traits< char >::int_type get_character()
Definition json.hpp:6559
char char_type
Definition json.hpp:6528
input_stream_adapter(const input_stream_adapter &)=delete
std::streambuf * sb
Definition json.hpp:6584
input_stream_adapter & operator=(input_stream_adapter &)=delete
input_stream_adapter(std::istream &i)
Definition json.hpp:6540
exception indicating errors with iterators
Definition json.hpp:4675
static invalid_iterator create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4678
invalid_iterator(int id_, const char *what_arg)
Definition json.hpp:4686
~iter_impl()=default
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:14174
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:13728
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:14119
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:13718
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:14061
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:14101
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:14165
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:13971
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:14274
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.hpp:14012
iter_impl operator++(int) &
post-increment (it++)
Definition json.hpp:13909
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:14128
reference operator[](difference_type n) const
access to successor
Definition json.hpp:14236
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
Definition json.hpp:13623
pointer operator->() const
dereference the iterator
Definition json.hpp:13867
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:14207
iter_impl(iter_impl &&) noexcept=default
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:14185
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:14110
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:13920
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:13823
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:14196
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
Definition json.hpp:13627
iter_impl< typename std::conditional< std::is_const< BasicJsonType >::value, typename std::remove_const< BasicJsonType >::type, const BasicJsonType >::type > other_iter_impl
the iterator with BasicJsonType of different const-ness
Definition json.hpp:13593
iter_impl()=default
friend BasicJsonType
Definition json.hpp:13596
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.hpp:13703
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition json.hpp:14052
iter_impl operator--(int) &
post-decrement (it–)
Definition json.hpp:13960
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.hpp:13693
void set_end() noexcept
set the iterator past the last value
Definition json.hpp:13784
Definition json.hpp:5452
iteration_proxy_value operator++(int) &
Definition json.hpp:5508
iteration_proxy_value(iteration_proxy_value const &)=default
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.hpp:5517
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.hpp:5523
std::ptrdiff_t difference_type
Definition json.hpp:5454
value_type & reference
Definition json.hpp:5457
string_type empty_str
an empty string (to return a reference for primitive values)
Definition json.hpp:5471
iteration_proxy_value(IteratorType it, std::size_t array_index_=0) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_default_constructible< string_type >::value)
Definition json.hpp:5475
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:5500
std::forward_iterator_tag iterator_category
Definition json.hpp:5458
iteration_proxy_value value_type
Definition json.hpp:5455
std::size_t array_index_last
last stringified array index
Definition json.hpp:5467
std::size_t array_index
an index for arrays (used to create key names)
Definition json.hpp:5465
iteration_proxy_value(iteration_proxy_value &&) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_move_constructible< string_type >::value)=default
IteratorType::reference value() const
return value of the iterator
Definition json.hpp:5565
value_type * pointer
Definition json.hpp:5456
const string_type & key() const
return key of the iterator
Definition json.hpp:5529
iteration_proxy_value & operator=(iteration_proxy_value const &)=default
string_type array_index_str
a string representation of the array index
Definition json.hpp:5469
typename std::remove_cv< typename std::remove_reference< decltype(std::declval< IteratorType >().key()) >::type >::type string_type
Definition json.hpp:5459
IteratorType anchor
the iterator
Definition json.hpp:5463
proxy class for the items() function
Definition json.hpp:5573
IteratorType::pointer container
the container to iterate
Definition json.hpp:5576
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.hpp:5598
iteration_proxy(iteration_proxy const &)=default
iteration_proxy(iteration_proxy &&) noexcept=default
iteration_proxy_value< IteratorType > begin() const noexcept
return iterator begin (needed for range-based for)
Definition json.hpp:5592
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:5582
iteration_proxy & operator=(iteration_proxy const &)=default
Definition json.hpp:6592
iterator_type end
Definition json.hpp:6634
bool empty() const
Definition json.hpp:6639
char_traits< char_type >::int_type get_character()
Definition json.hpp:6600
iterator_input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:6596
typename std::iterator_traits< IteratorType >::value_type char_type
Definition json.hpp:6594
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6614
iterator_type current
Definition json.hpp:6633
friend struct wide_string_input_helper
Definition json.hpp:6637
Definition json.hpp:15504
value_type owned_value
Definition json.hpp:15554
json_ref(json_ref &&) noexcept=default
json_ref(const value_type &value)
Definition json.hpp:15512
json_ref(value_type &&value)
Definition json.hpp:15508
value_type const & operator*() const
Definition json.hpp:15543
value_type const * operator->() const
Definition json.hpp:15548
json_ref(std::initializer_list< json_ref > init)
Definition json.hpp:15516
json_ref(Args &&... args)
Definition json.hpp:15523
value_type moved_or_copied() const
Definition json.hpp:15534
BasicJsonType value_type
Definition json.hpp:15506
value_type const * value_ref
Definition json.hpp:15555
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition json.hpp:14369
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition json.hpp:14381
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.hpp:14375
std::ptrdiff_t difference_type
Definition json.hpp:14355
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.hpp:14393
reference operator[](difference_type n) const
access to successor
Definition json.hpp:14417
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.hpp:14423
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.hpp:14411
typename Base::reference reference
the reference type for the pointed-to element
Definition json.hpp:14359
reference value() const
return the value of an iterator
Definition json.hpp:14430
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.hpp:14366
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.hpp:14387
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.hpp:14357
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.hpp:14405
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.hpp:14362
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.hpp:14399
Definition json.hpp:9546
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9549
bool end_object()
Definition json.hpp:9599
bool binary(binary_t &)
Definition json.hpp:9584
bool number_integer(number_integer_t)
Definition json.hpp:9564
bool start_array(std::size_t=detail::unknown_size())
Definition json.hpp:9604
bool boolean(bool)
Definition json.hpp:9559
bool null()
Definition json.hpp:9554
bool end_array()
Definition json.hpp:9609
bool number_unsigned(number_unsigned_t)
Definition json.hpp:9569
bool start_object(std::size_t=detail::unknown_size())
Definition json.hpp:9589
bool string(string_t &)
Definition json.hpp:9579
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9552
bool number_float(number_float_t, const string_t &)
Definition json.hpp:9574
bool parse_error(std::size_t, const std::string &, const detail::exception &)
Definition json.hpp:9614
bool key(string_t &)
Definition json.hpp:9594
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9548
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9550
typename BasicJsonType::string_t string_t
Definition json.hpp:9551
Definition json.hpp:9109
bool start_array(std::size_t len)
Definition json.hpp:9277
typename BasicJsonType::parser_callback_t parser_callback_t
Definition json.hpp:9116
bool null()
Definition json.hpp:9136
std::vector< BasicJsonType * > ref_stack
stack to model hierarchy of values
Definition json.hpp:9525
typename BasicJsonType::parse_event_t parse_event_t
Definition json.hpp:9117
json_sax_dom_callback_parser & operator=(json_sax_dom_callback_parser &&)=default
bool number_integer(number_integer_t val)
Definition json.hpp:9148
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:9356
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9113
BasicJsonType discarded
a discarded value for the callback
Definition json.hpp:9539
json_sax_dom_callback_parser & operator=(const json_sax_dom_callback_parser &)=delete
lexer< BasicJsonType, InputAdapterType > lexer_t
Definition json.hpp:9118
bool end_object()
Definition json.hpp:9227
const parser_callback_t callback
callback function
Definition json.hpp:9535
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:9154
BasicJsonType * object_element
helper to hold the reference for the next object element
Definition json.hpp:9531
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:9160
const bool allow_exceptions
whether to throw exceptions in case of errors
Definition json.hpp:9537
constexpr bool is_errored() const
Definition json.hpp:9368
json_sax_dom_callback_parser(BasicJsonType &r, parser_callback_t cb, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.hpp:9120
bool binary(binary_t &val)
Definition json.hpp:9172
std::vector< bool > key_keep_stack
stack to manage which object keys to keep
Definition json.hpp:9529
typename BasicJsonType::string_t string_t
Definition json.hpp:9114
bool boolean(bool val)
Definition json.hpp:9142
bool key(string_t &val)
Definition json.hpp:9210
bool string(string_t &val)
Definition json.hpp:9166
json_sax_dom_callback_parser(json_sax_dom_callback_parser &&)=default
BasicJsonType & root
the parsed JSON value
Definition json.hpp:9523
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9112
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9111
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9115
bool errored
whether a syntax error occurred
Definition json.hpp:9533
lexer_t * m_lexer_ref
the lexer reference to obtain the current position
Definition json.hpp:9541
bool end_array()
Definition json.hpp:9309
bool start_object(std::size_t len)
Definition json.hpp:9178
std::pair< bool, BasicJsonType * > handle_value(Value &&v, const bool skip_callback=false)
Definition json.hpp:9455
json_sax_dom_callback_parser(const json_sax_dom_callback_parser &)=delete
std::vector< bool > keep_stack
stack to manage which values to keep
Definition json.hpp:9527
SAX implementation to create a JSON value from SAX events.
Definition json.hpp:8803
lexer_t * m_lexer_ref
the lexer reference to obtain the current position
Definition json.hpp:9104
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:8852
std::vector< BasicJsonType * > ref_stack
stack to model hierarchy of values
Definition json.hpp:9096
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:8846
json_sax_dom_parser(const json_sax_dom_parser &)=delete
json_sax_dom_parser & operator=(const json_sax_dom_parser &)=delete
bool binary(binary_t &val)
Definition json.hpp:8864
BasicJsonType * object_element
helper to hold the reference for the next object element
Definition json.hpp:9098
typename BasicJsonType::binary_t binary_t
Definition json.hpp:8809
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.hpp:8817
bool start_object(std::size_t len)
Definition json.hpp:8870
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:8805
bool key(string_t &val)
Definition json.hpp:8893
bool end_object()
Definition json.hpp:8903
typename BasicJsonType::string_t string_t
Definition json.hpp:8808
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:8806
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:8961
lexer< BasicJsonType, InputAdapterType > lexer_t
Definition json.hpp:8810
bool boolean(bool val)
Definition json.hpp:8834
const bool allow_exceptions
whether to throw exceptions in case of errors
Definition json.hpp:9102
bool start_array(std::size_t len)
Definition json.hpp:8921
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:8807
JSON_HEDLEY_RETURNS_NON_NULL BasicJsonType * handle_value(Value &&v)
Definition json.hpp:9056
BasicJsonType & root
the parsed JSON value
Definition json.hpp:9094
bool end_array()
Definition json.hpp:8942
json_sax_dom_parser(json_sax_dom_parser &&)=default
bool errored
whether a syntax error occurred
Definition json.hpp:9100
constexpr bool is_errored() const
Definition json.hpp:8973
bool null()
Definition json.hpp:8828
bool string(string_t &val)
Definition json.hpp:8858
json_sax_dom_parser & operator=(json_sax_dom_parser &&)=default
bool number_integer(number_integer_t val)
Definition json.hpp:8840
Definition json.hpp:7043
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
Definition json.hpp:7070
token_type
token types for the parser
Definition json.hpp:7047
@ value_float
an floating point number – use get_number_float() for actual value
Definition json.hpp:7055
@ begin_array
the character for array begin [
Definition json.hpp:7056
@ value_string
a string – use get_string() for actual value
Definition json.hpp:7052
@ end_array
the character for array end ]
Definition json.hpp:7058
@ uninitialized
indicating the scanner is uninitialized
Definition json.hpp:7048
@ parse_error
indicating a parse error
Definition json.hpp:7062
@ value_integer
a signed integer – use get_number_integer() for actual value
Definition json.hpp:7054
@ value_separator
the value separator ,
Definition json.hpp:7061
@ end_object
the character for object end }
Definition json.hpp:7059
@ literal_true
the true literal
Definition json.hpp:7049
@ begin_object
the character for object begin {
Definition json.hpp:7057
@ value_unsigned
an unsigned integer – use get_number_unsigned() for actual value
Definition json.hpp:7053
@ literal_null
the null literal
Definition json.hpp:7051
@ end_of_input
indicating the end of the input buffer
Definition json.hpp:7063
@ name_separator
the name separator :
Definition json.hpp:7060
@ literal_or_value
a literal or the begin of a value (only for diagnostics)
Definition json.hpp:7064
@ literal_false
the false literal
Definition json.hpp:7050
lexical analysis
Definition json.hpp:7120
void reset() noexcept
reset token_buffer; current character is beginning of token
Definition json.hpp:8330
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.hpp:8502
string_t token_buffer
buffer for variable-length tokens (numbers, strings)
Definition json.hpp:8633
int get_codepoint()
get codepoint from 4 hex characters following \u
Definition json.hpp:7177
token_type scan_string()
scan a string literal
Definition json.hpp:7262
number_integer_t value_integer
Definition json.hpp:8639
void skip_whitespace()
Definition json.hpp:8516
const bool ignore_comments
whether comments should be ignored (true) or signaled as errors (false)
Definition json.hpp:8618
lexer(InputAdapterType &&adapter, bool ignore_comments_=false) noexcept
Definition json.hpp:7131
char_int_type current
the current character
Definition json.hpp:8621
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.hpp:8489
std::string get_token_string() const
Definition json.hpp:8464
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:7123
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.hpp:8423
typename BasicJsonType::string_t string_t
Definition json.hpp:7124
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:7122
bool next_byte_in_range(std::initializer_list< char_int_type > ranges)
check if the next byte(s) are inside a given range
Definition json.hpp:7225
char_int_type get()
Definition json.hpp:8348
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.hpp:8456
static void strtof(float &f, const char *str, char **endptr) noexcept
Definition json.hpp:7920
const char_int_type decimal_point_char
the decimal point
Definition json.hpp:8644
number_unsigned_t value_unsigned
Definition json.hpp:8640
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:7121
token_type scan()
Definition json.hpp:8525
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.hpp:8429
typename char_traits< char_type >::int_type char_int_type
Definition json.hpp:7126
bool scan_comment()
scan a comment
Definition json.hpp:7852
typename lexer_base< BasicJsonType >::token_type token_type
Definition json.hpp:7129
lexer(lexer &&)=default
~lexer()=default
const char * error_message
a description of occurred lexer errors
Definition json.hpp:8636
lexer & operator=(lexer &&)=default
bool next_unget
whether the next get() call should just return current
Definition json.hpp:8624
lexer(const lexer &)=delete
std::size_t decimal_point_position
the position of the decimal point in the input
Definition json.hpp:8646
typename InputAdapterType::char_type char_type
Definition json.hpp:7125
InputAdapterType ia
input adapter
Definition json.hpp:8615
lexer & operator=(lexer &)=delete
token_type scan_number()
scan a number literal
Definition json.hpp:7977
number_float_t value_float
Definition json.hpp:8641
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.hpp:8441
token_type scan_literal(const char_type *literal_text, const std::size_t length, token_type return_type)
Definition json.hpp:8310
std::vector< char_type > token_string
raw input token string (for error messages)
Definition json.hpp:8630
void add(char_int_type c)
add a character to token_buffer
Definition json.hpp:8412
position_t position
the start position of the current token
Definition json.hpp:8627
void unget()
unget current character (read it again on next get)
Definition json.hpp:8385
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.hpp:8435
static JSON_HEDLEY_PURE char get_decimal_point() noexcept
return the locale-dependent decimal point
Definition json.hpp:7151
exception indicating other library errors
Definition json.hpp:4727
other_error(int id_, const char *what_arg)
Definition json.hpp:4738
static other_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4730
exception indicating access out of the defined range
Definition json.hpp:4710
out_of_range(int id_, const char *what_arg)
Definition json.hpp:4721
static out_of_range create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4713
Definition json.hpp:15723
output_adapter(StringType &s)
Definition json.hpp:15734
output_adapter_t< CharType > oa
Definition json.hpp:15743
output_adapter(std::basic_ostream< CharType > &s)
Definition json.hpp:15730
output_adapter(std::vector< CharType, AllocatorType > &vec)
Definition json.hpp:15726
output adapter for output streams
Definition json.hpp:15675
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:15687
output_stream_adapter(std::basic_ostream< CharType > &s) noexcept
Definition json.hpp:15677
void write_character(CharType c) override
Definition json.hpp:15681
std::basic_ostream< CharType > & stream
Definition json.hpp:15693
output adapter for basic_string
Definition json.hpp:15700
void write_character(CharType c) override
Definition json.hpp:15706
output_string_adapter(StringType &s) noexcept
Definition json.hpp:15702
StringType & str
Definition json.hpp:15718
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:15712
output adapter for byte vectors
Definition json.hpp:15650
std::vector< CharType, AllocatorType > & v
Definition json.hpp:15668
output_vector_adapter(std::vector< CharType, AllocatorType > &vec) noexcept
Definition json.hpp:15652
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:15662
void write_character(CharType c) override
Definition json.hpp:15656
exception indicating a parse error
Definition json.hpp:4622
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:4634
static std::string position_string(const position_t &pos)
Definition json.hpp:4665
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4642
const std::size_t byte
byte index of the parse error
Definition json.hpp:4659
parse_error(int id_, std::size_t byte_, const char *what_arg)
Definition json.hpp:4662
std::string exception_message(const token_type expected, const std::string &context)
Definition json.hpp:13321
const bool allow_exceptions
whether to throw exceptions in case of errors
Definition json.hpp:13358
bool sax_parse_internal(SAX *sax)
Definition json.hpp:13023
typename lexer_t::token_type token_type
Definition json.hpp:12910
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.hpp:12936
token_type last_token
the type of the last read token
Definition json.hpp:13354
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:12906
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:12905
typename BasicJsonType::string_t string_t
Definition json.hpp:12908
lexer_t m_lexer
the lexer
Definition json.hpp:13356
lexer< BasicJsonType, InputAdapterType > lexer_t
Definition json.hpp:12909
bool accept(const bool strict=true)
public accept interface
Definition json.hpp:12996
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:12907
const parser_callback_t< BasicJsonType > callback
callback function
Definition json.hpp:13352
parser(InputAdapterType &&adapter, parser_callback_t< BasicJsonType > cb=nullptr, const bool allow_exceptions_=true, const bool skip_comments=false)
a parser reading from an input adapter
Definition json.hpp:12914
bool sax_parse(SAX *sax, const bool strict=true)
Definition json.hpp:13004
token_type get_token()
get next token from lexer
Definition json.hpp:13316
Definition json.hpp:13408
primitive_iterator_t & operator++() noexcept
Definition json.hpp:13470
primitive_iterator_t & operator-=(difference_type n) noexcept
Definition json.hpp:13502
static constexpr difference_type end_value
Definition json.hpp:13412
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition json.hpp:13437
primitive_iterator_t & operator--() noexcept
Definition json.hpp:13483
static constexpr difference_type begin_value
Definition json.hpp:13411
void set_end() noexcept
set iterator to a defined past the end
Definition json.hpp:13431
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13453
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition json.hpp:13443
primitive_iterator_t operator++(int) &noexcept
Definition json.hpp:13476
primitive_iterator_t & operator+=(difference_type n) noexcept
Definition json.hpp:13496
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13448
constexpr difference_type get_value() const noexcept
Definition json.hpp:13419
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13465
primitive_iterator_t operator+(difference_type n) noexcept
Definition json.hpp:13458
void set_begin() noexcept
set iterator to a defined beginning
Definition json.hpp:13425
primitive_iterator_t operator--(int) &noexcept
Definition json.hpp:13489
std::ptrdiff_t difference_type
Definition json.hpp:13410
typename BasicJsonType::binary_t::value_type binary_char_t
Definition json.hpp:18763
std::array< char, 512 > string_buffer
string buffer
Definition json.hpp:19682
std::uint8_t state
Definition json.hpp:19100
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:18762
std::size_t bytes_after_last_accept
Definition json.hpp:19104
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:18773
JSON_PRIVATE_UNLESS_TESTED const bool ensure_ascii
Definition json.hpp:19098
std::size_t undumped_chars
Definition json.hpp:19105
const char thousands_sep
the locale's thousand separator character
Definition json.hpp:19677
static constexpr std::uint8_t UTF8_REJECT
Definition json.hpp:18765
const char decimal_point
the locale's decimal point character
Definition json.hpp:19679
serializer & operator=(const serializer &)=delete
~serializer()=default
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition json.hpp:19690
string_t indent_string
the indentation string
Definition json.hpp:19687
const std::lconv * loc
the locale
Definition json.hpp:19675
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:18761
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:18760
serializer & operator=(serializer &&)=delete
typename BasicJsonType::string_t string_t
Definition json.hpp:18759
std::array< char, 64 > number_buffer
a (hopefully) large enough character buffer
Definition json.hpp:19672
const char indent_char
the indentation character
Definition json.hpp:19685
std::size_t bytes
Definition json.hpp:19101
static constexpr std::uint8_t UTF8_ACCEPT
Definition json.hpp:18764
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:18813
serializer(const serializer &)=delete
serializer(serializer &&)=delete
span_input_adapter(CharT b, std::size_t l)
Definition json.hpp:6962
contiguous_bytes_input_adapter ia
Definition json.hpp:6978
span_input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:6969
contiguous_bytes_input_adapter && get()
Definition json.hpp:6972
exception indicating executing a member function with a wrong type
Definition json.hpp:4693
static type_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4696
type_error(int id_, const char *what_arg)
Definition json.hpp:4704
Definition json.hpp:6771
std::size_t get_elements(T *, std::size_t=1)
Definition json.hpp:6797
std::char_traits< char >::int_type get_character() noexcept
Definition json.hpp:6778
std::array< std::char_traits< char >::int_type, 4 > utf8_bytes
Definition json.hpp:6812
base_adapter_type base_adapter
Definition json.hpp:6803
wide_string_input_adapter(BaseInputAdapter base)
Definition json.hpp:6775
char char_type
Definition json.hpp:6773
void fill_buffer()
Definition json.hpp:6806
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition json.hpp:14525
BasicJsonType & get_checked(BasicJsonType *ptr) const
Definition json.hpp:14911
json_pointer< string_t > convert() const &
Definition json.hpp:15324
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:14620
static BasicJsonType::size_type array_index(const string_t &s)
Definition json.hpp:14703
typename string_t_helper< RefStringType >::type string_t
Definition json.hpp:14547
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:14627
json_pointer result
Definition json.hpp:14748
result reference_tokens
Definition json.hpp:14749
json_pointer(const string_t &s="")
create JSON pointer
Definition json.hpp:14551
static std::vector< string_t > split(const string_t &reference_string)
split the string input to reference tokens
Definition json.hpp:15155
bool empty() const noexcept
return whether pointer points to the root document
Definition json.hpp:14686
BasicJsonType & get_and_create(BasicJsonType &j) const
create and return a reference to the pointed to value
Definition json.hpp:14763
void pop_back()
remove last reference token
Definition json.hpp:14648
string_t to_string() const
return a string representation of the JSON pointer
Definition json.hpp:14557
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition json.hpp:14605
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14679
json_pointer< string_t > convert() &&
Definition json.hpp:15331
static void flatten(const string_t &reference_string, const BasicJsonType &value, BasicJsonType &result)
Definition json.hpp:15224
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition json.hpp:14587
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:14612
BasicJsonType & get_unchecked(BasicJsonType *ptr) const
return a reference to the pointed to value
Definition json.hpp:14843
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition json.hpp:14634
static BasicJsonType unflatten(const BasicJsonType &value)
Definition json.hpp:15296
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition json.hpp:14597
friend class json_pointer
Definition json.hpp:14531
const string_t & back() const
return last reference token
Definition json.hpp:14660
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition json.hpp:14578
const BasicJsonType & get_unchecked(const BasicJsonType *ptr) const
return a const reference to the pointed to value
Definition json.hpp:14969
friend class basic_json
Definition json.hpp:14528
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14672
const BasicJsonType & get_checked(const BasicJsonType *ptr) const
Definition json.hpp:15018
bool contains(const BasicJsonType *ptr) const
Definition json.hpp:15067
decltype( get< N >(std::declval< ::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
Definition json.hpp:5644
nlohmann::json json
For better readability and development process using json is declared here at the top of the implemen...
Definition files.cpp:37
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
Definition json.hpp:2614
#define JSON_HEDLEY_CONST
Definition json.hpp:1832
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
Definition json.hpp:1116
#define JSON_INLINE_VARIABLE
Definition json.hpp:2513
#define JSON_HEDLEY_WARN_UNUSED_RESULT
Definition json.hpp:1462
#define JSON_PRIVATE_UNLESS_TESTED
Definition json.hpp:2573
#define NLOHMANN_JSON_VERSION_PATCH
Definition json.hpp:70
#define JSON_HEDLEY_LIKELY(expr)
Definition json.hpp:1727
bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15420
#define JSON_HEDLEY_NON_NULL(...)
Definition json.hpp:1620
#define JSON_INTERNAL_CATCH(exception)
Definition json.hpp:2540
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition json.hpp:25201
#define JSON_HEDLEY_RETURNS_NON_NULL
Definition json.hpp:2061
#define JSON_CATCH(exception)
Definition json.hpp:2539
#define JSON_ASSERT(x)
Definition json.hpp:2566
#define JSON_THROW(exception)
Definition json.hpp:2537
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
Definition json.hpp:81
#define NLOHMANN_JSON_VERSION_MAJOR
Definition json.hpp:68
bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15470
#define NLOHMANN_BASIC_JSON_TPL
Definition json.hpp:2624
#define JSON_HEDLEY_UNLIKELY(expr)
Definition json.hpp:1728
#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
Definition json.hpp:12793
#define JSON_TRY
Definition json.hpp:2538
#define NLOHMANN_JSON_NAMESPACE_END
Definition json.hpp:155
#define JSON_NO_UNIQUE_ADDRESS
Definition json.hpp:2519
basic_json< nlohmann::ordered_map > ordered_json
specialization that maintains the insertion order of object keys
Definition json.hpp:3553
#define NLOHMANN_JSON_VERSION_MINOR
Definition json.hpp:69
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)
Definition json.hpp:2908
bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15445
#define NLOHMANN_JSON_NAMESPACE_BEGIN
Definition json.hpp:145
#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
Definition json.hpp:12790
#define JSON_HEDLEY_DIAGNOSTIC_POP
Definition json.hpp:1117
#define JSON_EXPLICIT
Definition json.hpp:2945
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
Definition json.hpp:1410
#define JSON_HEDLEY_PURE
Definition json.hpp:1801
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)
Definition json.hpp:23607
#define JSON_DIAGNOSTIC_POSITIONS
Definition json.hpp:77
implements the Grisu2 algorithm for binary to decimal floating-point conversion.
Definition json.hpp:17650
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
Definition json.hpp:18097
cached_power get_cached_power_for_binary_exponent(int e)
Definition json.hpp:17933
Target reinterpret_bits(const Source source)
Definition json.hpp:17653
boundaries compute_boundaries(FloatType value)
Definition json.hpp:17794
void grisu2_round(char *buf, int len, std::uint64_t dist, std::uint64_t delta, std::uint64_t rest, std::uint64_t ten_k)
Definition json.hpp:18151
constexpr int kAlpha
Definition json.hpp:17916
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition json.hpp:18433
constexpr int kGamma
Definition json.hpp:17917
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition json.hpp:18192
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition json.hpp:18533
JSON_HEDLEY_RETURNS_NON_NULL char * format_buffer(char *buf, int len, int decimal_exponent, int min_exp, int max_exp)
prettify v = buf * 10^decimal_exponent
Definition json.hpp:18585
Definition json.hpp:4285
constexpr bool is_transparent()
Definition json.hpp:4316
constexpr bool is_c_string()
Definition json.hpp:4288
Definition json.hpp:3262
detail namespace with internal helper functions
Definition json.hpp:263
make_integer_sequence< size_t, N > make_index_sequence
Definition json.hpp:3313
decltype(std::declval< StringType & >().append(std::declval< Arg && >())) string_can_append
Definition json.hpp:4391
std::integral_constant< bool,(std::is_signed< OfType >::value &&(sizeof(T)< sizeof(OfType)))||(same_sign< OfType, T >::value &&sizeof(OfType)==sizeof(T)) > never_out_of_range
Definition json.hpp:4198
input_format_t
the supported input formats
Definition json.hpp:6469
@ bson
Definition json.hpp:6469
@ bjdata
Definition json.hpp:6469
@ ubjson
Definition json.hpp:6469
@ json
Definition json.hpp:6469
@ cbor
Definition json.hpp:6469
@ msgpack
Definition json.hpp:6469
typename detector< nonesuch, void, Op, Args... >::type detected_t
Definition json.hpp:314
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
Definition json.hpp:6061
static void unescape(StringType &s)
string unescaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3127
decltype(T::to_json(std::declval< Args >()...)) to_json_function
Definition json.hpp:3639
detector< Default, void, Op, Args... > detected_or
Definition json.hpp:317
decltype(std::declval< T & >().binary(std::declval< Binary & >())) binary_function_t
Definition json.hpp:9677
typename std::conditional< is_usable_as_key_type< typename BasicJsonType::object_comparator_t, typename BasicJsonType::object_t::key_type, KeyTypeCVRef, RequireTransparentComparator, ExcludeObjectKeyType >::value &&!is_json_iterator_of< BasicJsonType, KeyType >::value, std::true_type, std::false_type >::type is_usable_as_basic_json_key_type
Definition json.hpp:4132
is_detected< string_can_append_data, StringType, Arg > detect_string_can_append_data
Definition json.hpp:4412
decltype(std::declval< T & >().end_object()) end_object_function_t
Definition json.hpp:9689
OutStringType concat(Args &&... args)
Definition json.hpp:4471
typename T::value_type value_type_t
Definition json.hpp:3624
constexpr std::array< T, sizeof...(Args)> make_array(Args &&... args)
Definition json.hpp:3344
JSON_HEDLEY_RETURNS_NON_NULL char * to_chars(char *first, const char *last, FloatType value)
generates a decimal representation of the floating-point number value in [first, last).
Definition json.hpp:18670
decltype(std::declval< T & >().boolean(std::declval< bool >())) boolean_function_t
Definition json.hpp:9657
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
Definition json.hpp:323
is_detected< string_can_append, StringType, Arg > detect_string_can_append
Definition json.hpp:4394
typename std::enable_if< B, T >::type enable_if_t
Definition json.hpp:3217
parse_event_t
Definition json.hpp:12878
@ value
the parser finished reading a JSON value
Definition json.hpp:12890
@ key
the parser read a key of a value in an object
Definition json.hpp:12888
@ array_end
the parser read ] and finished processing a JSON array
Definition json.hpp:12886
@ array_start
the parser read [ and started to process a JSON array
Definition json.hpp:12884
@ object_start
the parser read { and started to process a JSON object
Definition json.hpp:12880
@ object_end
the parser read } and finished processing a JSON object
Definition json.hpp:12882
std::integral_constant< bool, all_signed< Types... >::value||all_unsigned< Types... >::value > same_sign
Definition json.hpp:4194
typename detector< nonesuch, void, Op, Args... >::value_t is_detected
Definition json.hpp:308
typename std::conditional< is_comparable< Comparator, ObjectKeyType, KeyTypeCVRef >::value &&!(ExcludeObjectKeyType &&std::is_same< KeyType, ObjectKeyType >::value) &&(!RequireTransparentComparator||is_detected< detect_is_transparent, Comparator >::value) &&!is_json_pointer< KeyType >::value, std::true_type, std::false_type >::type is_usable_as_key_type
Definition json.hpp:4114
typename T::pointer pointer_t
Definition json.hpp:3630
std::pair< A1, A2 > from_json_tuple_impl(BasicJsonType &&j, identity_tag< std::pair< A1, A2 > >, priority_tag< 0 >)
Definition json.hpp:5238
void from_json_array_impl(const BasicJsonType &j, typename BasicJsonType::array_t &arr, priority_tag< 3 >)
Definition json.hpp:5043
typename utility_internal::Gen< T, N >::type make_integer_sequence
Definition json.hpp:3305
conjunction< std::is_integral< Types >... > all_integral
Definition json.hpp:4184
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition json.hpp:15645
typename detected_or< Default, Op, Args... >::type detected_or_t
Definition json.hpp:320
decltype(std::declval< T & >().key(std::declval< String & >())) key_function_t
Definition json.hpp:9685
decltype(std::declval< T & >().null()) null_function_t
Definition json.hpp:9654
void int_to_string(StringType &target, std::size_t value)
Definition json.hpp:5426
T conditional_static_cast(U value)
Definition json.hpp:4172
typename T::difference_type difference_type_t
Definition json.hpp:3627
conjunction< std::is_unsigned< Types >... > all_unsigned
Definition json.hpp:4190
constexpr T static_const< T >::value
Definition json.hpp:3340
decltype(std::declval< T & >().start_object(std::declval< std::size_t >())) start_object_function_t
Definition json.hpp:9681
decltype(std::declval< T & >().number_float( std::declval< Float >(), std::declval< const String & >())) number_float_function_t
Definition json.hpp:9669
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.hpp:3093
decltype(std::declval< T & >().start_array(std::declval< std::size_t >())) start_array_function_t
Definition json.hpp:9692
is_detected< string_can_append_iter, StringType, Arg > detect_string_can_append_iter
Definition json.hpp:4406
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition json.hpp:5608
typename std::conditional< is_detected< detect_erase_with_key_type, typename BasicJsonType::object_t, KeyType >::value, std::true_type, std::false_type >::type has_erase_with_key_type
Definition json.hpp:4145
typename actual_object_comparator< BasicJsonType >::type actual_object_comparator_t
Definition json.hpp:3718
decltype(std::declval< ObjectType & >().erase(std::declval< KeyType >())) detect_erase_with_key_type
Definition json.hpp:4141
decltype(input_adapter(std::declval< const char * >(), std::declval< const char * >())) contiguous_bytes_input_adapter
Definition json.hpp:6923
cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:9804
@ ignore
ignore tags
Definition json.hpp:9806
@ store
store tags as binary type
Definition json.hpp:9807
@ error
throw a parse_error exception in case of a tag
Definition json.hpp:9805
value_type_t< iterator_traits< iterator_t< T > > > range_value_t
Definition json.hpp:3869
make_index_sequence< sizeof...(Ts)> index_sequence_for
Definition json.hpp:3321
void concat_into(OutStringType &)
Definition json.hpp:4387
constexpr bool value_in_range_of(T val)
Definition json.hpp:4272
value_t
the JSON type enumeration
Definition json.hpp:2995
@ null
null value
Definition json.hpp:2996
@ number_integer
number value (signed integer)
Definition json.hpp:3001
@ boolean
boolean value
Definition json.hpp:3000
@ discarded
discarded by the parser callback function
Definition json.hpp:3005
@ binary
binary array (ordered collection of bytes)
Definition json.hpp:3004
@ object
object (unordered set of name/value pairs)
Definition json.hpp:2997
@ string
string value
Definition json.hpp:2999
@ number_float
number value (floating-point)
Definition json.hpp:3003
@ number_unsigned
number value (unsigned integer)
Definition json.hpp:3002
@ array
array (ordered collection of values)
Definition json.hpp:2998
decltype(T::from_json(std::declval< Args >()...)) from_json_function
Definition json.hpp:3642
conjunction< std::is_signed< Types >... > all_signed
Definition json.hpp:4187
constexpr std::size_t unknown_size()
Definition json.hpp:8783
std::array< T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType &&j, identity_tag< std::array< T, sizeof...(Idx)> >, index_sequence< Idx... >)
Definition json.hpp:5126
static bool little_endianness(int num=1) noexcept
determine system byte order
Definition json.hpp:9817
StringType to_string(std::size_t value)
Definition json.hpp:5434
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition json.hpp:6310
decltype(std::declval< T & >().number_integer(std::declval< Integer >())) number_integer_function_t
Definition json.hpp:9661
typename make_void< Ts... >::type void_t
Definition json.hpp:269
std::size_t combine(std::size_t seed, std::size_t h) noexcept
Definition json.hpp:6292
decltype(std::declval< T & >().parse_error( std::declval< std::size_t >(), std::declval< const std::string & >(), std::declval< const Exception & >())) parse_error_function_t
Definition json.hpp:9699
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:3024
iterator_input_adapter_factory< IteratorType >::adapter_type input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:6859
enable_if_t< is_range< R >::value, result_of_begin< decltype(std::declval< R & >())> > iterator_t
Definition json.hpp:3866
typename T::iterator_category iterator_category_t
Definition json.hpp:3636
typename std::conditional< std::is_same< T, void >::value, json_default_base, T >::type json_base_class
Definition json.hpp:14475
is_c_string< uncvref_t< T > > is_c_string_uncvref
Definition json.hpp:4306
error_handler_t
how to treat decoding errors
Definition json.hpp:18750
@ strict
throw a type_error exception in case of invalid UTF-8
Definition json.hpp:18751
@ ignore
ignore invalid UTF-8 sequences
Definition json.hpp:18753
@ replace
replace invalid UTF-8 sequences with U+FFFD
Definition json.hpp:18752
std::size_t concat_length()
Definition json.hpp:4356
std::integral_constant< bool, Value > bool_constant
Definition json.hpp:4278
decltype(input_adapter(std::declval< std::string >())) string_input_adapter_type
Definition json.hpp:6899
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition json.hpp:3203
void from_json(const BasicJsonType &j, typename std::nullptr_t &n)
Definition json.hpp:4820
typename T::key_compare detect_key_compare
Definition json.hpp:3702
void to_json(BasicJsonType &j, T b) noexcept
Definition json.hpp:5922
void get_arithmetic_value(const BasicJsonType &j, ArithmeticType &val)
Definition json.hpp:4852
integer_sequence< size_t, Ints... > index_sequence
Definition json.hpp:3259
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
Definition json.hpp:326
is_specialization_of<::nlohmann::json_pointer, uncvref_t< T > > is_json_pointer
Definition json.hpp:4095
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().begin(), std::declval< const Arg & >().end())) string_can_append_iter
Definition json.hpp:4403
decltype(std::declval< T & >().end_array()) end_array_function_t
Definition json.hpp:9696
std::tuple< Args... > from_json_tuple_impl_base(BasicJsonType &&j, index_sequence< Idx... >)
Definition json.hpp:5226
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().data(), std::declval< const Arg & >().size())) string_can_append_data
Definition json.hpp:4409
typename T::key_type key_type_t
Definition json.hpp:3621
typename T::reference reference_t
Definition json.hpp:3633
typename T::is_transparent detect_is_transparent
Definition json.hpp:4108
bjdata_version_t
how to encode BJData
Definition json.hpp:15758
@ draft3
Definition json.hpp:15760
@ draft2
Definition json.hpp:15759
is_detected< string_can_append_op, StringType, Arg > detect_string_can_append_op
Definition json.hpp:4400
typename T::mapped_type mapped_type_t
Definition json.hpp:3618
decltype(std::declval< StringType & >()+=std::declval< Arg && >()) string_can_append_op
Definition json.hpp:4397
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3112
decltype(std::declval< T & >().string(std::declval< String & >())) string_function_t
Definition json.hpp:9673
decltype(std::declval< T >().template get< U >()) get_template_function
Definition json.hpp:3645
decltype(std::declval< T & >().number_unsigned(std::declval< Unsigned >())) number_unsigned_function_t
Definition json.hpp:9665
std::function< bool(int, parse_event_t, BasicJsonType &)> parser_callback_t
Definition json.hpp:12894
Definition json.hpp:25209
Definition json.hpp:25207
Definition json.hpp:5629
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:25282
namespace for Niels Lohmann
Definition json.hpp:6121
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:6145
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:6135
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:6125
Definition json.hpp:3710
typename BasicJsonType::object_t object_t
Definition json.hpp:3711
typename BasicJsonType::default_object_comparator_t object_comparator_t
Definition json.hpp:3712
typename std::conditional< has_key_compare< object_t >::value, typename object_t::key_compare, object_comparator_t >::type type
Definition json.hpp:3713
signed char char_type
Definition json.hpp:3757
static constexpr int_type eof() noexcept
Definition json.hpp:3771
uint64_t int_type
Definition json.hpp:3758
static char_type to_char_type(int_type i) noexcept
Definition json.hpp:3766
static int_type to_int_type(char_type c) noexcept
Definition json.hpp:3761
static char_type to_char_type(int_type i) noexcept
Definition json.hpp:3742
static constexpr int_type eof() noexcept
Definition json.hpp:3747
unsigned char char_type
Definition json.hpp:3733
uint64_t int_type
Definition json.hpp:3734
static int_type to_int_type(char_type c) noexcept
Definition json.hpp:3737
Definition json.hpp:3727
Definition json.hpp:3782
decltype(input_adapter(begin(std::declval< ContainerType >()), end(std::declval< ContainerType >()))) adapter_type
Definition json.hpp:6882
Definition json.hpp:295
std::false_type value_t
Definition json.hpp:296
Default type
Definition json.hpp:297
Definition json.hpp:17781
diyfp w
Definition json.hpp:17782
diyfp minus
Definition json.hpp:17783
diyfp plus
Definition json.hpp:17784
Definition json.hpp:17920
std::uint64_t f
Definition json.hpp:17921
int e
Definition json.hpp:17922
int k
Definition json.hpp:17923
Definition json.hpp:17663
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition json.hpp:17687
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
Definition json.hpp:17769
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition json.hpp:17752
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition json.hpp:17675
constexpr diyfp(std::uint64_t f_, int e_) noexcept
Definition json.hpp:17669
static constexpr int kPrecision
Definition json.hpp:17664
std::uint64_t f
Definition json.hpp:17666
int e
Definition json.hpp:17667
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
Definition json.hpp:5831
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
Definition json.hpp:5806
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
Definition json.hpp:5796
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
Definition json.hpp:5818
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
Definition json.hpp:5847
static void construct(BasicJsonType &j, const typename BasicJsonType::binary_t &b)
Definition json.hpp:5735
static void construct(BasicJsonType &j, typename BasicJsonType::binary_t &&b)
Definition json.hpp:5744
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
Definition json.hpp:5689
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
Definition json.hpp:5757
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
Definition json.hpp:5783
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
Definition json.hpp:5770
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
Definition json.hpp:5866
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
Definition json.hpp:5887
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
Definition json.hpp:5876
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
Definition json.hpp:5711
static void construct(BasicJsonType &j, const CompatibleStringType &str)
Definition json.hpp:5722
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
Definition json.hpp:5702
Definition json.hpp:5683
Definition json.hpp:5327
auto operator()(const BasicJsonType &j, T &&val) const noexcept(noexcept(from_json(j, std::forward< T >(val)))) -> decltype(from_json(j, std::forward< T >(val)))
Definition json.hpp:5329
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3664
Definition json.hpp:3649
Definition json.hpp:3705
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3679
Definition json.hpp:3674
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3694
Definition json.hpp:3689
Definition json.hpp:4771
Definition json.hpp:3245
T value_type
Definition json.hpp:3246
static constexpr std::size_t size() noexcept
Definition json.hpp:3247
an iterator value
Definition json.hpp:13524
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition json.hpp:13528
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition json.hpp:13530
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition json.hpp:13526
Definition json.hpp:3598
Definition json.hpp:3585
Definition json.hpp:4303
Definition json.hpp:4099
Definition json.hpp:3982
Definition json.hpp:4053
Definition json.hpp:3903
Definition json.hpp:3940
static constexpr auto value
Definition json.hpp:3941
Definition json.hpp:4056
Definition json.hpp:4069
Definition json.hpp:3876
Definition json.hpp:4026
Definition json.hpp:3936
Definition json.hpp:3947
ConstructibleStringType laundered_type
Definition json.hpp:3952
static constexpr auto value
Definition json.hpp:3955
Definition json.hpp:4072
Definition json.hpp:3814
Definition json.hpp:3795
Definition json.hpp:311
Definition json.hpp:3657
static constexpr bool value
Definition json.hpp:3658
Definition json.hpp:6835
typename std::iterator_traits< T >::value_type value_type
Definition json.hpp:6836
static constexpr auto value
Definition json.hpp:3838
iterator_traits< T > traits
Definition json.hpp:3835
Definition json.hpp:3829
Definition json.hpp:4078
Definition json.hpp:3608
Definition json.hpp:4160
char x[2]
Definition json.hpp:4161
Definition json.hpp:4156
static one test(decltype(&C::capacity))
char one
Definition json.hpp:4157
@ value
Definition json.hpp:4167
static two test(...)
Definition json.hpp:3848
detected_t< result_of_end, t_ref > sentinel
Definition json.hpp:3853
detected_t< result_of_begin, t_ref > iterator
Definition json.hpp:3852
typename std::add_lvalue_reference< T >::type t_ref
Definition json.hpp:3850
static constexpr bool value
Definition json.hpp:3862
static constexpr auto is_iterator_begin
Definition json.hpp:3858
Definition json.hpp:9736
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9741
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9742
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9745
typename BasicJsonType::exception exception_t
Definition json.hpp:9746
typename BasicJsonType::string_t string_t
Definition json.hpp:9744
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9743
Definition json.hpp:9705
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9714
typename BasicJsonType::exception exception_t
Definition json.hpp:9715
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9712
typename BasicJsonType::string_t string_t
Definition json.hpp:9713
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9711
static constexpr bool value
Definition json.hpp:9718
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9710
Definition json.hpp:4089
Definition json.hpp:4325
typename std::iterator_traits< iterator_type >::value_type char_type
Definition json.hpp:6847
wide_string_input_adapter< base_adapter_type, char_type > adapter_type
Definition json.hpp:6849
static adapter_type create(IteratorType first, IteratorType last)
Definition json.hpp:6851
iterator_input_adapter< iterator_type > adapter_type
Definition json.hpp:6825
typename std::iterator_traits< iterator_type >::value_type char_type
Definition json.hpp:6824
static adapter_type create(IteratorType first, IteratorType last)
Definition json.hpp:6827
IteratorType iterator_type
Definition json.hpp:6823
std::random_access_iterator_tag iterator_category
Definition json.hpp:3425
Definition json.hpp:3413
Definition json.hpp:3394
Default base class of the basic_json class.
Definition json.hpp:14472
Definition json.hpp:266
void type
Definition json.hpp:267
Definition json.hpp:3789
Definition json.hpp:281
nonesuch(nonesuch const &&)=delete
~nonesuch()=delete
void operator=(nonesuch &&)=delete
void operator=(nonesuch const &)=delete
nonesuch(nonesuch const &)=delete
abstract output adapter interface
Definition json.hpp:15631
output_adapter_protocol(const output_adapter_protocol &)=default
virtual ~output_adapter_protocol()=default
virtual void write_character(CharType c)=0
output_adapter_protocol(output_adapter_protocol &&) noexcept=default
virtual void write_characters(const CharType *s, std::size_t length)=0
struct to capture the start position of the current token
Definition json.hpp:3158
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:3162
std::size_t lines_read
the number of lines read
Definition json.hpp:3164
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:3160
Definition json.hpp:3328
Definition json.hpp:3334
static JSON_INLINE_VARIABLE constexpr T value
Definition json.hpp:3335
Definition json.hpp:6088
auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward< T >(val)))) -> decltype(to_json(j, std::forward< T >(val)), void())
Definition json.hpp:6090
integer_sequence< T, Ints...,(Ints+SeqSize)... > type
Definition json.hpp:3271
integer_sequence< T, Ints...,(Ints+SeqSize)..., 2 *SeqSize > type
Definition json.hpp:3277
Definition json.hpp:3265
integer_sequence< T > type
Definition json.hpp:3292
Definition json.hpp:3284
typename Extend< typename Gen< T, N/2 >::type, N/2, N % 2 >::type type
Definition json.hpp:3285
static constexpr bool test(T val)
Definition json.hpp:4256
static constexpr bool test(T)
Definition json.hpp:4265
Definition json.hpp:4251
static constexpr bool test(T val)
Definition json.hpp:4210
static constexpr bool test(T val)
Definition json.hpp:4230
static constexpr bool test(T val)
Definition json.hpp:4220
static constexpr bool test(T val)
Definition json.hpp:4240
Definition json.hpp:4205
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.hpp:6710
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.hpp:6652
Definition json.hpp:6646
Definition json.hpp:14535
T type
Definition json.hpp:14536
SAX interface.
Definition json.hpp:8668
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
json_sax()=default
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:8669
typename BasicJsonType::string_t string_t
Definition json.hpp:8672
virtual bool end_array()=0
the end of an array was read
json_sax(const json_sax &)=default
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:8671
virtual bool null()=0
a null value was read
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:8670
json_sax(json_sax &&) noexcept=default
typename BasicJsonType::binary_t binary_t
Definition json.hpp:8673
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:19732
std::vector< std::pair< const Key, T >, Allocator > Container
Definition json.hpp:19735
std::pair< iterator, bool > insert(value_type &&value)
Definition json.hpp:20026
typename Container::value_type value_type
Definition json.hpp:19739
std::equal_to< Key > key_compare
Definition json.hpp:19743
iterator erase(iterator pos)
Definition json.hpp:19904
T mapped_type
Definition json.hpp:19734
ordered_map(const Allocator &alloc) noexcept(noexcept(Container(alloc)))
Definition json.hpp:19749
T & operator[](KeyType &&key)
Definition json.hpp:19791
typename Container::iterator iterator
Definition json.hpp:19736
const T & at(KeyType &&key) const
Definition json.hpp:19851
T & at(KeyType &&key)
Definition json.hpp:19823
const T & operator[](KeyType &&key) const
Definition json.hpp:19803
iterator find(const key_type &key)
Definition json.hpp:19988
iterator erase(iterator first, iterator last)
Definition json.hpp:19909
const T & at(const key_type &key) const
Definition json.hpp:19836
const_iterator find(const key_type &key) const
Definition json.hpp:20014
T & operator[](const key_type &key)
Definition json.hpp:19784
size_type erase(KeyType &&key)
Definition json.hpp:19885
typename Container::size_type size_type
Definition json.hpp:19738
ordered_map() noexcept(noexcept(Container()))
Definition json.hpp:19748
void insert(InputIt first, InputIt last)
Definition json.hpp:20049
size_type count(const key_type &key) const
Definition json.hpp:19962
std::pair< iterator, bool > emplace(KeyType &&key, T &&t)
Definition json.hpp:19771
typename std::enable_if< std::is_convertible< typename std::iterator_traits< InputIt >::iterator_category, std::input_iterator_tag >::value >::type require_input_iter
Definition json.hpp:20045
size_type erase(const key_type &key)
Definition json.hpp:19864
ordered_map(std::initializer_list< value_type > init, const Allocator &alloc=Allocator())
Definition json.hpp:19753
std::pair< iterator, bool > insert(const value_type &value)
Definition json.hpp:20031
size_type count(KeyType &&key) const
Definition json.hpp:19976
Key key_type
Definition json.hpp:19733
ordered_map(It first, It last, const Allocator &alloc=Allocator())
Definition json.hpp:19751
const T & operator[](const key_type &key) const
Definition json.hpp:19796
JSON_NO_UNIQUE_ADDRESS key_compare m_compare
Definition json.hpp:20058
iterator find(KeyType &&key)
Definition json.hpp:20002
T & at(const key_type &key)
Definition json.hpp:19808
typename Container::const_iterator const_iterator
Definition json.hpp:19737
std::pair< iterator, bool > emplace(const key_type &key, T &&t)
Definition json.hpp:19756
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL &j) const
Definition json.hpp:25251
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:25265