Minecraft Community Edition 0.1.0
Loading...
Searching...
No Matches
json.hpp
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.12.0
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9/****************************************************************************\
10 * Note on documentation: The source files contain links to the online *
11 * documentation of the public API at https://json.nlohmann.me. This URL *
12 * contains the most recent documentation and should also be applicable to *
13 * previous versions; documentation for deprecated functions is not *
14 * removed, but marked deprecated. See "Generate documentation" section in *
15 * file docs/README.md. *
16\****************************************************************************/
17
18#ifndef INCLUDE_NLOHMANN_JSON_HPP_
19#define INCLUDE_NLOHMANN_JSON_HPP_
20
21#include <algorithm> // all_of, find, for_each
22#include <cstddef> // nullptr_t, ptrdiff_t, size_t
23#include <functional> // hash, less
24#include <initializer_list> // initializer_list
25#ifndef JSON_NO_IO
26#include <iosfwd> // istream, ostream
27#endif // JSON_NO_IO
28#include <iterator> // random_access_iterator_tag
29#include <memory> // unique_ptr
30#include <string> // string, stoi, to_string
31#include <utility> // declval, forward, move, pair, swap
32#include <vector> // vector
33
34// #include <nlohmann/adl_serializer.hpp>
35// __ _____ _____ _____
36// __| | __| | | | JSON for Modern C++
37// | | |__ | | | | | | version 3.12.0
38// |_____|_____|_____|_|___| https://github.com/nlohmann/json
39//
40// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
41// SPDX-License-Identifier: MIT
42
43
44
45#include <utility>
46
47// #include <nlohmann/detail/abi_macros.hpp>
48// __ _____ _____ _____
49// __| | __| | | | JSON for Modern C++
50// | | |__ | | | | | | version 3.12.0
51// |_____|_____|_____|_|___| https://github.com/nlohmann/json
52//
53// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
54// SPDX-License-Identifier: MIT
55
56
57
58// This file contains all macro definitions affecting or depending on the ABI
59
60#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
61#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
62#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0
63#warning "Already included a different version of the library!"
64#endif
65#endif
66#endif
67
68#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
69#define NLOHMANN_JSON_VERSION_MINOR 12 // NOLINT(modernize-macro-to-enum)
70#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum)
71
72#ifndef JSON_DIAGNOSTICS
73#define JSON_DIAGNOSTICS 0
74#endif
75
76#ifndef JSON_DIAGNOSTIC_POSITIONS
77#define JSON_DIAGNOSTIC_POSITIONS 0
78#endif
79
80#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
81#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
82#endif
83
84#if JSON_DIAGNOSTICS
85#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
86#else
87#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
88#endif
89
90#if JSON_DIAGNOSTIC_POSITIONS
91#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp
92#else
93#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS
94#endif
95
96#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
97#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
98#else
99#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
100#endif
101
102#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
103#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
104#endif
105
106// Construct the namespace ABI tags component
107#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c
108#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \
109 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c)
110
111#define NLOHMANN_JSON_ABI_TAGS \
112 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
113 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
114 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \
115 NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS)
116
117// Construct the namespace version component
118#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
119 _v ## major ## _ ## minor ## _ ## patch
120#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
121 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
122
123#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
124#define NLOHMANN_JSON_NAMESPACE_VERSION
125#else
126#define NLOHMANN_JSON_NAMESPACE_VERSION \
127 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
128 NLOHMANN_JSON_VERSION_MINOR, \
129 NLOHMANN_JSON_VERSION_PATCH)
130#endif
131
132// Combine namespace components
133#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
134#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
135 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
136
137#ifndef NLOHMANN_JSON_NAMESPACE
138#define NLOHMANN_JSON_NAMESPACE \
139 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
140 NLOHMANN_JSON_ABI_TAGS, \
141 NLOHMANN_JSON_NAMESPACE_VERSION)
142#endif
143
144#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
145#define NLOHMANN_JSON_NAMESPACE_BEGIN \
146 namespace nlohmann \
147 { \
148 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
149 NLOHMANN_JSON_ABI_TAGS, \
150 NLOHMANN_JSON_NAMESPACE_VERSION) \
151 {
152#endif
153
154#ifndef NLOHMANN_JSON_NAMESPACE_END
155#define NLOHMANN_JSON_NAMESPACE_END \
156 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
157 } // namespace nlohmann
158#endif
159
160// #include <nlohmann/detail/conversions/from_json.hpp>
161// __ _____ _____ _____
162// __| | __| | | | JSON for Modern C++
163// | | |__ | | | | | | version 3.12.0
164// |_____|_____|_____|_|___| https://github.com/nlohmann/json
165//
166// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
167// SPDX-License-Identifier: MIT
168
169
170
171#include <algorithm> // transform
172#include <array> // array
173#include <forward_list> // forward_list
174#include <iterator> // inserter, front_inserter, end
175#include <map> // map
176#include <string> // string
177#include <tuple> // tuple, make_tuple
178#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
179#include <unordered_map> // unordered_map
180#include <utility> // pair, declval
181#include <valarray> // valarray
182
183// #include <nlohmann/detail/exceptions.hpp>
184// __ _____ _____ _____
185// __| | __| | | | JSON for Modern C++
186// | | |__ | | | | | | version 3.12.0
187// |_____|_____|_____|_|___| https://github.com/nlohmann/json
188//
189// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
190// SPDX-License-Identifier: MIT
191
192
193
194#include <cstddef> // nullptr_t
195#include <exception> // exception
196#if JSON_DIAGNOSTICS
197#include <numeric> // accumulate
198#endif
199#include <stdexcept> // runtime_error
200#include <string> // to_string
201#include <vector> // vector
202
203// #include <nlohmann/detail/value_t.hpp>
204// __ _____ _____ _____
205// __| | __| | | | JSON for Modern C++
206// | | |__ | | | | | | version 3.12.0
207// |_____|_____|_____|_|___| https://github.com/nlohmann/json
208//
209// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
210// SPDX-License-Identifier: MIT
211
212
213
214#include <array> // array
215#include <cstddef> // size_t
216#include <cstdint> // uint8_t
217#include <string> // string
218
219// #include <nlohmann/detail/macro_scope.hpp>
220// __ _____ _____ _____
221// __| | __| | | | JSON for Modern C++
222// | | |__ | | | | | | version 3.12.0
223// |_____|_____|_____|_|___| https://github.com/nlohmann/json
224//
225// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
226// SPDX-License-Identifier: MIT
227
228
229
230#include <utility> // declval, pair
231// #include <nlohmann/detail/meta/detected.hpp>
232// __ _____ _____ _____
233// __| | __| | | | JSON for Modern C++
234// | | |__ | | | | | | version 3.12.0
235// |_____|_____|_____|_|___| https://github.com/nlohmann/json
236//
237// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
238// SPDX-License-Identifier: MIT
239
240
241
242#include <type_traits>
243
244// #include <nlohmann/detail/meta/void_t.hpp>
245// __ _____ _____ _____
246// __| | __| | | | JSON for Modern C++
247// | | |__ | | | | | | version 3.12.0
248// |_____|_____|_____|_|___| https://github.com/nlohmann/json
249//
250// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
251// SPDX-License-Identifier: MIT
252
253
254
255// #include <nlohmann/detail/abi_macros.hpp>
256
257
258NLOHMANN_JSON_NAMESPACE_BEGIN
259namespace detail {
260
261 template<typename ...Ts> struct make_void {
262 using type = void;
263 };
264 template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
265
266} // namespace detail
267NLOHMANN_JSON_NAMESPACE_END
268
269
270NLOHMANN_JSON_NAMESPACE_BEGIN
271namespace detail {
272
273 // https://en.cppreference.com/w/cpp/experimental/is_detected
274 struct nonesuch {
275 nonesuch() = delete;
276 ~nonesuch() = delete;
277 nonesuch(nonesuch const&) = delete;
278 nonesuch(nonesuch const&&) = delete;
279 void operator=(nonesuch const&) = delete;
280 void operator=(nonesuch&&) = delete;
281 };
282
283 template<class Default,
284 class AlwaysVoid,
285 template<class...> class Op,
286 class... Args>
287 struct detector {
288 using value_t = std::false_type;
289 using type = Default;
290 };
291
292 template<class Default, template<class...> class Op, class... Args>
293 struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
294 using value_t = std::true_type;
295 using type = Op<Args...>;
296 };
297
298 template<template<class...> class Op, class... Args>
299 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
300
301 template<template<class...> class Op, class... Args>
302 struct is_detected_lazy : is_detected<Op, Args...> {};
303
304 template<template<class...> class Op, class... Args>
305 using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
306
307 template<class Default, template<class...> class Op, class... Args>
308 using detected_or = detector<Default, void, Op, Args...>;
309
310 template<class Default, template<class...> class Op, class... Args>
311 using detected_or_t = typename detected_or<Default, Op, Args...>::type;
312
313 template<class Expected, template<class...> class Op, class... Args>
314 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
315
316 template<class To, template<class...> class Op, class... Args>
317 using is_detected_convertible =
318 std::is_convertible<detected_t<Op, Args...>, To>;
319
320} // namespace detail
321NLOHMANN_JSON_NAMESPACE_END
322
323// #include <nlohmann/thirdparty/hedley/hedley.hpp>
324
325
326// __ _____ _____ _____
327// __| | __| | | | JSON for Modern C++
328// | | |__ | | | | | | version 3.12.0
329// |_____|_____|_____|_|___| https://github.com/nlohmann/json
330//
331// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
332// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com>
333// SPDX-License-Identifier: MIT
334
335/* Hedley - https://nemequ.github.io/hedley
336 * Created by Evan Nemerson <evan@nemerson.com>
337 * SPDX-License-Identifier: CC0-1.0
338 */
339
340#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
341#if defined(JSON_HEDLEY_VERSION)
342#undef JSON_HEDLEY_VERSION
343#endif
344#define JSON_HEDLEY_VERSION 15
345
346#if defined(JSON_HEDLEY_STRINGIFY_EX)
347#undef JSON_HEDLEY_STRINGIFY_EX
348#endif
349#define JSON_HEDLEY_STRINGIFY_EX(x) #x
350
351#if defined(JSON_HEDLEY_STRINGIFY)
352#undef JSON_HEDLEY_STRINGIFY
353#endif
354#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
355
356#if defined(JSON_HEDLEY_CONCAT_EX)
357#undef JSON_HEDLEY_CONCAT_EX
358#endif
359#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
360
361#if defined(JSON_HEDLEY_CONCAT)
362#undef JSON_HEDLEY_CONCAT
363#endif
364#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
365
366#if defined(JSON_HEDLEY_CONCAT3_EX)
367#undef JSON_HEDLEY_CONCAT3_EX
368#endif
369#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
370
371#if defined(JSON_HEDLEY_CONCAT3)
372#undef JSON_HEDLEY_CONCAT3
373#endif
374#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
375
376#if defined(JSON_HEDLEY_VERSION_ENCODE)
377#undef JSON_HEDLEY_VERSION_ENCODE
378#endif
379#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
380
381#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
382#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
383#endif
384#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
385
386#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
387#undef JSON_HEDLEY_VERSION_DECODE_MINOR
388#endif
389#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
390
391#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
392#undef JSON_HEDLEY_VERSION_DECODE_REVISION
393#endif
394#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
395
396#if defined(JSON_HEDLEY_GNUC_VERSION)
397#undef JSON_HEDLEY_GNUC_VERSION
398#endif
399#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
400#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
401#elif defined(__GNUC__)
402#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
403#endif
404
405#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
406#undef JSON_HEDLEY_GNUC_VERSION_CHECK
407#endif
408#if defined(JSON_HEDLEY_GNUC_VERSION)
409#define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
410#else
411#define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
412#endif
413
414#if defined(JSON_HEDLEY_MSVC_VERSION)
415#undef JSON_HEDLEY_MSVC_VERSION
416#endif
417#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
418#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
419#elif defined(_MSC_FULL_VER) && !defined(__ICL)
420#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
421#elif defined(_MSC_VER) && !defined(__ICL)
422#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
423#endif
424
425#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
426#undef JSON_HEDLEY_MSVC_VERSION_CHECK
427#endif
428#if !defined(JSON_HEDLEY_MSVC_VERSION)
429#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
430#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
431#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
432#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
433#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
434#else
435#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
436#endif
437
438#if defined(JSON_HEDLEY_INTEL_VERSION)
439#undef JSON_HEDLEY_INTEL_VERSION
440#endif
441#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
442#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
443#elif defined(__INTEL_COMPILER) && !defined(__ICL)
444#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
445#endif
446
447#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
448#undef JSON_HEDLEY_INTEL_VERSION_CHECK
449#endif
450#if defined(JSON_HEDLEY_INTEL_VERSION)
451#define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
452#else
453#define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
454#endif
455
456#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
457#undef JSON_HEDLEY_INTEL_CL_VERSION
458#endif
459#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
460#define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
461#endif
462
463#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
464#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
465#endif
466#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
467#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
468#else
469#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
470#endif
471
472#if defined(JSON_HEDLEY_PGI_VERSION)
473#undef JSON_HEDLEY_PGI_VERSION
474#endif
475#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
476#define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
477#endif
478
479#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
480#undef JSON_HEDLEY_PGI_VERSION_CHECK
481#endif
482#if defined(JSON_HEDLEY_PGI_VERSION)
483#define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
484#else
485#define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
486#endif
487
488#if defined(JSON_HEDLEY_SUNPRO_VERSION)
489#undef JSON_HEDLEY_SUNPRO_VERSION
490#endif
491#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
492#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)
493#elif defined(__SUNPRO_C)
494#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
495#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
496#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)
497#elif defined(__SUNPRO_CC)
498#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
499#endif
500
501#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
502#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
503#endif
504#if defined(JSON_HEDLEY_SUNPRO_VERSION)
505#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
506#else
507#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
508#endif
509
510#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
511#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
512#endif
513#if defined(__EMSCRIPTEN__)
514#define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
515#endif
516
517#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
518#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
519#endif
520#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
521#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
522#else
523#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
524#endif
525
526#if defined(JSON_HEDLEY_ARM_VERSION)
527#undef JSON_HEDLEY_ARM_VERSION
528#endif
529#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
530#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
531#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
532#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
533#endif
534
535#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
536#undef JSON_HEDLEY_ARM_VERSION_CHECK
537#endif
538#if defined(JSON_HEDLEY_ARM_VERSION)
539#define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
540#else
541#define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
542#endif
543
544#if defined(JSON_HEDLEY_IBM_VERSION)
545#undef JSON_HEDLEY_IBM_VERSION
546#endif
547#if defined(__ibmxl__)
548#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
549#elif defined(__xlC__) && defined(__xlC_ver__)
550#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
551#elif defined(__xlC__)
552#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
553#endif
554
555#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
556#undef JSON_HEDLEY_IBM_VERSION_CHECK
557#endif
558#if defined(JSON_HEDLEY_IBM_VERSION)
559#define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
560#else
561#define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
562#endif
563
564#if defined(JSON_HEDLEY_TI_VERSION)
565#undef JSON_HEDLEY_TI_VERSION
566#endif
567#if \
568 defined(__TI_COMPILER_VERSION__) && \
569 ( \
570 defined(__TMS470__) || defined(__TI_ARM__) || \
571 defined(__MSP430__) || \
572 defined(__TMS320C2000__) \
573 )
574#if (__TI_COMPILER_VERSION__ >= 16000000)
575#define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
576#endif
577#endif
578
579#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
580#undef JSON_HEDLEY_TI_VERSION_CHECK
581#endif
582#if defined(JSON_HEDLEY_TI_VERSION)
583#define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
584#else
585#define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
586#endif
587
588#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
589#undef JSON_HEDLEY_TI_CL2000_VERSION
590#endif
591#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
592#define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
593#endif
594
595#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
596#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
597#endif
598#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
599#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
600#else
601#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
602#endif
603
604#if defined(JSON_HEDLEY_TI_CL430_VERSION)
605#undef JSON_HEDLEY_TI_CL430_VERSION
606#endif
607#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
608#define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
609#endif
610
611#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
612#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
613#endif
614#if defined(JSON_HEDLEY_TI_CL430_VERSION)
615#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
616#else
617#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
618#endif
619
620#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
621#undef JSON_HEDLEY_TI_ARMCL_VERSION
622#endif
623#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
624#define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
625#endif
626
627#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
628#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
629#endif
630#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
631#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
632#else
633#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
634#endif
635
636#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
637#undef JSON_HEDLEY_TI_CL6X_VERSION
638#endif
639#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
640#define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
641#endif
642
643#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
644#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
645#endif
646#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
647#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
648#else
649#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
650#endif
651
652#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
653#undef JSON_HEDLEY_TI_CL7X_VERSION
654#endif
655#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
656#define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
657#endif
658
659#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
660#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
661#endif
662#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
663#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
664#else
665#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
666#endif
667
668#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
669#undef JSON_HEDLEY_TI_CLPRU_VERSION
670#endif
671#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
672#define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
673#endif
674
675#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
676#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
677#endif
678#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
679#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
680#else
681#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
682#endif
683
684#if defined(JSON_HEDLEY_CRAY_VERSION)
685#undef JSON_HEDLEY_CRAY_VERSION
686#endif
687#if defined(_CRAYC)
688#if defined(_RELEASE_PATCHLEVEL)
689#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
690#else
691#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
692#endif
693#endif
694
695#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
696#undef JSON_HEDLEY_CRAY_VERSION_CHECK
697#endif
698#if defined(JSON_HEDLEY_CRAY_VERSION)
699#define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
700#else
701#define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
702#endif
703
704#if defined(JSON_HEDLEY_IAR_VERSION)
705#undef JSON_HEDLEY_IAR_VERSION
706#endif
707#if defined(__IAR_SYSTEMS_ICC__)
708#if __VER__ > 1000
709#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
710#else
711#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
712#endif
713#endif
714
715#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
716#undef JSON_HEDLEY_IAR_VERSION_CHECK
717#endif
718#if defined(JSON_HEDLEY_IAR_VERSION)
719#define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
720#else
721#define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
722#endif
723
724#if defined(JSON_HEDLEY_TINYC_VERSION)
725#undef JSON_HEDLEY_TINYC_VERSION
726#endif
727#if defined(__TINYC__)
728#define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
729#endif
730
731#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
732#undef JSON_HEDLEY_TINYC_VERSION_CHECK
733#endif
734#if defined(JSON_HEDLEY_TINYC_VERSION)
735#define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
736#else
737#define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
738#endif
739
740#if defined(JSON_HEDLEY_DMC_VERSION)
741#undef JSON_HEDLEY_DMC_VERSION
742#endif
743#if defined(__DMC__)
744#define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
745#endif
746
747#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
748#undef JSON_HEDLEY_DMC_VERSION_CHECK
749#endif
750#if defined(JSON_HEDLEY_DMC_VERSION)
751#define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
752#else
753#define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
754#endif
755
756#if defined(JSON_HEDLEY_COMPCERT_VERSION)
757#undef JSON_HEDLEY_COMPCERT_VERSION
758#endif
759#if defined(__COMPCERT_VERSION__)
760#define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
761#endif
762
763#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
764#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
765#endif
766#if defined(JSON_HEDLEY_COMPCERT_VERSION)
767#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
768#else
769#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
770#endif
771
772#if defined(JSON_HEDLEY_PELLES_VERSION)
773#undef JSON_HEDLEY_PELLES_VERSION
774#endif
775#if defined(__POCC__)
776#define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
777#endif
778
779#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
780#undef JSON_HEDLEY_PELLES_VERSION_CHECK
781#endif
782#if defined(JSON_HEDLEY_PELLES_VERSION)
783#define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
784#else
785#define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
786#endif
787
788#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
789#undef JSON_HEDLEY_MCST_LCC_VERSION
790#endif
791#if defined(__LCC__) && defined(__LCC_MINOR__)
792#define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
793#endif
794
795#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
796#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
797#endif
798#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
799#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
800#else
801#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
802#endif
803
804#if defined(JSON_HEDLEY_GCC_VERSION)
805#undef JSON_HEDLEY_GCC_VERSION
806#endif
807#if \
808 defined(JSON_HEDLEY_GNUC_VERSION) && \
809 !defined(__clang__) && \
810 !defined(JSON_HEDLEY_INTEL_VERSION) && \
811 !defined(JSON_HEDLEY_PGI_VERSION) && \
812 !defined(JSON_HEDLEY_ARM_VERSION) && \
813 !defined(JSON_HEDLEY_CRAY_VERSION) && \
814 !defined(JSON_HEDLEY_TI_VERSION) && \
815 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
816 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
817 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
818 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
819 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
820 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
821 !defined(__COMPCERT__) && \
822 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
823#define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
824#endif
825
826#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
827#undef JSON_HEDLEY_GCC_VERSION_CHECK
828#endif
829#if defined(JSON_HEDLEY_GCC_VERSION)
830#define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
831#else
832#define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
833#endif
834
835#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
836#undef JSON_HEDLEY_HAS_ATTRIBUTE
837#endif
838#if \
839 defined(__has_attribute) && \
840 ( \
841 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
842 )
843# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
844#else
845# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
846#endif
847
848#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
849#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
850#endif
851#if defined(__has_attribute)
852#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
853#else
854#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
855#endif
856
857#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
858#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
859#endif
860#if defined(__has_attribute)
861#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
862#else
863#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
864#endif
865
866#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
867#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
868#endif
869#if \
870 defined(__has_cpp_attribute) && \
871 defined(__cplusplus) && \
872 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
873#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
874#else
875#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
876#endif
877
878#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
879#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
880#endif
881#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
882#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
883#elif \
884 !defined(JSON_HEDLEY_PGI_VERSION) && \
885 !defined(JSON_HEDLEY_IAR_VERSION) && \
886 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
887 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
888#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
889#else
890#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
891#endif
892
893#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
894#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
895#endif
896#if defined(__has_cpp_attribute) && defined(__cplusplus)
897#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
898#else
899#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
900#endif
901
902#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
903#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
904#endif
905#if defined(__has_cpp_attribute) && defined(__cplusplus)
906#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
907#else
908#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
909#endif
910
911#if defined(JSON_HEDLEY_HAS_BUILTIN)
912#undef JSON_HEDLEY_HAS_BUILTIN
913#endif
914#if defined(__has_builtin)
915#define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
916#else
917#define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
918#endif
919
920#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
921#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
922#endif
923#if defined(__has_builtin)
924#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
925#else
926#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
927#endif
928
929#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
930#undef JSON_HEDLEY_GCC_HAS_BUILTIN
931#endif
932#if defined(__has_builtin)
933#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
934#else
935#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
936#endif
937
938#if defined(JSON_HEDLEY_HAS_FEATURE)
939#undef JSON_HEDLEY_HAS_FEATURE
940#endif
941#if defined(__has_feature)
942#define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
943#else
944#define JSON_HEDLEY_HAS_FEATURE(feature) (0)
945#endif
946
947#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
948#undef JSON_HEDLEY_GNUC_HAS_FEATURE
949#endif
950#if defined(__has_feature)
951#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
952#else
953#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
954#endif
955
956#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
957#undef JSON_HEDLEY_GCC_HAS_FEATURE
958#endif
959#if defined(__has_feature)
960#define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
961#else
962#define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
963#endif
964
965#if defined(JSON_HEDLEY_HAS_EXTENSION)
966#undef JSON_HEDLEY_HAS_EXTENSION
967#endif
968#if defined(__has_extension)
969#define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
970#else
971#define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
972#endif
973
974#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
975#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
976#endif
977#if defined(__has_extension)
978#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
979#else
980#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
981#endif
982
983#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
984#undef JSON_HEDLEY_GCC_HAS_EXTENSION
985#endif
986#if defined(__has_extension)
987#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
988#else
989#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
990#endif
991
992#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
993#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
994#endif
995#if defined(__has_declspec_attribute)
996#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
997#else
998#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
999#endif
1000
1001#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1002#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1003#endif
1004#if defined(__has_declspec_attribute)
1005#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1006#else
1007#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1008#endif
1009
1010#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1011#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1012#endif
1013#if defined(__has_declspec_attribute)
1014#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1015#else
1016#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1017#endif
1018
1019#if defined(JSON_HEDLEY_HAS_WARNING)
1020#undef JSON_HEDLEY_HAS_WARNING
1021#endif
1022#if defined(__has_warning)
1023#define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1024#else
1025#define JSON_HEDLEY_HAS_WARNING(warning) (0)
1026#endif
1027
1028#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1029#undef JSON_HEDLEY_GNUC_HAS_WARNING
1030#endif
1031#if defined(__has_warning)
1032#define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1033#else
1034#define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1035#endif
1036
1037#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1038#undef JSON_HEDLEY_GCC_HAS_WARNING
1039#endif
1040#if defined(__has_warning)
1041#define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1042#else
1043#define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1044#endif
1045
1046#if \
1047 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1048 defined(__clang__) || \
1049 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1050 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1051 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1052 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1053 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1054 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1055 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1056 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1057 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1058 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1059 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1060 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1061 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1062 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1063 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1064 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1065#define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1066#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1067#define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1068#else
1069#define JSON_HEDLEY_PRAGMA(value)
1070#endif
1071
1072#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1073#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1074#endif
1075#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1076#undef JSON_HEDLEY_DIAGNOSTIC_POP
1077#endif
1078#if defined(__clang__)
1079#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1080#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1081#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1082#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1083#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1084#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1085#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1086#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1087#elif \
1088 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1089 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1090#define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1091#define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1092#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1093#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1094#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1095#elif \
1096 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1097 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1098 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1099 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1100 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1101 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1102#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1103#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1104#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1105#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1106#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1107#else
1108#define JSON_HEDLEY_DIAGNOSTIC_PUSH
1109#define JSON_HEDLEY_DIAGNOSTIC_POP
1110#endif
1111
1112 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1113 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1114#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1115#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1116#endif
1117#if defined(__cplusplus)
1118# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1119# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1120# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1121# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1122 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1123 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1124 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1125 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1126 xpr \
1127 JSON_HEDLEY_DIAGNOSTIC_POP
1128# else
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 xpr \
1134 JSON_HEDLEY_DIAGNOSTIC_POP
1135# endif
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 xpr \
1141 JSON_HEDLEY_DIAGNOSTIC_POP
1142# endif
1143# endif
1144#endif
1145#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1146#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1147#endif
1148
1149#if defined(JSON_HEDLEY_CONST_CAST)
1150#undef JSON_HEDLEY_CONST_CAST
1151#endif
1152#if defined(__cplusplus)
1153# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1154#elif \
1155 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1156 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1157 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1158# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1159 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1160 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1161 ((T) (expr)); \
1162 JSON_HEDLEY_DIAGNOSTIC_POP \
1163 }))
1164#else
1165# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1166#endif
1167
1168#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1169#undef JSON_HEDLEY_REINTERPRET_CAST
1170#endif
1171#if defined(__cplusplus)
1172#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1173#else
1174#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1175#endif
1176
1177#if defined(JSON_HEDLEY_STATIC_CAST)
1178#undef JSON_HEDLEY_STATIC_CAST
1179#endif
1180#if defined(__cplusplus)
1181#define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1182#else
1183#define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1184#endif
1185
1186#if defined(JSON_HEDLEY_CPP_CAST)
1187#undef JSON_HEDLEY_CPP_CAST
1188#endif
1189#if defined(__cplusplus)
1190# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1191# define JSON_HEDLEY_CPP_CAST(T, expr) \
1192 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1193 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1194 ((T) (expr)) \
1195 JSON_HEDLEY_DIAGNOSTIC_POP
1196# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1197# define JSON_HEDLEY_CPP_CAST(T, expr) \
1198 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1199 _Pragma("diag_suppress=Pe137") \
1200 JSON_HEDLEY_DIAGNOSTIC_POP
1201# else
1202# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1203# endif
1204#else
1205# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1206#endif
1207
1208#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1209#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1210#endif
1211#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1212#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1213#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1214#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1215#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1216#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1217#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1218#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1219#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1220#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1221#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1222#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1223#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1224#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1225#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1226#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1227#elif \
1228 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1229 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1230 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1231 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1232 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1233 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1234 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1235 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1236 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1237 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1238 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1239#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1240#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1241#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1242#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1243#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1244#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1245#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1246#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1247#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1248#else
1249#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1250#endif
1251
1252#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1253#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1254#endif
1255#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1256#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1257#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1258#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1259#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1260#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1261#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1262#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1263#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1264#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1265#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1266#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1267#elif \
1268 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1269 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1270 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1271 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1272#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1273#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1274#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1275#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1276#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1277#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1278#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1279#else
1280#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1281#endif
1282
1283#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1284#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1285#endif
1286#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1287#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1288#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1289#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1290#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1291#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1292#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1293#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1294#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1295#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1296#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1297#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1298#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1299#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1300#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1301#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1302#elif \
1303 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1304 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1305 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1306#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1307#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1308#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1309#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1310#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1311#else
1312#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1313#endif
1314
1315#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1316#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1317#endif
1318#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1319#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1320#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1321#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1322#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1323#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1324#else
1325#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1326#endif
1327
1328#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1329#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1330#endif
1331#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1332#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1333#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1334#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1335#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1336#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1337#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1338#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1339#else
1340#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1341#endif
1342
1343#if defined(JSON_HEDLEY_DEPRECATED)
1344#undef JSON_HEDLEY_DEPRECATED
1345#endif
1346#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1347#undef JSON_HEDLEY_DEPRECATED_FOR
1348#endif
1349#if \
1350 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1351 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1352#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1353#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1354#elif \
1355 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1356 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1357 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1358 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1359 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1360 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1361 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1362 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1363 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1364 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1365 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1366 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1367#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1368#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1369#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1370#define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1371#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1372#elif \
1373 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1374 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1375 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1376 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1377 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1378 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1379 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1380 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1381 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1382 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1383 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1384 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1385 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1386 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1387 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1388 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1389#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1390#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1391#elif \
1392 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1393 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1394 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1395#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1396#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1397#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1398#define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1399#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1400#else
1401#define JSON_HEDLEY_DEPRECATED(since)
1402#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1403#endif
1404
1405#if defined(JSON_HEDLEY_UNAVAILABLE)
1406#undef JSON_HEDLEY_UNAVAILABLE
1407#endif
1408#if \
1409 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1410 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1411 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1412 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1413#define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1414#else
1415#define JSON_HEDLEY_UNAVAILABLE(available_since)
1416#endif
1417
1418#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1419#undef JSON_HEDLEY_WARN_UNUSED_RESULT
1420#endif
1421#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1422#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1423#endif
1424#if \
1425 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1426 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1427 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1428 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1429 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1430 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1431 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1432 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1433 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1434 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1435 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1436 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1437 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1438 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1439 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1440 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1441 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1442#define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1443#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1444#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1445#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1446#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1447#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1448#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1449#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1450#elif defined(_Check_return_) /* SAL */
1451#define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1452#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1453#else
1454#define JSON_HEDLEY_WARN_UNUSED_RESULT
1455#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1456#endif
1457
1458#if defined(JSON_HEDLEY_SENTINEL)
1459#undef JSON_HEDLEY_SENTINEL
1460#endif
1461#if \
1462 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1463 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1464 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1465 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1466 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1467#define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1468#else
1469#define JSON_HEDLEY_SENTINEL(position)
1470#endif
1471
1472#if defined(JSON_HEDLEY_NO_RETURN)
1473#undef JSON_HEDLEY_NO_RETURN
1474#endif
1475#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1476#define JSON_HEDLEY_NO_RETURN __noreturn
1477#elif \
1478 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1479 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1480#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1481#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1482#define JSON_HEDLEY_NO_RETURN _Noreturn
1483#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1484#define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1485#elif \
1486 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1487 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1488 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1489 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1490 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1491 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1492 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1493 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1494 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1495 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1496 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1497 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1498 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1499 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1500 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1501 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1502 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1503#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1504#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1505#define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1506#elif \
1507 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1508 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1509#define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1510#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1511#define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1512#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1513#define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1514#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1515#define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1516#else
1517#define JSON_HEDLEY_NO_RETURN
1518#endif
1519
1520#if defined(JSON_HEDLEY_NO_ESCAPE)
1521#undef JSON_HEDLEY_NO_ESCAPE
1522#endif
1523#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1524#define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1525#else
1526#define JSON_HEDLEY_NO_ESCAPE
1527#endif
1528
1529#if defined(JSON_HEDLEY_UNREACHABLE)
1530#undef JSON_HEDLEY_UNREACHABLE
1531#endif
1532#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1533#undef JSON_HEDLEY_UNREACHABLE_RETURN
1534#endif
1535#if defined(JSON_HEDLEY_ASSUME)
1536#undef JSON_HEDLEY_ASSUME
1537#endif
1538#if \
1539 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1540 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1541 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1542#define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1543#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1544#define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1545#elif \
1546 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1547 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1548#if defined(__cplusplus)
1549#define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1550#else
1551#define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1552#endif
1553#endif
1554#if \
1555 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1556 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1557 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1558 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1559 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1560 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1561 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1562#define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1563#elif defined(JSON_HEDLEY_ASSUME)
1564#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1565#endif
1566#if !defined(JSON_HEDLEY_ASSUME)
1567#if defined(JSON_HEDLEY_UNREACHABLE)
1568#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1569#else
1570#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1571#endif
1572#endif
1573#if defined(JSON_HEDLEY_UNREACHABLE)
1574#if \
1575 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1576 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1577#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1578#else
1579#define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1580#endif
1581#else
1582#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1583#endif
1584#if !defined(JSON_HEDLEY_UNREACHABLE)
1585#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1586#endif
1587
1588 JSON_HEDLEY_DIAGNOSTIC_PUSH
1589#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1590#pragma clang diagnostic ignored "-Wpedantic"
1591#endif
1592#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1593#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1594#endif
1595#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1596#if defined(__clang__)
1597#pragma clang diagnostic ignored "-Wvariadic-macros"
1598#elif defined(JSON_HEDLEY_GCC_VERSION)
1599#pragma GCC diagnostic ignored "-Wvariadic-macros"
1600#endif
1601#endif
1602#if defined(JSON_HEDLEY_NON_NULL)
1603#undef JSON_HEDLEY_NON_NULL
1604#endif
1605#if \
1606 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1607 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1608 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1609 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1610#define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1611#else
1612#define JSON_HEDLEY_NON_NULL(...)
1613#endif
1614 JSON_HEDLEY_DIAGNOSTIC_POP
1615
1616#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1617#undef JSON_HEDLEY_PRINTF_FORMAT
1618#endif
1619#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1620#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1621#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1622#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1623#elif \
1624 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1625 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1626 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1627 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1628 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1629 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1630 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1631 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1632 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1633 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1634 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1635 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1636 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1637 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1638 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1639 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1640 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1641#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1642#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1643#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1644#else
1645#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1646#endif
1647
1648#if defined(JSON_HEDLEY_CONSTEXPR)
1649#undef JSON_HEDLEY_CONSTEXPR
1650#endif
1651#if defined(__cplusplus)
1652#if __cplusplus >= 201103L
1653#define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1654#endif
1655#endif
1656#if !defined(JSON_HEDLEY_CONSTEXPR)
1657#define JSON_HEDLEY_CONSTEXPR
1658#endif
1659
1660#if defined(JSON_HEDLEY_PREDICT)
1661#undef JSON_HEDLEY_PREDICT
1662#endif
1663#if defined(JSON_HEDLEY_LIKELY)
1664#undef JSON_HEDLEY_LIKELY
1665#endif
1666#if defined(JSON_HEDLEY_UNLIKELY)
1667#undef JSON_HEDLEY_UNLIKELY
1668#endif
1669#if defined(JSON_HEDLEY_UNPREDICTABLE)
1670#undef JSON_HEDLEY_UNPREDICTABLE
1671#endif
1672#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1673#define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1674#endif
1675#if \
1676 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1677 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1678 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1679# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1680# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1681# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1682# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1683# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1684#elif \
1685 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1686 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1687 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1688 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1689 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1690 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1691 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1692 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1693 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1694 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1695 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1696 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1697 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1698 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1699 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1700 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1701# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1702 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1703# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1704 (__extension__ ({ \
1705 double hedley_probability_ = (probability); \
1706 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1707 }))
1708# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1709 (__extension__ ({ \
1710 double hedley_probability_ = (probability); \
1711 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1712 }))
1713# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1714# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1715#else
1716# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1717# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1718# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1719# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1720# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1721#endif
1722#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1723#define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1724#endif
1725
1726#if defined(JSON_HEDLEY_MALLOC)
1727#undef JSON_HEDLEY_MALLOC
1728#endif
1729#if \
1730 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1731 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1732 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1733 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1734 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1735 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1736 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1737 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1738 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1739 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1740 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1741 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1742 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1743 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1744 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1745 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1746 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1747 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1748#define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1749#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1750#define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1751#elif \
1752 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1753 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1754#define JSON_HEDLEY_MALLOC __declspec(restrict)
1755#else
1756#define JSON_HEDLEY_MALLOC
1757#endif
1758
1759#if defined(JSON_HEDLEY_PURE)
1760#undef JSON_HEDLEY_PURE
1761#endif
1762#if \
1763 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1764 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1765 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1766 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1767 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1768 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1769 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1770 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1771 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1772 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1773 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1774 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1775 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1776 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1777 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1778 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1779 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1780 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1781 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1782# define JSON_HEDLEY_PURE __attribute__((__pure__))
1783#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1784# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1785#elif defined(__cplusplus) && \
1786 ( \
1787 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1788 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1789 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1790 )
1791# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1792#else
1793# define JSON_HEDLEY_PURE
1794#endif
1795
1796#if defined(JSON_HEDLEY_CONST)
1797#undef JSON_HEDLEY_CONST
1798#endif
1799#if \
1800 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1801 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1802 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1803 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1804 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1805 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1806 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1807 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1808 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1809 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1810 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1811 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1812 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1813 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1814 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1815 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1816 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1817 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1818 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1819#define JSON_HEDLEY_CONST __attribute__((__const__))
1820#elif \
1821 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1822#define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1823#else
1824#define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1825#endif
1826
1827#if defined(JSON_HEDLEY_RESTRICT)
1828#undef JSON_HEDLEY_RESTRICT
1829#endif
1830#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1831#define JSON_HEDLEY_RESTRICT restrict
1832#elif \
1833 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1834 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1835 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1836 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1837 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1838 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1839 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1840 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1841 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1842 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1843 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1844 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1845 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1846 defined(__clang__) || \
1847 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1848#define JSON_HEDLEY_RESTRICT __restrict
1849#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1850#define JSON_HEDLEY_RESTRICT _Restrict
1851#else
1852#define JSON_HEDLEY_RESTRICT
1853#endif
1854
1855#if defined(JSON_HEDLEY_INLINE)
1856#undef JSON_HEDLEY_INLINE
1857#endif
1858#if \
1859 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1860 (defined(__cplusplus) && (__cplusplus >= 199711L))
1861#define JSON_HEDLEY_INLINE inline
1862#elif \
1863 defined(JSON_HEDLEY_GCC_VERSION) || \
1864 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1865#define JSON_HEDLEY_INLINE __inline__
1866#elif \
1867 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1868 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1869 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1870 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1871 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1872 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1873 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1874 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1875 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1876 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1877#define JSON_HEDLEY_INLINE __inline
1878#else
1879#define JSON_HEDLEY_INLINE
1880#endif
1881
1882#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1883#undef JSON_HEDLEY_ALWAYS_INLINE
1884#endif
1885#if \
1886 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1887 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1888 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1889 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1890 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1891 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1892 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1893 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1894 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1895 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1896 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1897 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1898 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1899 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1900 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1901 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1902 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1903 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1904 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1905# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1906#elif \
1907 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1908 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1909# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1910#elif defined(__cplusplus) && \
1911 ( \
1912 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1913 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1914 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1915 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1916 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1917 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1918 )
1919# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1920#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1921# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1922#else
1923# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1924#endif
1925
1926#if defined(JSON_HEDLEY_NEVER_INLINE)
1927#undef JSON_HEDLEY_NEVER_INLINE
1928#endif
1929#if \
1930 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1931 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1932 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1933 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1934 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1935 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1936 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1937 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1938 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1939 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1940 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1941 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1942 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1943 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1944 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1945 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1946 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1947 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1948 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1949#define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1950#elif \
1951 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1952 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1953#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1954#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1955#define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1956#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1957#define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1958#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1959#define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1960#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1961#define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1962#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1963#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1964#else
1965#define JSON_HEDLEY_NEVER_INLINE
1966#endif
1967
1968#if defined(JSON_HEDLEY_PRIVATE)
1969#undef JSON_HEDLEY_PRIVATE
1970#endif
1971#if defined(JSON_HEDLEY_PUBLIC)
1972#undef JSON_HEDLEY_PUBLIC
1973#endif
1974#if defined(JSON_HEDLEY_IMPORT)
1975#undef JSON_HEDLEY_IMPORT
1976#endif
1977#if defined(_WIN32) || defined(__CYGWIN__)
1978# define JSON_HEDLEY_PRIVATE
1979# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1980# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1981#else
1982# if \
1983 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1984 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1985 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1986 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1987 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1988 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1989 ( \
1990 defined(__TI_EABI__) && \
1991 ( \
1992 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1993 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1994 ) \
1995 ) || \
1996 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1997# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1998# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1999# else
2000# define JSON_HEDLEY_PRIVATE
2001# define JSON_HEDLEY_PUBLIC
2002# endif
2003# define JSON_HEDLEY_IMPORT extern
2004#endif
2005
2006#if defined(JSON_HEDLEY_NO_THROW)
2007#undef JSON_HEDLEY_NO_THROW
2008#endif
2009#if \
2010 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2011 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2012 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2013 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2014#define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2015#elif \
2016 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2017 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2018 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2019#define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2020#else
2021#define JSON_HEDLEY_NO_THROW
2022#endif
2023
2024#if defined(JSON_HEDLEY_FALL_THROUGH)
2025#undef JSON_HEDLEY_FALL_THROUGH
2026#endif
2027#if \
2028 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2029 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2030 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2031#define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2032#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2033#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2034#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2035#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2036#elif defined(__fallthrough) /* SAL */
2037#define JSON_HEDLEY_FALL_THROUGH __fallthrough
2038#else
2039#define JSON_HEDLEY_FALL_THROUGH
2040#endif
2041
2042#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2043#undef JSON_HEDLEY_RETURNS_NON_NULL
2044#endif
2045#if \
2046 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2047 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2048 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2049#define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2050#elif defined(_Ret_notnull_) /* SAL */
2051#define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2052#else
2053#define JSON_HEDLEY_RETURNS_NON_NULL
2054#endif
2055
2056#if defined(JSON_HEDLEY_ARRAY_PARAM)
2057#undef JSON_HEDLEY_ARRAY_PARAM
2058#endif
2059#if \
2060 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2061 !defined(__STDC_NO_VLA__) && \
2062 !defined(__cplusplus) && \
2063 !defined(JSON_HEDLEY_PGI_VERSION) && \
2064 !defined(JSON_HEDLEY_TINYC_VERSION)
2065#define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2066#else
2067#define JSON_HEDLEY_ARRAY_PARAM(name)
2068#endif
2069
2070#if defined(JSON_HEDLEY_IS_CONSTANT)
2071#undef JSON_HEDLEY_IS_CONSTANT
2072#endif
2073#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2074#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2075#endif
2076 /* JSON_HEDLEY_IS_CONSTEXPR_ is for
2077 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2078#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2079#undef JSON_HEDLEY_IS_CONSTEXPR_
2080#endif
2081#if \
2082 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2083 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2084 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2085 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2086 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2087 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2088 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2089 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2090 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2091 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2092#define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2093#endif
2094#if !defined(__cplusplus)
2095# if \
2096 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2097 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2098 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2099 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2100 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2101 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2102 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2103#if defined(__INTPTR_TYPE__)
2104#define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2105#else
2106#include <stdint.h>
2107#define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2108#endif
2109# elif \
2110 ( \
2111 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2112 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2113 !defined(JSON_HEDLEY_PGI_VERSION) && \
2114 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2115 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2116 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2117 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2118 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2119 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2120#if defined(__INTPTR_TYPE__)
2121#define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2122#else
2123#include <stdint.h>
2124#define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2125#endif
2126# elif \
2127 defined(JSON_HEDLEY_GCC_VERSION) || \
2128 defined(JSON_HEDLEY_INTEL_VERSION) || \
2129 defined(JSON_HEDLEY_TINYC_VERSION) || \
2130 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2131 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2132 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2133 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2134 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2135 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2136 defined(__clang__)
2137# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2138 sizeof(void) != \
2139 sizeof(*( \
2140 1 ? \
2141 ((void*) ((expr) * 0L) ) : \
2142((struct { char v[sizeof(void) * 2]; } *) 1) \
2143 ) \
2144 ) \
2145 )
2146# endif
2147#endif
2148#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2149#if !defined(JSON_HEDLEY_IS_CONSTANT)
2150#define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2151#endif
2152#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2153#else
2154#if !defined(JSON_HEDLEY_IS_CONSTANT)
2155#define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2156#endif
2157#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2158#endif
2159
2160#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2161#undef JSON_HEDLEY_BEGIN_C_DECLS
2162#endif
2163#if defined(JSON_HEDLEY_END_C_DECLS)
2164#undef JSON_HEDLEY_END_C_DECLS
2165#endif
2166#if defined(JSON_HEDLEY_C_DECL)
2167#undef JSON_HEDLEY_C_DECL
2168#endif
2169#if defined(__cplusplus)
2170#define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2171#define JSON_HEDLEY_END_C_DECLS }
2172#define JSON_HEDLEY_C_DECL extern "C"
2173#else
2174#define JSON_HEDLEY_BEGIN_C_DECLS
2175#define JSON_HEDLEY_END_C_DECLS
2176#define JSON_HEDLEY_C_DECL
2177#endif
2178
2179#if defined(JSON_HEDLEY_STATIC_ASSERT)
2180#undef JSON_HEDLEY_STATIC_ASSERT
2181#endif
2182#if \
2183 !defined(__cplusplus) && ( \
2184 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2185 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2186 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2187 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2188 defined(_Static_assert) \
2189 )
2190# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2191#elif \
2192 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2193 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2194 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2195# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2196#else
2197# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2198#endif
2199
2200#if defined(JSON_HEDLEY_NULL)
2201#undef JSON_HEDLEY_NULL
2202#endif
2203#if defined(__cplusplus)
2204#if __cplusplus >= 201103L
2205#define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2206#elif defined(NULL)
2207#define JSON_HEDLEY_NULL NULL
2208#else
2209#define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2210#endif
2211#elif defined(NULL)
2212#define JSON_HEDLEY_NULL NULL
2213#else
2214#define JSON_HEDLEY_NULL ((void*) 0)
2215#endif
2216
2217#if defined(JSON_HEDLEY_MESSAGE)
2218#undef JSON_HEDLEY_MESSAGE
2219#endif
2220#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2221# define JSON_HEDLEY_MESSAGE(msg) \
2222 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2223 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2224 JSON_HEDLEY_PRAGMA(message msg) \
2225 JSON_HEDLEY_DIAGNOSTIC_POP
2226#elif \
2227 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2228 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2229# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2230#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2231# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2232#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2233# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2234#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2235# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2236#else
2237# define JSON_HEDLEY_MESSAGE(msg)
2238#endif
2239
2240#if defined(JSON_HEDLEY_WARNING)
2241#undef JSON_HEDLEY_WARNING
2242#endif
2243#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2244# define JSON_HEDLEY_WARNING(msg) \
2245 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2246 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2247 JSON_HEDLEY_PRAGMA(clang warning msg) \
2248 JSON_HEDLEY_DIAGNOSTIC_POP
2249#elif \
2250 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2251 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2252 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2253# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2254#elif \
2255 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2256 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2257# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2258#else
2259# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2260#endif
2261
2262#if defined(JSON_HEDLEY_REQUIRE)
2263#undef JSON_HEDLEY_REQUIRE
2264#endif
2265#if defined(JSON_HEDLEY_REQUIRE_MSG)
2266#undef JSON_HEDLEY_REQUIRE_MSG
2267#endif
2268#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2269# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2270# define JSON_HEDLEY_REQUIRE(expr) \
2271 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2272 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2273 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2274 JSON_HEDLEY_DIAGNOSTIC_POP
2275# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2276 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2277 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2278 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2279 JSON_HEDLEY_DIAGNOSTIC_POP
2280# else
2281# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2282# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2283# endif
2284#else
2285# define JSON_HEDLEY_REQUIRE(expr)
2286# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2287#endif
2288
2289#if defined(JSON_HEDLEY_FLAGS)
2290#undef JSON_HEDLEY_FLAGS
2291#endif
2292#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2293#define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2294#else
2295#define JSON_HEDLEY_FLAGS
2296#endif
2297
2298#if defined(JSON_HEDLEY_FLAGS_CAST)
2299#undef JSON_HEDLEY_FLAGS_CAST
2300#endif
2301#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2302# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2303 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2304 _Pragma("warning(disable:188)") \
2305 ((T) (expr)); \
2306 JSON_HEDLEY_DIAGNOSTIC_POP \
2307 }))
2308#else
2309# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2310#endif
2311
2312#if defined(JSON_HEDLEY_EMPTY_BASES)
2313#undef JSON_HEDLEY_EMPTY_BASES
2314#endif
2315#if \
2316 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2317 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2318#define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2319#else
2320#define JSON_HEDLEY_EMPTY_BASES
2321#endif
2322
2323 /* Remaining macros are deprecated. */
2324
2325#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2326#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2327#endif
2328#if defined(__clang__)
2329#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2330#else
2331#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2332#endif
2333
2334#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2335#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2336#endif
2337#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2338
2339#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2340#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2341#endif
2342#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2343
2344#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2345#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2346#endif
2347#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2348
2349#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2350#undef JSON_HEDLEY_CLANG_HAS_FEATURE
2351#endif
2352#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2353
2354#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2355#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2356#endif
2357#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2358
2359#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2360#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2361#endif
2362#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2363
2364#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2365#undef JSON_HEDLEY_CLANG_HAS_WARNING
2366#endif
2367#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2368
2369#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2370
2371
2372// This file contains all internal macro definitions (except those affecting ABI)
2373// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2374
2375// #include <nlohmann/detail/abi_macros.hpp>
2376
2377
2378// exclude unsupported compilers
2379#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2380#if defined(__clang__)
2381#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2382#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2383#endif
2384#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2385#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2386#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2387#endif
2388#endif
2389#endif
2390
2391// C++ language standard detection
2392// if the user manually specified the used C++ version, this is skipped
2393#if !defined(JSON_HAS_CPP_26) && !defined(JSON_HAS_CPP_23) && !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2394#if (defined(__cplusplus) && __cplusplus > 202302L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202302L)
2395#define JSON_HAS_CPP_26
2396#define JSON_HAS_CPP_23
2397#define JSON_HAS_CPP_20
2398#define JSON_HAS_CPP_17
2399#define JSON_HAS_CPP_14
2400#elif (defined(__cplusplus) && __cplusplus > 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L)
2401#define JSON_HAS_CPP_23
2402#define JSON_HAS_CPP_20
2403#define JSON_HAS_CPP_17
2404#define JSON_HAS_CPP_14
2405#elif (defined(__cplusplus) && __cplusplus > 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L)
2406#define JSON_HAS_CPP_20
2407#define JSON_HAS_CPP_17
2408#define JSON_HAS_CPP_14
2409#elif (defined(__cplusplus) && __cplusplus > 201402L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2410#define JSON_HAS_CPP_17
2411#define JSON_HAS_CPP_14
2412#elif (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2413#define JSON_HAS_CPP_14
2414#endif
2415// the cpp 11 flag is always specified because it is the minimal required version
2416#define JSON_HAS_CPP_11
2417#endif
2418
2419#ifdef __has_include
2420#if __has_include(<version>)
2421#include <version>
2422#endif
2423#endif
2424
2425#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2426#ifdef JSON_HAS_CPP_17
2427#if defined(__cpp_lib_filesystem)
2428#define JSON_HAS_FILESYSTEM 1
2429#elif defined(__cpp_lib_experimental_filesystem)
2430#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2431#elif !defined(__has_include)
2432#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2433#elif __has_include(<filesystem>)
2434#define JSON_HAS_FILESYSTEM 1
2435#elif __has_include(<experimental/filesystem>)
2436#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2437#endif
2438
2439// std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2440#if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2441#undef JSON_HAS_FILESYSTEM
2442#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2443#endif
2444
2445// no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2446#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2447#undef JSON_HAS_FILESYSTEM
2448#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2449#endif
2450
2451// no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2452#if defined(__clang_major__) && __clang_major__ < 7
2453#undef JSON_HAS_FILESYSTEM
2454#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2455#endif
2456
2457// no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2458#if defined(_MSC_VER) && _MSC_VER < 1914
2459#undef JSON_HAS_FILESYSTEM
2460#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2461#endif
2462
2463// no filesystem support before iOS 13
2464#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2465#undef JSON_HAS_FILESYSTEM
2466#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2467#endif
2468
2469// no filesystem support before macOS Catalina
2470#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2471#undef JSON_HAS_FILESYSTEM
2472#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2473#endif
2474#endif
2475#endif
2476
2477#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2478#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2479#endif
2480
2481#ifndef JSON_HAS_FILESYSTEM
2482#define JSON_HAS_FILESYSTEM 0
2483#endif
2484
2485#ifndef JSON_HAS_THREE_WAY_COMPARISON
2486#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2487 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2488#define JSON_HAS_THREE_WAY_COMPARISON 1
2489#else
2490#define JSON_HAS_THREE_WAY_COMPARISON 0
2491#endif
2492#endif
2493
2494#ifndef JSON_HAS_RANGES
2495 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has a syntax error
2496#if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2497#define JSON_HAS_RANGES 0
2498#elif defined(__cpp_lib_ranges)
2499#define JSON_HAS_RANGES 1
2500#else
2501#define JSON_HAS_RANGES 0
2502#endif
2503#endif
2504
2505#ifndef JSON_HAS_STATIC_RTTI
2506#if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2507#define JSON_HAS_STATIC_RTTI 1
2508#else
2509#define JSON_HAS_STATIC_RTTI 0
2510#endif
2511#endif
2512
2513#ifdef JSON_HAS_CPP_17
2514#define JSON_INLINE_VARIABLE inline
2515#else
2516#define JSON_INLINE_VARIABLE
2517#endif
2518
2519#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2520#define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2521#else
2522#define JSON_NO_UNIQUE_ADDRESS
2523#endif
2524
2525// disable documentation warnings on clang
2526#if defined(__clang__)
2527#pragma clang diagnostic push
2528#pragma clang diagnostic ignored "-Wdocumentation"
2529#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2530#endif
2531
2532// allow disabling exceptions
2533#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2534#define JSON_THROW(exception) throw exception
2535#define JSON_TRY try
2536#define JSON_CATCH(exception) catch(exception)
2537#define JSON_INTERNAL_CATCH(exception) catch(exception)
2538#else
2539#include <cstdlib>
2540#define JSON_THROW(exception) std::abort()
2541#define JSON_TRY if(true)
2542#define JSON_CATCH(exception) if(false)
2543#define JSON_INTERNAL_CATCH(exception) if(false)
2544#endif
2545
2546// override exception macros
2547#if defined(JSON_THROW_USER)
2548#undef JSON_THROW
2549#define JSON_THROW JSON_THROW_USER
2550#endif
2551#if defined(JSON_TRY_USER)
2552#undef JSON_TRY
2553#define JSON_TRY JSON_TRY_USER
2554#endif
2555#if defined(JSON_CATCH_USER)
2556#undef JSON_CATCH
2557#define JSON_CATCH JSON_CATCH_USER
2558#undef JSON_INTERNAL_CATCH
2559#define JSON_INTERNAL_CATCH JSON_CATCH_USER
2560#endif
2561#if defined(JSON_INTERNAL_CATCH_USER)
2562#undef JSON_INTERNAL_CATCH
2563#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2564#endif
2565
2566// allow overriding assert
2567#if !defined(JSON_ASSERT)
2568#include <cassert> // assert
2569#define JSON_ASSERT(x) assert(x)
2570#endif
2571
2572// allow accessing some private functions (needed by the test suite)
2573#if defined(JSON_TESTS_PRIVATE)
2574#define JSON_PRIVATE_UNLESS_TESTED public
2575#else
2576#define JSON_PRIVATE_UNLESS_TESTED private
2577#endif
2578
2584#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2585 template<typename BasicJsonType> \
2586 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2587 { \
2588 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2589 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2590 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2591 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2592 auto it = std::find_if(std::begin(m), std::end(m), \
2593 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2594 { \
2595 return ej_pair.first == e; \
2596 }); \
2597 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2598 } \
2599 template<typename BasicJsonType> \
2600 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2601 { \
2602 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2603 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2604 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2605 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2606 auto it = std::find_if(std::begin(m), std::end(m), \
2607 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2608 { \
2609 return ej_pair.second == j; \
2610 }); \
2611 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2612 }
2613
2614// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2615// may be removed in the future once the class is split.
2616
2617#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2618 template<template<typename, typename, typename...> class ObjectType, \
2619 template<typename, typename...> class ArrayType, \
2620 class StringType, class BooleanType, class NumberIntegerType, \
2621 class NumberUnsignedType, class NumberFloatType, \
2622 template<typename> class AllocatorType, \
2623 template<typename, typename = void> class JSONSerializer, \
2624 class BinaryType, \
2625 class CustomBaseClass>
2626
2627#define NLOHMANN_BASIC_JSON_TPL \
2628 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2629 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2630 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2631
2632// Macros to simplify conversion from/to types
2633
2634#define NLOHMANN_JSON_EXPAND( x ) x
2635#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
2636#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2637 NLOHMANN_JSON_PASTE64, \
2638 NLOHMANN_JSON_PASTE63, \
2639 NLOHMANN_JSON_PASTE62, \
2640 NLOHMANN_JSON_PASTE61, \
2641 NLOHMANN_JSON_PASTE60, \
2642 NLOHMANN_JSON_PASTE59, \
2643 NLOHMANN_JSON_PASTE58, \
2644 NLOHMANN_JSON_PASTE57, \
2645 NLOHMANN_JSON_PASTE56, \
2646 NLOHMANN_JSON_PASTE55, \
2647 NLOHMANN_JSON_PASTE54, \
2648 NLOHMANN_JSON_PASTE53, \
2649 NLOHMANN_JSON_PASTE52, \
2650 NLOHMANN_JSON_PASTE51, \
2651 NLOHMANN_JSON_PASTE50, \
2652 NLOHMANN_JSON_PASTE49, \
2653 NLOHMANN_JSON_PASTE48, \
2654 NLOHMANN_JSON_PASTE47, \
2655 NLOHMANN_JSON_PASTE46, \
2656 NLOHMANN_JSON_PASTE45, \
2657 NLOHMANN_JSON_PASTE44, \
2658 NLOHMANN_JSON_PASTE43, \
2659 NLOHMANN_JSON_PASTE42, \
2660 NLOHMANN_JSON_PASTE41, \
2661 NLOHMANN_JSON_PASTE40, \
2662 NLOHMANN_JSON_PASTE39, \
2663 NLOHMANN_JSON_PASTE38, \
2664 NLOHMANN_JSON_PASTE37, \
2665 NLOHMANN_JSON_PASTE36, \
2666 NLOHMANN_JSON_PASTE35, \
2667 NLOHMANN_JSON_PASTE34, \
2668 NLOHMANN_JSON_PASTE33, \
2669 NLOHMANN_JSON_PASTE32, \
2670 NLOHMANN_JSON_PASTE31, \
2671 NLOHMANN_JSON_PASTE30, \
2672 NLOHMANN_JSON_PASTE29, \
2673 NLOHMANN_JSON_PASTE28, \
2674 NLOHMANN_JSON_PASTE27, \
2675 NLOHMANN_JSON_PASTE26, \
2676 NLOHMANN_JSON_PASTE25, \
2677 NLOHMANN_JSON_PASTE24, \
2678 NLOHMANN_JSON_PASTE23, \
2679 NLOHMANN_JSON_PASTE22, \
2680 NLOHMANN_JSON_PASTE21, \
2681 NLOHMANN_JSON_PASTE20, \
2682 NLOHMANN_JSON_PASTE19, \
2683 NLOHMANN_JSON_PASTE18, \
2684 NLOHMANN_JSON_PASTE17, \
2685 NLOHMANN_JSON_PASTE16, \
2686 NLOHMANN_JSON_PASTE15, \
2687 NLOHMANN_JSON_PASTE14, \
2688 NLOHMANN_JSON_PASTE13, \
2689 NLOHMANN_JSON_PASTE12, \
2690 NLOHMANN_JSON_PASTE11, \
2691 NLOHMANN_JSON_PASTE10, \
2692 NLOHMANN_JSON_PASTE9, \
2693 NLOHMANN_JSON_PASTE8, \
2694 NLOHMANN_JSON_PASTE7, \
2695 NLOHMANN_JSON_PASTE6, \
2696 NLOHMANN_JSON_PASTE5, \
2697 NLOHMANN_JSON_PASTE4, \
2698 NLOHMANN_JSON_PASTE3, \
2699 NLOHMANN_JSON_PASTE2, \
2700 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2701#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2702#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2703#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2704#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2705#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2706#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)
2707#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)
2708#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)
2709#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)
2710#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)
2711#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)
2712#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)
2713#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)
2714#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)
2715#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)
2716#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)
2717#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)
2718#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)
2719#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)
2720#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)
2721#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)
2722#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)
2723#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)
2724#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)
2725#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)
2726#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)
2727#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)
2728#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)
2729#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)
2730#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)
2731#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)
2732#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)
2733#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)
2734#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)
2735#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)
2736#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)
2737#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)
2738#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)
2739#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)
2740#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)
2741#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)
2742#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)
2743#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)
2744#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)
2745#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)
2746#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)
2747#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)
2748#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)
2749#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)
2750#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)
2751#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)
2752#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)
2753#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)
2754#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)
2755#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)
2756#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)
2757#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)
2758#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)
2759#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)
2760#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)
2761#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)
2762#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)
2763#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)
2764
2765#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2766#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2767#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;
2768
2775#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2776 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2777 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2778 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2779 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2780
2787#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2788 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2789 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2790 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2791 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__)) }
2792
2799#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2800 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2801 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2802
2809#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2810 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2811 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2812 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2813 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2814
2821#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2822 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2823 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2824 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2825 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__)) }
2826
2833#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2834 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2835 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2836
2843#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \
2844 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2845 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__)) } \
2846 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2847 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__)) }
2848
2855#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2856 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2857 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__)) } \
2858 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2859 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__)) }
2860
2867#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2868 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2869 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__)) }
2870
2877#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \
2878 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2879 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2880 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2881 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__)) }
2882
2889#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2890 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2891 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__)) } \
2892 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2893 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__)) }
2894
2901#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2902 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2903 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__)) }
2904
2905// inspired from https://stackoverflow.com/a/26745591
2906// allows calling any std function as if (e.g., with begin):
2907// using std::begin; begin(x);
2908//
2909// it allows using the detected idiom to retrieve the return type
2910// of such an expression
2911#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2912 namespace detail { \
2913 using std::std_name; \
2914 \
2915 template<typename... T> \
2916 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2917 } \
2918 \
2919 namespace detail2 { \
2920 struct std_name##_tag \
2921 { \
2922 }; \
2923 \
2924 template<typename... T> \
2925 std_name##_tag std_name(T&&...); \
2926 \
2927 template<typename... T> \
2928 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2929 \
2930 template<typename... T> \
2931 struct would_call_std_##std_name \
2932 { \
2933 static constexpr auto const value = ::nlohmann::detail:: \
2934 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2935 }; \
2936 } /* namespace detail2 */ \
2937 \
2938 template<typename... T> \
2939 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2940 { \
2941 }
2942
2943#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2944#define JSON_USE_IMPLICIT_CONVERSIONS 1
2945#endif
2946
2947#if JSON_USE_IMPLICIT_CONVERSIONS
2948#define JSON_EXPLICIT
2949#else
2950#define JSON_EXPLICIT explicit
2951#endif
2952
2953#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2954#define JSON_DISABLE_ENUM_SERIALIZATION 0
2955#endif
2956
2957#ifndef JSON_USE_GLOBAL_UDLS
2958#define JSON_USE_GLOBAL_UDLS 1
2959#endif
2960
2961#if JSON_HAS_THREE_WAY_COMPARISON
2962#include <compare> // partial_ordering
2963#endif
2964
2965NLOHMANN_JSON_NAMESPACE_BEGIN
2966namespace detail {
2967
2969 // JSON type enumeration //
2971
3008
3022#if JSON_HAS_THREE_WAY_COMPARISON
3023 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
3024#else
3025 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3026#endif
3027 {
3028 static constexpr std::array<std::uint8_t, 9> order = { {
3029 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
3030 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
3031 6 /* binary */
3032 }
3033 };
3034
3035 const auto l_index = static_cast<std::size_t>(lhs);
3036 const auto r_index = static_cast<std::size_t>(rhs);
3037#if JSON_HAS_THREE_WAY_COMPARISON
3038 if (l_index < order.size() && r_index < order.size()) {
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__)
3052 inline bool operator<(const value_t lhs, const value_t rhs) noexcept {
3053 return std::is_lt(lhs <=> rhs); // *NOPAD*
3054 }
3055#endif
3056
3057} // namespace detail
3058NLOHMANN_JSON_NAMESPACE_END
3059
3060// #include <nlohmann/detail/string_escape.hpp>
3061// __ _____ _____ _____
3062// __| | __| | | | JSON for Modern C++
3063// | | |__ | | | | | | version 3.12.0
3064// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3065//
3066// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
3067// SPDX-License-Identifier: MIT
3068
3069
3070
3071// #include <nlohmann/detail/abi_macros.hpp>
3072
3073
3074NLOHMANN_JSON_NAMESPACE_BEGIN
3075namespace detail {
3076
3090 template<typename StringType>
3091 inline void replace_substring(StringType& s, const StringType& f,
3092 const StringType& t) {
3093 JSON_ASSERT(!f.empty());
3094 for (auto pos = s.find(f); // find the first occurrence of f
3095 pos != StringType::npos; // make sure f was found
3096 s.replace(pos, f.size(), t), // replace with t, and
3097 pos = s.find(f, pos + t.size())) // find the next occurrence of f
3098 {
3099 }
3100 }
3101
3109 template<typename StringType>
3110 inline StringType escape(StringType s) {
3111 replace_substring(s, StringType{ "~" }, StringType{ "~0" });
3112 replace_substring(s, StringType{ "/" }, StringType{ "~1" });
3113 return s;
3114 }
3115
3123 template<typename StringType>
3124 inline void unescape(StringType& s) {
3125 replace_substring(s, StringType{ "~1" }, StringType{ "/" });
3126 replace_substring(s, StringType{ "~0" }, StringType{ "~" });
3127 }
3128
3129} // namespace detail
3130NLOHMANN_JSON_NAMESPACE_END
3131
3132// #include <nlohmann/detail/input/position_t.hpp>
3133// __ _____ _____ _____
3134// __| | __| | | | JSON for Modern C++
3135// | | |__ | | | | | | version 3.12.0
3136// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3137//
3138// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
3139// SPDX-License-Identifier: MIT
3140
3141
3142
3143#include <cstddef> // size_t
3144
3145// #include <nlohmann/detail/abi_macros.hpp>
3146
3147
3148NLOHMANN_JSON_NAMESPACE_BEGIN
3149namespace detail {
3150
3152 struct position_t {
3154 std::size_t chars_read_total = 0;
3158 std::size_t lines_read = 0;
3159
3161 constexpr operator size_t() const {
3162 return chars_read_total;
3163 }
3164 };
3165
3166} // namespace detail
3167NLOHMANN_JSON_NAMESPACE_END
3168
3169// #include <nlohmann/detail/macro_scope.hpp>
3170
3171// #include <nlohmann/detail/meta/cpp_future.hpp>
3172// __ _____ _____ _____
3173// __| | __| | | | JSON for Modern C++
3174// | | |__ | | | | | | version 3.12.0
3175// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3176//
3177// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
3178// SPDX-FileCopyrightText: 2018 The Abseil Authors
3179// SPDX-License-Identifier: MIT
3180
3181
3182
3183#include <array> // array
3184#include <cstddef> // size_t
3185#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3186#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3187
3188// #include <nlohmann/detail/macro_scope.hpp>
3189
3190
3191NLOHMANN_JSON_NAMESPACE_BEGIN
3192namespace detail {
3193
3194 template<typename T>
3195 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3196
3197#ifdef JSON_HAS_CPP_14
3198
3199 // the following utilities are natively available in C++14
3200 using std::enable_if_t;
3201 using std::index_sequence;
3202 using std::make_index_sequence;
3203 using std::index_sequence_for;
3204
3205#else
3206
3207 // alias templates to reduce boilerplate
3208 template<bool B, typename T = void>
3209 using enable_if_t = typename std::enable_if<B, T>::type;
3210
3211 // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3212 // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3213
3215
3216 // integer_sequence
3217 //
3218 // Class template representing a compile-time integer sequence. An instantiation
3219 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3220 // type through its template arguments (which is a common need when
3221 // working with C++11 variadic templates). `absl::integer_sequence` is designed
3222 // to be a drop-in replacement for C++14's `std::integer_sequence`.
3223 //
3224 // Example:
3225 //
3226 // template< class T, T... Ints >
3227 // void user_function(integer_sequence<T, Ints...>);
3228 //
3229 // int main()
3230 // {
3231 // // user_function's `T` will be deduced to `int` and `Ints...`
3232 // // will be deduced to `0, 1, 2, 3, 4`.
3233 // user_function(make_integer_sequence<int, 5>());
3234 // }
3235 template <typename T, T... Ints>
3237 using value_type = T;
3238 static constexpr std::size_t size() noexcept {
3239 return sizeof...(Ints);
3240 }
3241 };
3242
3243 // index_sequence
3244 //
3245 // A helper template for an `integer_sequence` of `size_t`,
3246 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3247 // `std::index_sequence`.
3248 template <size_t... Ints>
3249 using index_sequence = integer_sequence<size_t, Ints...>;
3250
3251 namespace utility_internal {
3252
3253 template <typename Seq, size_t SeqSize, size_t Rem>
3254 struct Extend;
3255
3256 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3257 template <typename T, T... Ints, size_t SeqSize>
3258 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0> {
3259 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3260 };
3261
3262 template <typename T, T... Ints, size_t SeqSize>
3263 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1> {
3264 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3265 };
3266
3267 // Recursion helper for 'make_integer_sequence<T, N>'.
3268 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3269 template <typename T, size_t N>
3270 struct Gen {
3271 using type =
3272 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3273 };
3274
3275 template <typename T>
3276 struct Gen<T, 0> {
3277 using type = integer_sequence<T>;
3278 };
3279
3280 } // namespace utility_internal
3281
3282 // Compile-time sequences of integers
3283
3284 // make_integer_sequence
3285 //
3286 // This template alias is equivalent to
3287 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3288 // replacement for C++14's `std::make_integer_sequence`.
3289 template <typename T, T N>
3290 using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3291
3292 // make_index_sequence
3293 //
3294 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3295 // and is designed to be a drop-in replacement for C++14's
3296 // `std::make_index_sequence`.
3297 template <size_t N>
3298 using make_index_sequence = make_integer_sequence<size_t, N>;
3299
3300 // index_sequence_for
3301 //
3302 // Converts a typename pack into an index sequence of the same length, and
3303 // is designed to be a drop-in replacement for C++14's
3304 // `std::index_sequence_for()`
3305 template <typename... Ts>
3306 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3307
3309
3310#endif
3311
3312// dispatch utility (taken from ranges-v3)
3313 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3314 template<> struct priority_tag<0> {};
3315
3316 // taken from ranges-v3
3317 template<typename T>
3319 static JSON_INLINE_VARIABLE constexpr T value{};
3320 };
3321
3322#ifndef JSON_HAS_CPP_17
3323 template<typename T>
3324 constexpr T static_const<T>::value;
3325#endif
3326
3327 template<typename T, typename... Args>
3328 constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args) {
3329 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3330 }
3331
3332} // namespace detail
3333NLOHMANN_JSON_NAMESPACE_END
3334
3335// #include <nlohmann/detail/meta/type_traits.hpp>
3336// __ _____ _____ _____
3337// __| | __| | | | JSON for Modern C++
3338// | | |__ | | | | | | version 3.12.0
3339// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3340//
3341// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
3342// SPDX-License-Identifier: MIT
3343
3344
3345
3346#include <limits> // numeric_limits
3347#include <string> // char_traits
3348#include <tuple> // tuple
3349#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3350#include <utility> // declval
3351#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3352#include <cstddef> // byte
3353#endif
3354// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3355// __ _____ _____ _____
3356// __| | __| | | | JSON for Modern C++
3357// | | |__ | | | | | | version 3.12.0
3358// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3359//
3360// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
3361// SPDX-License-Identifier: MIT
3362
3363
3364
3365#include <iterator> // random_access_iterator_tag
3366
3367// #include <nlohmann/detail/abi_macros.hpp>
3368
3369// #include <nlohmann/detail/meta/void_t.hpp>
3370
3371// #include <nlohmann/detail/meta/cpp_future.hpp>
3372
3373
3374NLOHMANN_JSON_NAMESPACE_BEGIN
3375namespace detail {
3376
3377 template<typename It, typename = void>
3379
3380 template<typename It>
3382 It,
3383 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3384 typename It::reference, typename It::iterator_category >>
3385 {
3386 using difference_type = typename It::difference_type;
3387 using value_type = typename It::value_type;
3388 using pointer = typename It::pointer;
3389 using reference = typename It::reference;
3390 using iterator_category = typename It::iterator_category;
3391 };
3392
3393 // This is required as some compilers implement std::iterator_traits in a way that
3394 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3395 template<typename T, typename = void>
3397
3398 template<typename T>
3399 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3400 : iterator_types<T> {};
3401
3402 template<typename T>
3403 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>> {
3404 using iterator_category = std::random_access_iterator_tag;
3405 using value_type = T;
3406 using difference_type = ptrdiff_t;
3407 using pointer = T*;
3408 using reference = T&;
3409 };
3410
3411} // namespace detail
3412NLOHMANN_JSON_NAMESPACE_END
3413
3414// #include <nlohmann/detail/macro_scope.hpp>
3415
3416// #include <nlohmann/detail/meta/call_std/begin.hpp>
3417// __ _____ _____ _____
3418// __| | __| | | | JSON for Modern C++
3419// | | |__ | | | | | | version 3.12.0
3420// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3421//
3422// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
3423// SPDX-License-Identifier: MIT
3424
3425
3426
3427// #include <nlohmann/detail/macro_scope.hpp>
3428
3429
3430NLOHMANN_JSON_NAMESPACE_BEGIN
3431
3432NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3433
3434NLOHMANN_JSON_NAMESPACE_END
3435
3436// #include <nlohmann/detail/meta/call_std/end.hpp>
3437// __ _____ _____ _____
3438// __| | __| | | | JSON for Modern C++
3439// | | |__ | | | | | | version 3.12.0
3440// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3441//
3442// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
3443// SPDX-License-Identifier: MIT
3444
3445
3446
3447// #include <nlohmann/detail/macro_scope.hpp>
3448
3449
3450NLOHMANN_JSON_NAMESPACE_BEGIN
3451
3452NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3453
3454NLOHMANN_JSON_NAMESPACE_END
3455
3456// #include <nlohmann/detail/meta/cpp_future.hpp>
3457
3458// #include <nlohmann/detail/meta/detected.hpp>
3459
3460// #include <nlohmann/json_fwd.hpp>
3461// __ _____ _____ _____
3462// __| | __| | | | JSON for Modern C++
3463// | | |__ | | | | | | version 3.12.0
3464// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3465//
3466// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
3467// SPDX-License-Identifier: MIT
3468
3469#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3470#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3471
3472#include <cstdint> // int64_t, uint64_t
3473#include <map> // map
3474#include <memory> // allocator
3475#include <string> // string
3476#include <vector> // vector
3477
3478// #include <nlohmann/detail/abi_macros.hpp>
3479
3480
3486NLOHMANN_JSON_NAMESPACE_BEGIN
3487
3495template<typename T = void, typename SFINAE = void>
3496struct adl_serializer;
3497
3500template<template<typename U, typename V, typename... Args> class ObjectType =
3501 std::map,
3502 template<typename U, typename... Args> class ArrayType = std::vector,
3503 class StringType = std::string, class BooleanType = bool,
3504 class NumberIntegerType = std::int64_t,
3505 class NumberUnsignedType = std::uint64_t,
3506 class NumberFloatType = double,
3507 template<typename U> class AllocatorType = std::allocator,
3508 template<typename T, typename SFINAE = void> class JSONSerializer =
3510 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3511 class CustomBaseClass = void>
3512class basic_json;
3513
3516template<typename RefStringType>
3518
3523using json = basic_json<>;
3524
3527template<class Key, class T, class IgnoredLess, class Allocator>
3529
3532using ordered_json = basic_json<nlohmann::ordered_map>;
3533
3534NLOHMANN_JSON_NAMESPACE_END
3535
3536#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3537
3538
3539NLOHMANN_JSON_NAMESPACE_BEGIN
3548namespace detail {
3549
3551 // helpers //
3553
3554 // Note to maintainers:
3555 //
3556 // Every trait in this file expects a non-CV-qualified type.
3557 // The only exceptions are in the 'aliases for detected' section
3558 // (i.e., those of the form: decltype(T::member_function(std::declval<T>())))
3559 //
3560 // In this case, T has to be properly CV-qualified to constraint the function arguments
3561 // (e.g., to_json(BasicJsonType&, const T&))
3562
3563 template<typename> struct is_basic_json : std::false_type {};
3564
3565 NLOHMANN_BASIC_JSON_TPL_DECLARATION
3566 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3567
3568 // used by exceptions create() member functions
3569 // true_type for the pointer to possibly cv-qualified basic_json or std::nullptr_t
3570 // false_type otherwise
3571 template<typename BasicJsonContext>
3573 std::integral_constant < bool,
3574 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3575 || std::is_same<BasicJsonContext, std::nullptr_t>::value > {};
3576
3578 // json_ref helpers //
3580
3581 template<typename>
3582 class json_ref;
3583
3584 template<typename>
3585 struct is_json_ref : std::false_type {};
3586
3587 template<typename T>
3588 struct is_json_ref<json_ref<T>> : std::true_type {};
3589
3591 // aliases for detected //
3593
3594 template<typename T>
3595 using mapped_type_t = typename T::mapped_type;
3596
3597 template<typename T>
3598 using key_type_t = typename T::key_type;
3599
3600 template<typename T>
3601 using value_type_t = typename T::value_type;
3602
3603 template<typename T>
3604 using difference_type_t = typename T::difference_type;
3605
3606 template<typename T>
3607 using pointer_t = typename T::pointer;
3608
3609 template<typename T>
3610 using reference_t = typename T::reference;
3611
3612 template<typename T>
3613 using iterator_category_t = typename T::iterator_category;
3614
3615 template<typename T, typename... Args>
3616 using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3617
3618 template<typename T, typename... Args>
3619 using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3620
3621 template<typename T, typename U>
3622 using get_template_function = decltype(std::declval<T>().template get<U>());
3623
3624 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3625 template<typename BasicJsonType, typename T, typename = void>
3626 struct has_from_json : std::false_type {};
3627
3628 // trait checking if j.get<T> is valid
3629 // use this trait instead of std::is_constructible or std::is_convertible,
3630 // both rely on, or make use of implicit conversions, and thus fail when T
3631 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3632 template <typename BasicJsonType, typename T>
3633 struct is_getable {
3634 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3635 };
3636
3637 template<typename BasicJsonType, typename T>
3638 struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> {
3639 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3640
3641 static constexpr bool value =
3642 is_detected_exact<void, from_json_function, serializer,
3643 const BasicJsonType&, T&>::value;
3644 };
3645
3646 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
3647 // this overload is used for non-default-constructible user-defined-types
3648 template<typename BasicJsonType, typename T, typename = void>
3649 struct has_non_default_from_json : std::false_type {};
3650
3651 template<typename BasicJsonType, typename T>
3652 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> {
3653 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3654
3655 static constexpr bool value =
3656 is_detected_exact<T, from_json_function, serializer,
3657 const BasicJsonType&>::value;
3658 };
3659
3660 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3661 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3662 template<typename BasicJsonType, typename T, typename = void>
3663 struct has_to_json : std::false_type {};
3664
3665 template<typename BasicJsonType, typename T>
3666 struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> {
3667 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3668
3669 static constexpr bool value =
3670 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3671 T>::value;
3672 };
3673
3674 template<typename T>
3675 using detect_key_compare = typename T::key_compare;
3676
3677 template<typename T>
3678 struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3679
3680 // obtains the actual object key comparator
3681 template<typename BasicJsonType>
3683 using object_t = typename BasicJsonType::object_t;
3684 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3685 using type = typename std::conditional < has_key_compare<object_t>::value,
3686 typename object_t::key_compare, object_comparator_t>::type;
3687 };
3688
3689 template<typename BasicJsonType>
3690 using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
3691
3693 // char_traits //
3695
3696 // Primary template of char_traits calls std char_traits
3697 template<typename T>
3698 struct char_traits : std::char_traits<T> {};
3699
3700 // Explicitly define char traits for unsigned char since it is not standard
3701 template<>
3702 struct char_traits<unsigned char> : std::char_traits<char> {
3703 using char_type = unsigned char;
3704 using int_type = uint64_t;
3705
3706 // Redefine to_int_type function
3707 static int_type to_int_type(char_type c) noexcept {
3708 return static_cast<int_type>(c);
3709 }
3710
3711 static char_type to_char_type(int_type i) noexcept {
3712 return static_cast<char_type>(i);
3713 }
3714
3715 static constexpr int_type eof() noexcept {
3716 return static_cast<int_type>(std::char_traits<char>::eof());
3717 }
3718 };
3719
3720 // Explicitly define char traits for signed char since it is not standard
3721 template<>
3722 struct char_traits<signed char> : std::char_traits<char> {
3723 using char_type = signed char;
3724 using int_type = uint64_t;
3725
3726 // Redefine to_int_type function
3727 static int_type to_int_type(char_type c) noexcept {
3728 return static_cast<int_type>(c);
3729 }
3730
3731 static char_type to_char_type(int_type i) noexcept {
3732 return static_cast<char_type>(i);
3733 }
3734
3735 static constexpr int_type eof() noexcept {
3736 return static_cast<int_type>(std::char_traits<char>::eof());
3737 }
3738 };
3739
3740#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3741 template<>
3742 struct char_traits<std::byte> : std::char_traits<char> {
3743 using char_type = std::byte;
3744 using int_type = uint64_t;
3745
3746 static int_type to_int_type(char_type c) noexcept {
3747 return static_cast<int_type>(std::to_integer<unsigned char>(c));
3748 }
3749
3750 static char_type to_char_type(int_type i) noexcept {
3751 return std::byte(static_cast<unsigned char>(i));
3752 }
3753
3754 static constexpr int_type eof() noexcept {
3755 return static_cast<int_type>(std::char_traits<char>::eof());
3756 }
3757 };
3758#endif
3759
3761 // is_ functions //
3763
3764 // https://en.cppreference.com/w/cpp/types/conjunction
3765 template<class...> struct conjunction : std::true_type {};
3766 template<class B> struct conjunction<B> : B {};
3767 template<class B, class... Bn>
3768 struct conjunction<B, Bn...>
3769 : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3770
3771 // https://en.cppreference.com/w/cpp/types/negation
3772 template<class B> struct negation : std::integral_constant < bool, !B::value > {};
3773
3774 // Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3775 // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3776 // This causes compile errors in e.g., Clang 3.5 or GCC 4.9.
3777 template <typename T>
3778 struct is_default_constructible : std::is_default_constructible<T> {};
3779
3780 template <typename T1, typename T2>
3781 struct is_default_constructible<std::pair<T1, T2>>
3782 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3783
3784 template <typename T1, typename T2>
3785 struct is_default_constructible<const std::pair<T1, T2>>
3786 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3787
3788 template <typename... Ts>
3789 struct is_default_constructible<std::tuple<Ts...>>
3790 : conjunction<is_default_constructible<Ts>...> {};
3791
3792 template <typename... Ts>
3793 struct is_default_constructible<const std::tuple<Ts...>>
3794 : conjunction<is_default_constructible<Ts>...> {};
3795
3796 template <typename T, typename... Args>
3797 struct is_constructible : std::is_constructible<T, Args...> {};
3798
3799 template <typename T1, typename T2>
3800 struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3801
3802 template <typename T1, typename T2>
3803 struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3804
3805 template <typename... Ts>
3806 struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3807
3808 template <typename... Ts>
3809 struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3810
3811 template<typename T, typename = void>
3812 struct is_iterator_traits : std::false_type {};
3813
3814 template<typename T>
3816 private:
3817 using traits = iterator_traits<T>;
3818
3819 public:
3820 static constexpr auto value =
3821 is_detected<value_type_t, traits>::value&&
3822 is_detected<difference_type_t, traits>::value&&
3823 is_detected<pointer_t, traits>::value&&
3824 is_detected<iterator_category_t, traits>::value&&
3825 is_detected<reference_t, traits>::value;
3826 };
3827
3828 template<typename T>
3829 struct is_range {
3830 private:
3831 using t_ref = typename std::add_lvalue_reference<T>::type;
3832
3833 using iterator = detected_t<result_of_begin, t_ref>;
3834 using sentinel = detected_t<result_of_end, t_ref>;
3835
3836 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3837 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3838 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3839 static constexpr auto is_iterator_begin =
3841
3842 public:
3843 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value&& is_iterator_begin;
3844 };
3845
3846 template<typename R>
3847 using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3848
3849 template<typename T>
3850 using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3851
3852 // The following implementation of is_complete_type is taken from
3853 // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3854 // and is written by Xiang Fan who agreed to use it in this library.
3855
3856 template<typename T, typename = void>
3857 struct is_complete_type : std::false_type {};
3858
3859 template<typename T>
3860 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3861
3862 template<typename BasicJsonType, typename CompatibleObjectType,
3863 typename = void>
3864 struct is_compatible_object_type_impl : std::false_type {};
3865
3866 template<typename BasicJsonType, typename CompatibleObjectType>
3868 BasicJsonType, CompatibleObjectType,
3869 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3870 is_detected<key_type_t, CompatibleObjectType>::value >>
3871 {
3872 using object_t = typename BasicJsonType::object_t;
3873
3874 // macOS's is_constructible does not play well with nonesuch...
3875 static constexpr bool value =
3876 is_constructible<typename object_t::key_type,
3877 typename CompatibleObjectType::key_type>::value&&
3878 is_constructible<typename object_t::mapped_type,
3879 typename CompatibleObjectType::mapped_type>::value;
3880 };
3881
3882 template<typename BasicJsonType, typename CompatibleObjectType>
3884 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3885
3886 template<typename BasicJsonType, typename ConstructibleObjectType,
3887 typename = void>
3888 struct is_constructible_object_type_impl : std::false_type {};
3889
3890 template<typename BasicJsonType, typename ConstructibleObjectType>
3892 BasicJsonType, ConstructibleObjectType,
3893 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3894 is_detected<key_type_t, ConstructibleObjectType>::value >>
3895 {
3896 using object_t = typename BasicJsonType::object_t;
3897
3898 static constexpr bool value =
3900 (std::is_move_assignable<ConstructibleObjectType>::value ||
3901 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3902 (is_constructible<typename ConstructibleObjectType::key_type,
3903 typename object_t::key_type>::value &&
3904 std::is_same <
3905 typename object_t::mapped_type,
3906 typename ConstructibleObjectType::mapped_type >::value)) ||
3907 (has_from_json<BasicJsonType,
3908 typename ConstructibleObjectType::mapped_type>::value ||
3910 BasicJsonType,
3911 typename ConstructibleObjectType::mapped_type >::value);
3912 };
3913
3914 template<typename BasicJsonType, typename ConstructibleObjectType>
3916 : is_constructible_object_type_impl<BasicJsonType,
3917 ConstructibleObjectType> {};
3918
3919 template<typename BasicJsonType, typename CompatibleStringType>
3924
3925 template<typename BasicJsonType, typename ConstructibleStringType>
3927 // launder type through decltype() to fix compilation failure on ICPC
3928#ifdef __INTEL_COMPILER
3929 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3930#else
3931 using laundered_type = ConstructibleStringType;
3932#endif
3933
3934 static constexpr auto value =
3935 conjunction <
3937 is_detected_exact<typename BasicJsonType::string_t::value_type,
3938 value_type_t, laundered_type >>::value;
3939 };
3940
3941 template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3942 struct is_compatible_array_type_impl : std::false_type {};
3943
3944 template<typename BasicJsonType, typename CompatibleArrayType>
3946 BasicJsonType, CompatibleArrayType,
3947 enable_if_t <
3948 is_detected<iterator_t, CompatibleArrayType>::value&&
3949 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value &&
3950 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3951 // c.f. https://github.com/nlohmann/json/pull/3073
3952 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3953 {
3954 static constexpr bool value =
3955 is_constructible<BasicJsonType,
3956 range_value_t<CompatibleArrayType>>::value;
3957 };
3958
3959 template<typename BasicJsonType, typename CompatibleArrayType>
3961 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3962
3963 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3964 struct is_constructible_array_type_impl : std::false_type {};
3965
3966 template<typename BasicJsonType, typename ConstructibleArrayType>
3968 BasicJsonType, ConstructibleArrayType,
3969 enable_if_t<std::is_same<ConstructibleArrayType,
3970 typename BasicJsonType::value_type>::value >>
3971 : std::true_type {};
3972
3973 template<typename BasicJsonType, typename ConstructibleArrayType>
3975 BasicJsonType, ConstructibleArrayType,
3976 enable_if_t < !std::is_same<ConstructibleArrayType,
3977 typename BasicJsonType::value_type>::value &&
3978 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3979 is_default_constructible<ConstructibleArrayType>::value &&
3980 (std::is_move_assignable<ConstructibleArrayType>::value ||
3981 std::is_copy_assignable<ConstructibleArrayType>::value) &&
3982 is_detected<iterator_t, ConstructibleArrayType>::value&&
3983 is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3984 is_detected<range_value_t, ConstructibleArrayType>::value &&
3985 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3986 // c.f. https://github.com/nlohmann/json/pull/3073
3987 !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3989 detected_t<range_value_t, ConstructibleArrayType >>::value >>
3990 {
3991 using value_type = range_value_t<ConstructibleArrayType>;
3992
3993 static constexpr bool value =
3994 std::is_same<value_type,
3995 typename BasicJsonType::array_t::value_type>::value ||
3996 has_from_json<BasicJsonType,
3997 value_type>::value ||
3999 BasicJsonType,
4000 value_type >::value;
4001 };
4002
4003 template<typename BasicJsonType, typename ConstructibleArrayType>
4005 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
4006
4007 template<typename RealIntegerType, typename CompatibleNumberIntegerType,
4008 typename = void>
4009 struct is_compatible_integer_type_impl : std::false_type {};
4010
4011 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4013 RealIntegerType, CompatibleNumberIntegerType,
4014 enable_if_t < std::is_integral<RealIntegerType>::value&&
4015 std::is_integral<CompatibleNumberIntegerType>::value &&
4016 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
4017 {
4018 // is there an assert somewhere on overflows?
4019 using RealLimits = std::numeric_limits<RealIntegerType>;
4020 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
4021
4022 static constexpr auto value =
4023 is_constructible<RealIntegerType,
4024 CompatibleNumberIntegerType>::value&&
4025 CompatibleLimits::is_integer&&
4026 RealLimits::is_signed == CompatibleLimits::is_signed;
4027 };
4028
4029 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4031 : is_compatible_integer_type_impl<RealIntegerType,
4032 CompatibleNumberIntegerType> {};
4033
4034 template<typename BasicJsonType, typename CompatibleType, typename = void>
4035 struct is_compatible_type_impl : std::false_type {};
4036
4037 template<typename BasicJsonType, typename CompatibleType>
4039 BasicJsonType, CompatibleType,
4040 enable_if_t<is_complete_type<CompatibleType>::value >>
4041 {
4042 static constexpr bool value =
4044 };
4045
4046 template<typename BasicJsonType, typename CompatibleType>
4048 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
4049
4050 template<typename BasicJsonType, typename CompatibleReferenceType>
4052 using JsonType = uncvref_t<BasicJsonType>;
4053 using CVType = typename std::remove_reference<CompatibleReferenceType>::type;
4054 using Type = typename std::remove_cv<CVType>::type;
4055 constexpr static bool value = std::is_reference<CompatibleReferenceType>::value &&
4056 (!std::is_const<typename std::remove_reference<BasicJsonType>::type>::value || std::is_const<CVType>::value) &&
4057 (std::is_same<typename JsonType::boolean_t, Type>::value ||
4058 std::is_same<typename JsonType::number_float_t, Type>::value ||
4059 std::is_same<typename JsonType::number_integer_t, Type>::value ||
4060 std::is_same<typename JsonType::number_unsigned_t, Type>::value ||
4061 std::is_same<typename JsonType::string_t, Type>::value ||
4062 std::is_same<typename JsonType::binary_t, Type>::value ||
4063 std::is_same<typename JsonType::object_t, Type>::value ||
4064 std::is_same<typename JsonType::array_t, Type>::value);
4065 };
4066
4067 template<typename BasicJsonType, typename CompatibleReferenceType>
4069 : is_compatible_reference_type_impl<BasicJsonType, CompatibleReferenceType> {};
4070
4071 template<typename T1, typename T2>
4072 struct is_constructible_tuple : std::false_type {};
4073
4074 template<typename T1, typename... Args>
4075 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
4076
4077 template<typename BasicJsonType, typename T>
4078 struct is_json_iterator_of : std::false_type {};
4079
4080 template<typename BasicJsonType>
4081 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
4082
4083 template<typename BasicJsonType>
4084 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type {};
4085
4086 // checks if a given type T is a template specialization of Primary
4087 template<template <typename...> class Primary, typename T>
4088 struct is_specialization_of : std::false_type {};
4089
4090 template<template <typename...> class Primary, typename... Args>
4091 struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
4092
4093 template<typename T>
4095
4096 // checks if B is a json_pointer<A>
4097 template <typename A, typename B>
4098 struct is_json_pointer_of : std::false_type {};
4099
4100 template <typename A>
4101 struct is_json_pointer_of<A, ::nlohmann::json_pointer<A>> : std::true_type {};
4102
4103 template <typename A>
4104 struct is_json_pointer_of<A, ::nlohmann::json_pointer<A>&> : std::true_type {};
4105
4106 // checks if A and B are comparable using Compare functor
4107 template<typename Compare, typename A, typename B, typename = void>
4108 struct is_comparable : std::false_type {};
4109
4110 // We exclude json_pointer here, because the checks using Compare(A, B) will
4111 // use json_pointer::operator string_t() which triggers a deprecation warning
4112 // for GCC. See https://github.com/nlohmann/json/issues/4621. The call to
4113 // is_json_pointer_of can be removed once the deprecated function has been
4114 // removed.
4115 template<typename Compare, typename A, typename B>
4116 struct is_comparable < Compare, A, B, enable_if_t < !is_json_pointer_of<A, B>::value
4117 && std::is_constructible <decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>()))>::value
4118 && std::is_constructible <decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))>::value
4119 >> : std::true_type {};
4120
4121 template<typename T>
4122 using detect_is_transparent = typename T::is_transparent;
4123
4124 // type trait to check if KeyType can be used as an object key (without a BasicJsonType)
4125 // see is_usable_as_basic_json_key_type below
4126 template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4127 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4128 using is_usable_as_key_type = typename std::conditional <
4130 && !(ExcludeObjectKeyType&& std::is_same<KeyType,
4131 ObjectKeyType>::value)
4132 && (!RequireTransparentComparator
4133 || is_detected <detect_is_transparent, Comparator>::value)
4134 && !is_json_pointer<KeyType>::value,
4135 std::true_type,
4136 std::false_type >::type;
4137
4138 // type trait to check if KeyType can be used as an object key
4139 // true if:
4140 // - KeyType is comparable with BasicJsonType::object_t::key_type
4141 // - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4142 // - the comparator is transparent or RequireTransparentComparator is false
4143 // - KeyType is not a JSON iterator or json_pointer
4144 template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4145 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4146 using is_usable_as_basic_json_key_type = typename std::conditional <
4147 (is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4148 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4149 RequireTransparentComparator, ExcludeObjectKeyType>::value
4151#ifdef JSON_HAS_CPP_17
4152 || std::is_convertible<KeyType, std::string_view>::value
4153#endif
4154 , std::true_type,
4155 std::false_type >::type;
4156
4157 template<typename ObjectType, typename KeyType>
4158 using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4159
4160 // type trait to check if object_t has an erase() member functions accepting KeyType
4161 template<typename BasicJsonType, typename KeyType>
4162 using has_erase_with_key_type = typename std::conditional <
4163 is_detected <
4164 detect_erase_with_key_type,
4165 typename BasicJsonType::object_t, KeyType >::value,
4166 std::true_type,
4167 std::false_type >::type;
4168
4169 // a naive helper to check if a type is an ordered_map (exploits the fact that
4170 // ordered_map inherits capacity() from std::vector)
4171 template <typename T>
4173 using one = char;
4174
4175 struct two {
4176 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4177 };
4178
4179 template <typename C> static one test(decltype(&C::capacity));
4180 template <typename C> static two test(...);
4181
4182 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg,cppcoreguidelines-use-enum-class)
4183 };
4184
4185 // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4186 template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4187 T conditional_static_cast(U value) {
4188 return static_cast<T>(value);
4189 }
4190
4191 template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4192 T conditional_static_cast(U value) {
4193 return value;
4194 }
4195
4196 template<typename... Types>
4197 using all_integral = conjunction<std::is_integral<Types>...>;
4198
4199 template<typename... Types>
4200 using all_signed = conjunction<std::is_signed<Types>...>;
4201
4202 template<typename... Types>
4203 using all_unsigned = conjunction<std::is_unsigned<Types>...>;
4204
4205 // there's a disjunction trait in another PR; replace when merged
4206 template<typename... Types>
4207 using same_sign = std::integral_constant < bool,
4208 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4209
4210 template<typename OfType, typename T>
4211 using never_out_of_range = std::integral_constant < bool,
4212 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4213 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4214
4215 template<typename OfType, typename T,
4216 bool OfTypeSigned = std::is_signed<OfType>::value,
4217 bool TSigned = std::is_signed<T>::value>
4219
4220 template<typename OfType, typename T>
4221 struct value_in_range_of_impl2<OfType, T, false, false> {
4222 static constexpr bool test(T val) {
4223 using CommonType = typename std::common_type<OfType, T>::type;
4224 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4225 }
4226 };
4227
4228 template<typename OfType, typename T>
4229 struct value_in_range_of_impl2<OfType, T, true, false> {
4230 static constexpr bool test(T val) {
4231 using CommonType = typename std::common_type<OfType, T>::type;
4232 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4233 }
4234 };
4235
4236 template<typename OfType, typename T>
4237 struct value_in_range_of_impl2<OfType, T, false, true> {
4238 static constexpr bool test(T val) {
4239 using CommonType = typename std::common_type<OfType, T>::type;
4240 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4241 }
4242 };
4243
4244 template<typename OfType, typename T>
4245 struct value_in_range_of_impl2<OfType, T, true, true> {
4246 static constexpr bool test(T val) {
4247 using CommonType = typename std::common_type<OfType, T>::type;
4248 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4249 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4250 }
4251 };
4252
4253 template<typename OfType, typename T,
4254 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4255 typename = detail::enable_if_t<all_integral<OfType, T>::value>>
4257
4258 template<typename OfType, typename T>
4259 struct value_in_range_of_impl1<OfType, T, false> {
4260 static constexpr bool test(T val) {
4262 }
4263 };
4264
4265 template<typename OfType, typename T>
4266 struct value_in_range_of_impl1<OfType, T, true> {
4267 static constexpr bool test(T /*val*/) {
4268 return true;
4269 }
4270 };
4271
4272 template<typename OfType, typename T>
4273 constexpr bool value_in_range_of(T val) {
4275 }
4276
4277 template<bool Value>
4278 using bool_constant = std::integral_constant<bool, Value>;
4279
4281 // is_c_string
4283
4284 namespace impl {
4285
4286 template<typename T>
4287 constexpr bool is_c_string() {
4288 using TUnExt = typename std::remove_extent<T>::type;
4289 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4290 using TUnPtr = typename std::remove_pointer<T>::type;
4291 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4292 return
4293 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4294 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4295 }
4296
4297 } // namespace impl
4298
4299 // checks whether T is a [cv] char */[cv] char[] C string
4300 template<typename T>
4301 struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4302
4303 template<typename T>
4304 using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
4305
4307 // is_transparent
4309
4310 namespace impl {
4311
4312 template<typename T>
4313 constexpr bool is_transparent() {
4314 return is_detected<detect_is_transparent, T>::value;
4315 }
4316
4317 } // namespace impl
4318
4319 // checks whether T has a member named is_transparent
4320 template<typename T>
4321 struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4322
4324
4325} // namespace detail
4326NLOHMANN_JSON_NAMESPACE_END
4327
4328// #include <nlohmann/detail/string_concat.hpp>
4329// __ _____ _____ _____
4330// __| | __| | | | JSON for Modern C++
4331// | | |__ | | | | | | version 3.12.0
4332// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4333//
4334// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
4335// SPDX-License-Identifier: MIT
4336
4337
4338
4339#include <cstring> // strlen
4340#include <string> // string
4341#include <utility> // forward
4342
4343// #include <nlohmann/detail/meta/cpp_future.hpp>
4344
4345// #include <nlohmann/detail/meta/detected.hpp>
4346
4347
4348NLOHMANN_JSON_NAMESPACE_BEGIN
4349namespace detail {
4350
4351 inline std::size_t concat_length() {
4352 return 0;
4353 }
4354
4355 template<typename... Args>
4356 inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4357
4358 template<typename StringType, typename... Args>
4359 inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4360
4361 template<typename... Args>
4362 inline std::size_t concat_length(const char /*c*/, const Args& ... rest) {
4363 return 1 + concat_length(rest...);
4364 }
4365
4366 template<typename... Args>
4367 inline std::size_t concat_length(const char* cstr, const Args& ... rest) {
4368 // cppcheck-suppress ignoredReturnValue
4369 return ::strlen(cstr) + concat_length(rest...);
4370 }
4371
4372 template<typename StringType, typename... Args>
4373 inline std::size_t concat_length(const StringType& str, const Args& ... rest) {
4374 return str.size() + concat_length(rest...);
4375 }
4376
4377 template<typename OutStringType>
4378 inline void concat_into(OutStringType& /*out*/) {}
4379
4380 template<typename StringType, typename Arg>
4381 using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg&& >()));
4382
4383 template<typename StringType, typename Arg>
4384 using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
4385
4386 template<typename StringType, typename Arg>
4387 using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg&& >());
4388
4389 template<typename StringType, typename Arg>
4390 using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
4391
4392 template<typename StringType, typename Arg>
4393 using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4394
4395 template<typename StringType, typename Arg>
4396 using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
4397
4398 template<typename StringType, typename Arg>
4399 using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4400
4401 template<typename StringType, typename Arg>
4402 using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
4403
4404 template < typename OutStringType, typename Arg, typename... Args,
4405 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4406 && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
4407 inline void concat_into(OutStringType& out, Arg&& arg, Args && ... rest);
4408
4409 template < typename OutStringType, typename Arg, typename... Args,
4410 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4411 && !detect_string_can_append_op<OutStringType, Arg>::value
4412 && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
4413 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4414
4415 template < typename OutStringType, typename Arg, typename... Args,
4416 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4417 && !detect_string_can_append_op<OutStringType, Arg>::value
4418 && !detect_string_can_append_iter<OutStringType, Arg>::value
4419 && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
4420 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4421
4422 template<typename OutStringType, typename Arg, typename... Args,
4423 enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
4424 inline void concat_into(OutStringType& out, Arg&& arg, Args && ... rest) {
4425 out.append(std::forward<Arg>(arg));
4426 concat_into(out, std::forward<Args>(rest)...);
4427 }
4428
4429 template < typename OutStringType, typename Arg, typename... Args,
4430 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4431 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4432 inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest) {
4433 out += std::forward<Arg>(arg);
4434 concat_into(out, std::forward<Args>(rest)...);
4435 }
4436
4437 template < typename OutStringType, typename Arg, typename... Args,
4438 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4439 && !detect_string_can_append_op<OutStringType, Arg>::value
4440 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4441 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) {
4442 out.append(arg.begin(), arg.end());
4443 concat_into(out, std::forward<Args>(rest)...);
4444 }
4445
4446 template < typename OutStringType, typename Arg, typename... Args,
4447 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4448 && !detect_string_can_append_op<OutStringType, Arg>::value
4449 && !detect_string_can_append_iter<OutStringType, Arg>::value
4450 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4451 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) {
4452 out.append(arg.data(), arg.size());
4453 concat_into(out, std::forward<Args>(rest)...);
4454 }
4455
4456 template<typename OutStringType = std::string, typename... Args>
4457 inline OutStringType concat(Args && ... args) {
4458 OutStringType str;
4459 str.reserve(concat_length(args...));
4460 concat_into(str, std::forward<Args>(args)...);
4461 return str;
4462 }
4463
4464} // namespace detail
4465NLOHMANN_JSON_NAMESPACE_END
4466
4467
4468// With -Wweak-vtables, Clang will complain about the exception classes as they
4469// have no out-of-line virtual method definitions and their vtable will be
4470// emitted in every translation unit. This issue cannot be fixed with a
4471// header-only library as there is no implementation file to move these
4472// functions to. As a result, we suppress this warning here to avoid client
4473// code stumbling over this. See https://github.com/nlohmann/json/issues/4087
4474// for a discussion.
4475#if defined(__clang__)
4476#pragma clang diagnostic push
4477#pragma clang diagnostic ignored "-Wweak-vtables"
4478#endif
4479
4480NLOHMANN_JSON_NAMESPACE_BEGIN
4481namespace detail {
4482
4484 // exceptions //
4486
4489 class exception : public std::exception {
4490 public:
4492 const char* what() const noexcept override {
4493 return m.what();
4494 }
4495
4497 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4498
4499 protected:
4500 JSON_HEDLEY_NON_NULL(3)
4501 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4502
4503 static std::string name(const std::string& ename, int id_) {
4504 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4505 }
4506
4507 static std::string diagnostics(std::nullptr_t /*leaf_element*/) {
4508 return "";
4509 }
4510
4511 template<typename BasicJsonType>
4512 static std::string diagnostics(const BasicJsonType* leaf_element) {
4513#if JSON_DIAGNOSTICS
4514 std::vector<std::string> tokens;
4515 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent) {
4516 switch (current->m_parent->type()) {
4517 case value_t::array:
4518 {
4519 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i) {
4520 if (&current->m_parent->m_data.m_value.array->operator[](i) == current) {
4521 tokens.emplace_back(std::to_string(i));
4522 break;
4523 }
4524 }
4525 break;
4526 }
4527
4528 case value_t::object:
4529 {
4530 for (const auto& element : *current->m_parent->m_data.m_value.object) {
4531 if (&element.second == current) {
4532 tokens.emplace_back(element.first.c_str());
4533 break;
4534 }
4535 }
4536 break;
4537 }
4538
4539 case value_t::null: // LCOV_EXCL_LINE
4540 case value_t::string: // LCOV_EXCL_LINE
4541 case value_t::boolean: // LCOV_EXCL_LINE
4542 case value_t::number_integer: // LCOV_EXCL_LINE
4543 case value_t::number_unsigned: // LCOV_EXCL_LINE
4544 case value_t::number_float: // LCOV_EXCL_LINE
4545 case value_t::binary: // LCOV_EXCL_LINE
4546 case value_t::discarded: // LCOV_EXCL_LINE
4547 default: // LCOV_EXCL_LINE
4548 break; // LCOV_EXCL_LINE
4549 }
4550 }
4551
4552 if (tokens.empty()) {
4553 return "";
4554 }
4555
4556 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4557 [](const std::string& a, const std::string& b) {
4558 return concat(a, '/', detail::escape(b));
4559 });
4560
4561 return concat('(', str, ") ", get_byte_positions(leaf_element));
4562#else
4563 return get_byte_positions(leaf_element);
4564#endif
4565 }
4566
4567 private:
4569 std::runtime_error m;
4570#if JSON_DIAGNOSTIC_POSITIONS
4571 template<typename BasicJsonType>
4572 static std::string get_byte_positions(const BasicJsonType* leaf_element) {
4573 if ((leaf_element->start_pos() != std::string::npos) && (leaf_element->end_pos() != std::string::npos)) {
4574 return concat("(bytes ", std::to_string(leaf_element->start_pos()), "-", std::to_string(leaf_element->end_pos()), ") ");
4575 }
4576 return "";
4577 }
4578#else
4579 template<typename BasicJsonType>
4580 static std::string get_byte_positions(const BasicJsonType* leaf_element) {
4581 static_cast<void>(leaf_element);
4582 return "";
4583 }
4584#endif
4585 };
4586
4589 class parse_error : public exception {
4590 public:
4600 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4601 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context) {
4602 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4603 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4604 return { id_, pos.chars_read_total, w.c_str() };
4605 }
4606
4607 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4608 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context) {
4609 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4610 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4611 ": ", exception::diagnostics(context), what_arg);
4612 return { id_, byte_, w.c_str() };
4613 }
4614
4624 const std::size_t byte;
4625
4626 private:
4627 parse_error(int id_, std::size_t byte_, const char* what_arg)
4628 : exception(id_, what_arg), byte(byte_) {}
4629
4630 static std::string position_string(const position_t& pos) {
4631 return concat(" at line ", std::to_string(pos.lines_read + 1),
4632 ", column ", std::to_string(pos.chars_read_current_line));
4633 }
4634 };
4635
4638 class invalid_iterator : public exception {
4639 public:
4640 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4641 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context) {
4642 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4643 return { id_, w.c_str() };
4644 }
4645
4646 private:
4647 JSON_HEDLEY_NON_NULL(3)
4648 invalid_iterator(int id_, const char* what_arg)
4649 : exception(id_, what_arg) {}
4650 };
4651
4654 class type_error : public exception {
4655 public:
4656 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4657 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context) {
4658 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4659 return { id_, w.c_str() };
4660 }
4661
4662 private:
4663 JSON_HEDLEY_NON_NULL(3)
4664 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4665 };
4666
4669 class out_of_range : public exception {
4670 public:
4671 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4672 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context) {
4673 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4674 return { id_, w.c_str() };
4675 }
4676
4677 private:
4678 JSON_HEDLEY_NON_NULL(3)
4679 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4680 };
4681
4684 class other_error : public exception {
4685 public:
4686 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4687 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context) {
4688 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4689 return { id_, w.c_str() };
4690 }
4691
4692 private:
4693 JSON_HEDLEY_NON_NULL(3)
4694 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4695 };
4696
4697} // namespace detail
4698NLOHMANN_JSON_NAMESPACE_END
4699
4700#if defined(__clang__)
4701#pragma clang diagnostic pop
4702#endif
4703
4704// #include <nlohmann/detail/macro_scope.hpp>
4705
4706// #include <nlohmann/detail/meta/cpp_future.hpp>
4707
4708// #include <nlohmann/detail/meta/identity_tag.hpp>
4709// __ _____ _____ _____
4710// __| | __| | | | JSON for Modern C++
4711// | | |__ | | | | | | version 3.12.0
4712// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4713//
4714// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
4715// SPDX-License-Identifier: MIT
4716
4717
4718
4719// #include <nlohmann/detail/abi_macros.hpp>
4720
4721
4722NLOHMANN_JSON_NAMESPACE_BEGIN
4723namespace detail {
4724
4725 // dispatching helper struct
4726 template <class T> struct identity_tag {};
4727
4728} // namespace detail
4729NLOHMANN_JSON_NAMESPACE_END
4730
4731// #include <nlohmann/detail/meta/std_fs.hpp>
4732// __ _____ _____ _____
4733// __| | __| | | | JSON for Modern C++
4734// | | |__ | | | | | | version 3.12.0
4735// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4736//
4737// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
4738// SPDX-License-Identifier: MIT
4739
4740
4741
4742// #include <nlohmann/detail/macro_scope.hpp>
4743
4744
4745#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4746#include <experimental/filesystem>
4747NLOHMANN_JSON_NAMESPACE_BEGIN
4748namespace detail {
4749 namespace std_fs = std::experimental::filesystem;
4750} // namespace detail
4751NLOHMANN_JSON_NAMESPACE_END
4752#elif JSON_HAS_FILESYSTEM
4753#include <filesystem> // NOLINT(build/c++17)
4754NLOHMANN_JSON_NAMESPACE_BEGIN
4755namespace detail {
4756 namespace std_fs = std::filesystem;
4757} // namespace detail
4758NLOHMANN_JSON_NAMESPACE_END
4759#endif
4760
4761// #include <nlohmann/detail/meta/type_traits.hpp>
4762
4763// #include <nlohmann/detail/meta/logic.hpp>
4764
4765
4766// #include <nlohmann/detail/macro_scope.hpp>
4767
4768
4769NLOHMANN_JSON_NAMESPACE_BEGIN
4770namespace detail {
4771#ifdef JSON_HAS_CPP_17
4772
4773 template<bool... Booleans>
4774 struct cxpr_or_impl : std::integral_constant < bool, (Booleans || ...) > {};
4775
4776 template<bool... Booleans>
4777 struct cxpr_and_impl : std::integral_constant < bool, (Booleans &&...) > {};
4778
4779#else
4780
4781 template<bool... Booleans>
4782 struct cxpr_or_impl : std::false_type {};
4783
4784 template<bool... Booleans>
4785 struct cxpr_or_impl<true, Booleans...> : std::true_type {};
4786
4787 template<bool... Booleans>
4788 struct cxpr_or_impl<false, Booleans...> : cxpr_or_impl<Booleans...> {};
4789
4790 template<bool... Booleans>
4791 struct cxpr_and_impl : std::true_type {};
4792
4793 template<bool... Booleans>
4794 struct cxpr_and_impl<true, Booleans...> : cxpr_and_impl<Booleans...> {};
4795
4796 template<bool... Booleans>
4797 struct cxpr_and_impl<false, Booleans...> : std::false_type {};
4798
4799#endif
4800
4801 template<class Boolean>
4802 struct cxpr_not : std::integral_constant < bool, !Boolean::value > {};
4803
4804 template<class... Booleans>
4805 struct cxpr_or : cxpr_or_impl<Booleans::value...> {};
4806
4807 template<bool... Booleans>
4808 struct cxpr_or_c : cxpr_or_impl<Booleans...> {};
4809
4810 template<class... Booleans>
4811 struct cxpr_and : cxpr_and_impl<Booleans::value...> {};
4812
4813 template<bool... Booleans>
4814 struct cxpr_and_c : cxpr_and_impl<Booleans...> {};
4815
4816} // namespace detail
4817NLOHMANN_JSON_NAMESPACE_END
4818
4819// #include <nlohmann/detail/string_concat.hpp>
4820
4821// #include <nlohmann/detail/value_t.hpp>
4822
4823
4824// include after macro_scope.hpp
4825#ifdef JSON_HAS_CPP_17
4826#include <optional> // optional
4827#endif
4828
4829#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4830#include <string_view> // u8string_view
4831#endif
4832
4833NLOHMANN_JSON_NAMESPACE_BEGIN
4834namespace detail {
4835
4836 template<typename BasicJsonType>
4837 inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) {
4838 if (JSON_HEDLEY_UNLIKELY(!j.is_null())) {
4839 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4840 }
4841 n = nullptr;
4842 }
4843
4844#ifdef JSON_HAS_CPP_17
4845 template < typename BasicJsonType, typename T,
4846 typename std::enable_if < !nlohmann::detail::is_basic_json<T>::value, int >::type = 0 >
4847 void from_json(const BasicJsonType& j, std::optional<T>& opt) {
4848 if (j.is_null()) {
4849 opt = std::nullopt;
4850 }
4851 else {
4852 opt.emplace(j.template get<T>());
4853 }
4854 }
4855#endif // JSON_HAS_CPP_17
4856
4857 // overloads for basic_json template parameters
4858 template < typename BasicJsonType, typename ArithmeticType,
4859 enable_if_t < std::is_arithmetic<ArithmeticType>::value &&
4860 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4861 int > = 0 >
4862 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) {
4863 switch (static_cast<value_t>(j)) {
4865 {
4866 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4867 break;
4868 }
4870 {
4871 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4872 break;
4873 }
4875 {
4876 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4877 break;
4878 }
4879
4880 case value_t::null:
4881 case value_t::object:
4882 case value_t::array:
4883 case value_t::string:
4884 case value_t::boolean:
4885 case value_t::binary:
4886 case value_t::discarded:
4887 default:
4888 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4889 }
4890 }
4891
4892 template<typename BasicJsonType>
4893 inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) {
4894 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) {
4895 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4896 }
4897 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4898 }
4899
4900 template<typename BasicJsonType>
4901 inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) {
4902 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) {
4903 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4904 }
4905 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4906 }
4907
4908 template <
4909 typename BasicJsonType, typename StringType,
4910 enable_if_t <
4911 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4912 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4913 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4914 && !is_json_ref<StringType>::value, int > = 0 >
4915 inline void from_json(const BasicJsonType& j, StringType& s) {
4916 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) {
4917 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4918 }
4919
4920 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4921 }
4922
4923 template<typename BasicJsonType>
4924 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) {
4925 get_arithmetic_value(j, val);
4926 }
4927
4928 template<typename BasicJsonType>
4929 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) {
4930 get_arithmetic_value(j, val);
4931 }
4932
4933 template<typename BasicJsonType>
4934 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) {
4935 get_arithmetic_value(j, val);
4936 }
4937
4938#if !JSON_DISABLE_ENUM_SERIALIZATION
4939 template<typename BasicJsonType, typename EnumType,
4940 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4941 inline void from_json(const BasicJsonType& j, EnumType& e) {
4942 typename std::underlying_type<EnumType>::type val;
4943 get_arithmetic_value(j, val);
4944 e = static_cast<EnumType>(val);
4945 }
4946#endif // JSON_DISABLE_ENUM_SERIALIZATION
4947
4948 // forward_list doesn't have an insert method
4949 template<typename BasicJsonType, typename T, typename Allocator,
4950 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4951 inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) {
4952 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
4953 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4954 }
4955 l.clear();
4956 std::transform(j.rbegin(), j.rend(),
4957 std::front_inserter(l), [](const BasicJsonType& i) {
4958 return i.template get<T>();
4959 });
4960 }
4961
4962 // valarray doesn't have an insert method
4963 template<typename BasicJsonType, typename T,
4964 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4965 inline void from_json(const BasicJsonType& j, std::valarray<T>& l) {
4966 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
4967 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4968 }
4969 l.resize(j.size());
4970 std::transform(j.begin(), j.end(), std::begin(l),
4971 [](const BasicJsonType& elem) {
4972 return elem.template get<T>();
4973 });
4974 }
4975
4976 template<typename BasicJsonType, typename T, std::size_t N>
4977 auto from_json(const BasicJsonType& j, T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4978 -> decltype(j.template get<T>(), void()) {
4979 for (std::size_t i = 0; i < N; ++i) {
4980 arr[i] = j.at(i).template get<T>();
4981 }
4982 }
4983
4984 template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2>
4985 auto from_json(const BasicJsonType& j, T(&arr)[N1][N2]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4986 -> decltype(j.template get<T>(), void()) {
4987 for (std::size_t i1 = 0; i1 < N1; ++i1) {
4988 for (std::size_t i2 = 0; i2 < N2; ++i2) {
4989 arr[i1][i2] = j.at(i1).at(i2).template get<T>();
4990 }
4991 }
4992 }
4993
4994 template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3>
4995 auto from_json(const BasicJsonType& j, T(&arr)[N1][N2][N3]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4996 -> decltype(j.template get<T>(), void()) {
4997 for (std::size_t i1 = 0; i1 < N1; ++i1) {
4998 for (std::size_t i2 = 0; i2 < N2; ++i2) {
4999 for (std::size_t i3 = 0; i3 < N3; ++i3) {
5000 arr[i1][i2][i3] = j.at(i1).at(i2).at(i3).template get<T>();
5001 }
5002 }
5003 }
5004 }
5005
5006 template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3, std::size_t N4>
5007 auto from_json(const BasicJsonType& j, T(&arr)[N1][N2][N3][N4]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5008 -> decltype(j.template get<T>(), void()) {
5009 for (std::size_t i1 = 0; i1 < N1; ++i1) {
5010 for (std::size_t i2 = 0; i2 < N2; ++i2) {
5011 for (std::size_t i3 = 0; i3 < N3; ++i3) {
5012 for (std::size_t i4 = 0; i4 < N4; ++i4) {
5013 arr[i1][i2][i3][i4] = j.at(i1).at(i2).at(i3).at(i4).template get<T>();
5014 }
5015 }
5016 }
5017 }
5018 }
5019
5020 template<typename BasicJsonType>
5021 inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) {
5022 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
5023 }
5024
5025 template<typename BasicJsonType, typename T, std::size_t N>
5026 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
5027 priority_tag<2> /*unused*/)
5028 -> decltype(j.template get<T>(), void()) {
5029 for (std::size_t i = 0; i < N; ++i) {
5030 arr[i] = j.at(i).template get<T>();
5031 }
5032 }
5033
5034 template<typename BasicJsonType, typename ConstructibleArrayType,
5035 enable_if_t<
5036 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5037 int> = 0>
5038 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
5039 -> decltype(
5040 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
5041 j.template get<typename ConstructibleArrayType::value_type>(),
5042 void()) {
5043 using std::end;
5044
5045 ConstructibleArrayType ret;
5046 ret.reserve(j.size());
5047 std::transform(j.begin(), j.end(),
5048 std::inserter(ret, end(ret)), [](const BasicJsonType& i) {
5049 // get<BasicJsonType>() returns *this, this won't call a from_json
5050 // method when value_type is BasicJsonType
5051 return i.template get<typename ConstructibleArrayType::value_type>();
5052 });
5053 arr = std::move(ret);
5054 }
5055
5056 template<typename BasicJsonType, typename ConstructibleArrayType,
5057 enable_if_t<
5058 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5059 int> = 0>
5060 inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
5061 priority_tag<0> /*unused*/) {
5062 using std::end;
5063
5064 ConstructibleArrayType ret;
5065 std::transform(
5066 j.begin(), j.end(), std::inserter(ret, end(ret)),
5067 [](const BasicJsonType& i) {
5068 // get<BasicJsonType>() returns *this, this won't call a from_json
5069 // method when value_type is BasicJsonType
5070 return i.template get<typename ConstructibleArrayType::value_type>();
5071 });
5072 arr = std::move(ret);
5073 }
5074
5075 template < typename BasicJsonType, typename ConstructibleArrayType,
5076 enable_if_t <
5079 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value &&
5080 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value &&
5082 int > = 0 >
5083 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
5084 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
5085 j.template get<typename ConstructibleArrayType::value_type>(),
5086 void()) {
5087 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
5088 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5089 }
5090
5091 from_json_array_impl(j, arr, priority_tag<3> {});
5092 }
5093
5094 template < typename BasicJsonType, typename T, std::size_t... Idx >
5095 std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
5096 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/) {
5097 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
5098 }
5099
5100 template < typename BasicJsonType, typename T, std::size_t N >
5101 auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
5102 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {})) {
5103 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
5104 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5105 }
5106
5107 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
5108 }
5109
5110 template<typename BasicJsonType>
5111 inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) {
5112 if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) {
5113 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
5114 }
5115
5116 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
5117 }
5118
5119 template<typename BasicJsonType, typename ConstructibleObjectType,
5120 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
5121 inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) {
5122 if (JSON_HEDLEY_UNLIKELY(!j.is_object())) {
5123 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
5124 }
5125
5126 ConstructibleObjectType ret;
5127 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
5128 using value_type = typename ConstructibleObjectType::value_type;
5129 std::transform(
5130 inner_object->begin(), inner_object->end(),
5131 std::inserter(ret, ret.begin()),
5132 [](typename BasicJsonType::object_t::value_type const& p) {
5133 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
5134 });
5135 obj = std::move(ret);
5136 }
5137
5138 // overload for arithmetic types, not chosen for basic_json template arguments
5139 // (BooleanType, etc.); note: Is it really necessary to provide explicit
5140 // overloads for boolean_t etc. in case of a custom BooleanType which is not
5141 // an arithmetic type?
5142 template < typename BasicJsonType, typename ArithmeticType,
5143 enable_if_t <
5144 std::is_arithmetic<ArithmeticType>::value &&
5145 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value &&
5146 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value &&
5147 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value &&
5148 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
5149 int > = 0 >
5150 inline void from_json(const BasicJsonType& j, ArithmeticType& val) {
5151 switch (static_cast<value_t>(j)) {
5153 {
5154 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
5155 break;
5156 }
5158 {
5159 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5160 break;
5161 }
5163 {
5164 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5165 break;
5166 }
5167 case value_t::boolean:
5168 {
5169 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5170 break;
5171 }
5172
5173 case value_t::null:
5174 case value_t::object:
5175 case value_t::array:
5176 case value_t::string:
5177 case value_t::binary:
5178 case value_t::discarded:
5179 default:
5180 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5181 }
5182 }
5183
5184 template<typename BasicJsonType, typename Type>
5185 detail::uncvref_t<Type> from_json_tuple_get_impl(BasicJsonType&& j, detail::identity_tag<Type> /*unused*/, detail::priority_tag<0> /*unused*/) {
5186 return std::forward<BasicJsonType>(j).template get<detail::uncvref_t<Type>>();
5187 }
5188
5189 template<typename BasicJsonType, typename Type,
5190 detail::enable_if_t<detail::is_compatible_reference_type<BasicJsonType, Type>::value, int> = 0>
5191 Type from_json_tuple_get_impl(BasicJsonType&& j, detail::identity_tag<Type> /*unused*/, detail::priority_tag<1> /*unused*/) {
5192 return std::forward<BasicJsonType>(j).template get_ref<Type>();
5193 }
5194
5195 template<typename BasicJsonType, typename Type,
5196 detail::enable_if_t<std::is_arithmetic<uncvref_t<Type>>::value, int> = 0>
5197 detail::uncvref_t<Type> from_json_tuple_get_impl(BasicJsonType&& j, detail::identity_tag<Type> /*unused*/, detail::priority_tag<2> /*unused*/) {
5198 return std::forward<BasicJsonType>(j).template get<detail::uncvref_t<Type>>();
5199 }
5200
5201 template<std::size_t PTagValue, typename BasicJsonType, typename... Types>
5202 using tuple_type = std::tuple < decltype(from_json_tuple_get_impl(std::declval<BasicJsonType>(), detail::identity_tag<Types> {}, detail::priority_tag<PTagValue> {}))... > ;
5203
5204 template<std::size_t PTagValue, typename... Args, typename BasicJsonType, std::size_t... Idx>
5205 tuple_type<PTagValue, BasicJsonType, Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/) {
5206 return tuple_type<PTagValue, BasicJsonType, Args...>(from_json_tuple_get_impl(std::forward<BasicJsonType>(j).at(Idx), detail::identity_tag<Args> {}, detail::priority_tag<PTagValue> {})...);
5207 }
5208
5209 template<std::size_t PTagValue, typename BasicJsonType>
5210 std::tuple<> from_json_tuple_impl_base(BasicJsonType& /*unused*/, index_sequence<> /*unused*/) {
5211 return {};
5212 }
5213
5214 template < typename BasicJsonType, class A1, class A2 >
5215 std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/) {
5216 return { std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5217 std::forward<BasicJsonType>(j).at(1).template get<A2>() };
5218 }
5219
5220 template<typename BasicJsonType, typename A1, typename A2>
5221 inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/) {
5222 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5223 }
5224
5225 template<typename BasicJsonType, typename... Args>
5226 std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/) {
5228 "Can not return a tuple containing references to types not contained in a Json, try Json::get_to()");
5229 return from_json_tuple_impl_base<1, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5230 }
5231
5232 template<typename BasicJsonType, typename... Args>
5233 inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/) {
5234 t = from_json_tuple_impl_base<2, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5235 }
5236
5237 template<typename BasicJsonType, typename TupleRelated>
5238 auto from_json(BasicJsonType&& j, TupleRelated&& t)
5239 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {})) {
5240 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
5241 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5242 }
5243
5244 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5245 }
5246
5247 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5248 typename = enable_if_t < !std::is_constructible <
5249 typename BasicJsonType::string_t, Key >::value >>
5250 inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m) {
5251 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
5252 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5253 }
5254 m.clear();
5255 for (const auto& p : j) {
5256 if (JSON_HEDLEY_UNLIKELY(!p.is_array())) {
5257 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5258 }
5259 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5260 }
5261 }
5262
5263 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5264 typename = enable_if_t < !std::is_constructible <
5265 typename BasicJsonType::string_t, Key >::value >>
5266 inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m) {
5267 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
5268 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5269 }
5270 m.clear();
5271 for (const auto& p : j) {
5272 if (JSON_HEDLEY_UNLIKELY(!p.is_array())) {
5273 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5274 }
5275 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5276 }
5277 }
5278
5279#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5280 template<typename BasicJsonType>
5281 inline void from_json(const BasicJsonType& j, std_fs::path& p) {
5282 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) {
5283 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5284 }
5285 const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5286 // Checking for C++20 standard or later can be insufficient in case the
5287 // library support for char8_t is either incomplete or was disabled
5288 // altogether. Use the __cpp_lib_char8_t feature test instead.
5289#if defined(__cpp_lib_char8_t) && (__cpp_lib_char8_t >= 201907L)
5290 p = std_fs::path(std::u8string_view(reinterpret_cast<const char8_t*>(s.data()), s.size()));
5291#else
5292 p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20
5293#endif
5294 }
5295#endif
5296
5298 template<typename BasicJsonType, typename T>
5299 auto operator()(const BasicJsonType& j, T&& val) const
5300 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5301 -> decltype(from_json(j, std::forward<T>(val))) {
5302 return from_json(j, std::forward<T>(val));
5303 }
5304 };
5305
5306} // namespace detail
5307
5308#ifndef JSON_HAS_CPP_17
5312namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5313{
5314#endif
5315 JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5316 detail::static_const<detail::from_json_fn>::value;
5317#ifndef JSON_HAS_CPP_17
5318} // namespace
5319#endif
5320
5321NLOHMANN_JSON_NAMESPACE_END
5322
5323// #include <nlohmann/detail/conversions/to_json.hpp>
5324// __ _____ _____ _____
5325// __| | __| | | | JSON for Modern C++
5326// | | |__ | | | | | | version 3.12.0
5327// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5328//
5329// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
5330// SPDX-License-Identifier: MIT
5331
5332
5333
5334// #include <nlohmann/detail/macro_scope.hpp>
5335// JSON_HAS_CPP_17
5336#ifdef JSON_HAS_CPP_17
5337#include <optional> // optional
5338#endif
5339
5340#include <algorithm> // copy
5341#include <iterator> // begin, end
5342#include <memory> // allocator_traits
5343#include <string> // basic_string, char_traits
5344#include <tuple> // tuple, get
5345#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5346#include <utility> // move, forward, declval, pair
5347#include <valarray> // valarray
5348#include <vector> // vector
5349
5350// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5351// __ _____ _____ _____
5352// __| | __| | | | JSON for Modern C++
5353// | | |__ | | | | | | version 3.12.0
5354// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5355//
5356// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
5357// SPDX-License-Identifier: MIT
5358
5359
5360
5361#include <cstddef> // size_t
5362#include <iterator> // forward_iterator_tag
5363#include <tuple> // tuple_size, get, tuple_element
5364#include <utility> // move
5365
5366#if JSON_HAS_RANGES
5367#include <ranges> // enable_borrowed_range
5368#endif
5369
5370// #include <nlohmann/detail/abi_macros.hpp>
5371
5372// #include <nlohmann/detail/meta/type_traits.hpp>
5373
5374// #include <nlohmann/detail/string_utils.hpp>
5375// __ _____ _____ _____
5376// __| | __| | | | JSON for Modern C++
5377// | | |__ | | | | | | version 3.12.0
5378// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5379//
5380// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
5381// SPDX-License-Identifier: MIT
5382
5383
5384
5385#include <cstddef> // size_t
5386#include <string> // string, to_string
5387
5388// #include <nlohmann/detail/abi_macros.hpp>
5389
5390
5391NLOHMANN_JSON_NAMESPACE_BEGIN
5392namespace detail {
5393
5394 template<typename StringType>
5395 void int_to_string(StringType& target, std::size_t value) {
5396 // For ADL
5397 using std::to_string;
5398 target = to_string(value);
5399 }
5400
5401 template<typename StringType>
5402 StringType to_string(std::size_t value) {
5403 StringType result;
5404 int_to_string(result, value);
5405 return result;
5406 }
5407
5408} // namespace detail
5409NLOHMANN_JSON_NAMESPACE_END
5410
5411// #include <nlohmann/detail/value_t.hpp>
5412
5413
5414NLOHMANN_JSON_NAMESPACE_BEGIN
5415namespace detail {
5416
5417 template<typename IteratorType> class iteration_proxy_value {
5418 public:
5419 using difference_type = std::ptrdiff_t;
5420 using value_type = iteration_proxy_value;
5421 using pointer = value_type*;
5422 using reference = value_type&;
5423 using iterator_category = std::forward_iterator_tag;
5424 using string_type = typename std::remove_cv< typename std::remove_reference<decltype(std::declval<IteratorType>().key()) >::type >::type;
5425
5426 private:
5428 IteratorType anchor{};
5430 std::size_t array_index = 0;
5432 mutable std::size_t array_index_last = 0;
5434 mutable string_type array_index_str = "0";
5436 string_type empty_str{};
5437
5438 public:
5439 explicit iteration_proxy_value() = default;
5440 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5441 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5442 && std::is_nothrow_default_constructible<string_type>::value)
5443 : anchor(std::move(it))
5444 , array_index(array_index_) {}
5445
5446 iteration_proxy_value(iteration_proxy_value const&) = default;
5447 iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
5448 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5449 iteration_proxy_value(iteration_proxy_value&&)
5450 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5451 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5452 iteration_proxy_value& operator=(iteration_proxy_value&&)
5453 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5454 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5455 ~iteration_proxy_value() = default;
5456
5458 const iteration_proxy_value& operator*() const {
5459 return *this;
5460 }
5461
5463 iteration_proxy_value& operator++() {
5464 ++anchor;
5465 ++array_index;
5466
5467 return *this;
5468 }
5469
5470 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5471 {
5472 auto tmp = iteration_proxy_value(anchor, array_index);
5473 ++anchor;
5474 ++array_index;
5475 return tmp;
5476 }
5477
5479 bool operator==(const iteration_proxy_value& o) const {
5480 return anchor == o.anchor;
5481 }
5482
5484 bool operator!=(const iteration_proxy_value& o) const {
5485 return anchor != o.anchor;
5486 }
5487
5489 const string_type& key() const {
5490 JSON_ASSERT(anchor.m_object != nullptr);
5491
5492 switch (anchor.m_object->type()) {
5493 // use integer array index as key
5494 case value_t::array:
5495 {
5496 if (array_index != array_index_last) {
5497 int_to_string(array_index_str, array_index);
5498 array_index_last = array_index;
5499 }
5500 return array_index_str;
5501 }
5502
5503 // use key from the object
5504 case value_t::object:
5505 return anchor.key();
5506
5507 // use an empty key for all primitive types
5508 case value_t::null:
5509 case value_t::string:
5510 case value_t::boolean:
5514 case value_t::binary:
5515 case value_t::discarded:
5516 default:
5517 return empty_str;
5518 }
5519 }
5520
5522 typename IteratorType::reference value() const {
5523 return anchor.value();
5524 }
5525 };
5526
5528 template<typename IteratorType> class iteration_proxy {
5529 private:
5531 typename IteratorType::pointer container = nullptr;
5532
5533 public:
5534 explicit iteration_proxy() = default;
5535
5537 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5538 : container(&cont) {}
5539
5540 iteration_proxy(iteration_proxy const&) = default;
5541 iteration_proxy& operator=(iteration_proxy const&) = default;
5542 iteration_proxy(iteration_proxy&&) noexcept = default;
5543 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5544 ~iteration_proxy() = default;
5545
5547 iteration_proxy_value<IteratorType> begin() const noexcept {
5548 return iteration_proxy_value<IteratorType>(container->begin());
5549 }
5550
5553 return iteration_proxy_value<IteratorType>(container->end());
5554 }
5555 };
5556
5557 // Structured Bindings Support
5558 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
5559 // And see https://github.com/nlohmann/json/pull/1391
5560 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5561 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key()) {
5562 return i.key();
5563 }
5564 // Structured Bindings Support
5565 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
5566 // And see https://github.com/nlohmann/json/pull/1391
5567 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5568 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value()) {
5569 return i.value();
5570 }
5571
5572} // namespace detail
5573NLOHMANN_JSON_NAMESPACE_END
5574
5575// The Addition to the STD Namespace is required to add
5576// Structured Bindings Support to the iteration_proxy_value class
5577// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5578// And see https://github.com/nlohmann/json/pull/1391
5579namespace std {
5580
5581#if defined(__clang__)
5582 // Fix: https://github.com/nlohmann/json/issues/1401
5583#pragma clang diagnostic push
5584#pragma clang diagnostic ignored "-Wmismatched-tags"
5585#endif
5586 template<typename IteratorType>
5587 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5588 : public std::integral_constant<std::size_t, 2> {};
5589
5590 template<std::size_t N, typename IteratorType>
5591 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5592 {
5593 public:
5594 using type = decltype(
5595 get<N>(std::declval <
5596 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5597 };
5598#if defined(__clang__)
5599#pragma clang diagnostic pop
5600#endif
5601
5602} // namespace std
5603
5604#if JSON_HAS_RANGES
5605template <typename IteratorType>
5606inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5607#endif
5608
5609// #include <nlohmann/detail/meta/cpp_future.hpp>
5610
5611// #include <nlohmann/detail/meta/std_fs.hpp>
5612
5613// #include <nlohmann/detail/meta/type_traits.hpp>
5614
5615// #include <nlohmann/detail/value_t.hpp>
5616
5617
5618NLOHMANN_JSON_NAMESPACE_BEGIN
5619namespace detail {
5620
5622 // constructors //
5624
5625 /*
5626 * Note all external_constructor<>::construct functions need to call
5627 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5628 * allocated value (e.g., a string). See bug issue
5629 * https://github.com/nlohmann/json/issues/2865 for more information.
5630 */
5631
5632 template<value_t> struct external_constructor;
5633
5634 template<>
5636 template<typename BasicJsonType>
5637 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept {
5638 j.m_data.m_value.destroy(j.m_data.m_type);
5639 j.m_data.m_type = value_t::boolean;
5640 j.m_data.m_value = b;
5641 j.assert_invariant();
5642 }
5643 };
5644
5645 template<>
5647 template<typename BasicJsonType>
5648 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) {
5649 j.m_data.m_value.destroy(j.m_data.m_type);
5650 j.m_data.m_type = value_t::string;
5651 j.m_data.m_value = s;
5652 j.assert_invariant();
5653 }
5654
5655 template<typename BasicJsonType>
5656 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) {
5657 j.m_data.m_value.destroy(j.m_data.m_type);
5658 j.m_data.m_type = value_t::string;
5659 j.m_data.m_value = std::move(s);
5660 j.assert_invariant();
5661 }
5662
5663 template < typename BasicJsonType, typename CompatibleStringType,
5664 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5665 int > = 0 >
5666 static void construct(BasicJsonType& j, const CompatibleStringType& str) {
5667 j.m_data.m_value.destroy(j.m_data.m_type);
5668 j.m_data.m_type = value_t::string;
5669 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5670 j.assert_invariant();
5671 }
5672 };
5673
5674 template<>
5676 template<typename BasicJsonType>
5677 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) {
5678 j.m_data.m_value.destroy(j.m_data.m_type);
5679 j.m_data.m_type = value_t::binary;
5680 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5681 j.assert_invariant();
5682 }
5683
5684 template<typename BasicJsonType>
5685 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) {
5686 j.m_data.m_value.destroy(j.m_data.m_type);
5687 j.m_data.m_type = value_t::binary;
5688 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5689 j.assert_invariant();
5690 }
5691 };
5692
5693 template<>
5695 template<typename BasicJsonType>
5696 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept {
5697 j.m_data.m_value.destroy(j.m_data.m_type);
5698 j.m_data.m_type = value_t::number_float;
5699 j.m_data.m_value = val;
5700 j.assert_invariant();
5701 }
5702 };
5703
5704 template<>
5706 template<typename BasicJsonType>
5707 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept {
5708 j.m_data.m_value.destroy(j.m_data.m_type);
5709 j.m_data.m_type = value_t::number_unsigned;
5710 j.m_data.m_value = val;
5711 j.assert_invariant();
5712 }
5713 };
5714
5715 template<>
5717 template<typename BasicJsonType>
5718 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept {
5719 j.m_data.m_value.destroy(j.m_data.m_type);
5720 j.m_data.m_type = value_t::number_integer;
5721 j.m_data.m_value = val;
5722 j.assert_invariant();
5723 }
5724 };
5725
5726 template<>
5728 template<typename BasicJsonType>
5729 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) {
5730 j.m_data.m_value.destroy(j.m_data.m_type);
5731 j.m_data.m_type = value_t::array;
5732 j.m_data.m_value = arr;
5733 j.set_parents();
5734 j.assert_invariant();
5735 }
5736
5737 template<typename BasicJsonType>
5738 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) {
5739 j.m_data.m_value.destroy(j.m_data.m_type);
5740 j.m_data.m_type = value_t::array;
5741 j.m_data.m_value = std::move(arr);
5742 j.set_parents();
5743 j.assert_invariant();
5744 }
5745
5746 template < typename BasicJsonType, typename CompatibleArrayType,
5747 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5748 int > = 0 >
5749 static void construct(BasicJsonType& j, const CompatibleArrayType& arr) {
5750 using std::begin;
5751 using std::end;
5752
5753 j.m_data.m_value.destroy(j.m_data.m_type);
5754 j.m_data.m_type = value_t::array;
5755 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5756 j.set_parents();
5757 j.assert_invariant();
5758 }
5759
5760 template<typename BasicJsonType>
5761 static void construct(BasicJsonType& j, const std::vector<bool>& arr) {
5762 j.m_data.m_value.destroy(j.m_data.m_type);
5763 j.m_data.m_type = value_t::array;
5764 j.m_data.m_value = value_t::array;
5765 j.m_data.m_value.array->reserve(arr.size());
5766 for (const bool x : arr) {
5767 j.m_data.m_value.array->push_back(x);
5768 j.set_parent(j.m_data.m_value.array->back());
5769 }
5770 j.assert_invariant();
5771 }
5772
5773 template<typename BasicJsonType, typename T,
5774 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5775 static void construct(BasicJsonType& j, const std::valarray<T>& arr) {
5776 j.m_data.m_value.destroy(j.m_data.m_type);
5777 j.m_data.m_type = value_t::array;
5778 j.m_data.m_value = value_t::array;
5779 j.m_data.m_value.array->resize(arr.size());
5780 if (arr.size() > 0) {
5781 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5782 }
5783 j.set_parents();
5784 j.assert_invariant();
5785 }
5786 };
5787
5788 template<>
5790 template<typename BasicJsonType>
5791 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) {
5792 j.m_data.m_value.destroy(j.m_data.m_type);
5793 j.m_data.m_type = value_t::object;
5794 j.m_data.m_value = obj;
5795 j.set_parents();
5796 j.assert_invariant();
5797 }
5798
5799 template<typename BasicJsonType>
5800 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) {
5801 j.m_data.m_value.destroy(j.m_data.m_type);
5802 j.m_data.m_type = value_t::object;
5803 j.m_data.m_value = std::move(obj);
5804 j.set_parents();
5805 j.assert_invariant();
5806 }
5807
5808 template < typename BasicJsonType, typename CompatibleObjectType,
5809 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5810 static void construct(BasicJsonType& j, const CompatibleObjectType& obj) {
5811 using std::begin;
5812 using std::end;
5813
5814 j.m_data.m_value.destroy(j.m_data.m_type);
5815 j.m_data.m_type = value_t::object;
5816 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5817 j.set_parents();
5818 j.assert_invariant();
5819 }
5820 };
5821
5823 // to_json //
5825
5826#ifdef JSON_HAS_CPP_17
5827 template<typename BasicJsonType, typename T,
5828 enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
5829 void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept {
5830 if (opt.has_value()) {
5831 j = *opt;
5832 }
5833 else {
5834 j = nullptr;
5835 }
5836 }
5837#endif
5838
5839 template<typename BasicJsonType, typename T,
5840 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5841 inline void to_json(BasicJsonType& j, T b) noexcept {
5843 }
5844
5845 template < typename BasicJsonType, typename BoolRef,
5846 enable_if_t <
5847 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5848 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5849 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5850 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5851 typename BasicJsonType::boolean_t >::value))
5852 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5853 inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept {
5854 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5855 }
5856
5857 template<typename BasicJsonType, typename CompatibleString,
5858 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5859 inline void to_json(BasicJsonType& j, const CompatibleString& s) {
5861 }
5862
5863 template<typename BasicJsonType>
5864 inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) {
5866 }
5867
5868 template<typename BasicJsonType, typename FloatType,
5869 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5870 inline void to_json(BasicJsonType& j, FloatType val) noexcept {
5871 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5872 }
5873
5874 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5875 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5876 inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept {
5877 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5878 }
5879
5880 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5881 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5882 inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept {
5883 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5884 }
5885
5886#if !JSON_DISABLE_ENUM_SERIALIZATION
5887 template<typename BasicJsonType, typename EnumType,
5888 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5889 inline void to_json(BasicJsonType& j, EnumType e) noexcept {
5890 using underlying_type = typename std::underlying_type<EnumType>::type;
5891 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
5892 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
5893 }
5894#endif // JSON_DISABLE_ENUM_SERIALIZATION
5895
5896 template<typename BasicJsonType>
5897 inline void to_json(BasicJsonType& j, const std::vector<bool>& e) {
5899 }
5900
5901 template < typename BasicJsonType, typename CompatibleArrayType,
5902 enable_if_t < is_compatible_array_type<BasicJsonType,
5903 CompatibleArrayType>::value &&
5905 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value &&
5906 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value &&
5908 int > = 0 >
5909 inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr) {
5911 }
5912
5913 template<typename BasicJsonType>
5914 inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) {
5916 }
5917
5918 template<typename BasicJsonType, typename T,
5919 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5920 inline void to_json(BasicJsonType& j, const std::valarray<T>& arr) {
5922 }
5923
5924 template<typename BasicJsonType>
5925 inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) {
5927 }
5928
5929 template < typename BasicJsonType, typename CompatibleObjectType,
5930 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value && !is_basic_json<CompatibleObjectType>::value, int > = 0 >
5931 inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) {
5933 }
5934
5935 template<typename BasicJsonType>
5936 inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) {
5938 }
5939
5940 template <
5941 typename BasicJsonType, typename T, std::size_t N,
5942 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
5943 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5944 int > = 0 >
5945 inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5946 {
5948 }
5949
5950 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
5951 inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p) {
5952 j = { p.first, p.second };
5953 }
5954
5955 // for https://github.com/nlohmann/json/pull/1134
5956 template<typename BasicJsonType, typename T,
5957 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
5958 inline void to_json(BasicJsonType& j, const T& b) {
5959 j = { {b.key(), b.value()} };
5960 }
5961
5962 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
5963 inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/) {
5964 j = { std::get<Idx>(t)... };
5965 }
5966
5967 template<typename BasicJsonType, typename Tuple>
5968 inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& /*unused*/, index_sequence<> /*unused*/) {
5969 using array_t = typename BasicJsonType::array_t;
5970 j = array_t();
5971 }
5972
5973 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
5974 inline void to_json(BasicJsonType& j, const T& t) {
5975 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5976 }
5977
5978#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5979#if defined(__cpp_lib_char8_t)
5980 template<typename BasicJsonType, typename Tr, typename Allocator>
5981 inline void to_json(BasicJsonType& j, const std::basic_string<char8_t, Tr, Allocator>& s) {
5982 using OtherAllocator = typename std::allocator_traits<Allocator>::template rebind_alloc<char>;
5983 j = std::basic_string<char, std::char_traits<char>, OtherAllocator>(s.begin(), s.end(), s.get_allocator());
5984 }
5985#endif
5986
5987 template<typename BasicJsonType>
5988 inline void to_json(BasicJsonType& j, const std_fs::path& p) {
5989 // Returns either a std::string or a std::u8string depending whether library
5990 // support for char8_t is enabled.
5991 j = p.u8string();
5992 }
5993#endif
5994
5995 struct to_json_fn {
5996 template<typename BasicJsonType, typename T>
5997 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
5998 -> decltype(to_json(j, std::forward<T>(val)), void()) {
5999 return to_json(j, std::forward<T>(val));
6000 }
6001 };
6002} // namespace detail
6003
6004#ifndef JSON_HAS_CPP_17
6008namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
6009{
6010#endif
6011 JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
6012 detail::static_const<detail::to_json_fn>::value;
6013#ifndef JSON_HAS_CPP_17
6014} // namespace
6015#endif
6016
6017NLOHMANN_JSON_NAMESPACE_END
6018
6019// #include <nlohmann/detail/meta/identity_tag.hpp>
6020
6021
6022NLOHMANN_JSON_NAMESPACE_BEGIN
6023
6025template<typename ValueType, typename>
6029 template<typename BasicJsonType, typename TargetType = ValueType>
6030 static auto from_json(BasicJsonType&& j, TargetType& val) noexcept(
6031 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
6032 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void()) {
6033 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
6034 }
6035
6038 template<typename BasicJsonType, typename TargetType = ValueType>
6039 static auto from_json(BasicJsonType&& j) noexcept(
6040 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
6041 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})) {
6042 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
6043 }
6044
6047 template<typename BasicJsonType, typename TargetType = ValueType>
6048 static auto to_json(BasicJsonType& j, TargetType&& val) noexcept(
6049 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
6050 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void()) {
6051 ::nlohmann::to_json(j, std::forward<TargetType>(val));
6052 }
6053};
6054
6055NLOHMANN_JSON_NAMESPACE_END
6056
6057// #include <nlohmann/byte_container_with_subtype.hpp>
6058// __ _____ _____ _____
6059// __| | __| | | | JSON for Modern C++
6060// | | |__ | | | | | | version 3.12.0
6061// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6062//
6063// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
6064// SPDX-License-Identifier: MIT
6065
6066
6067
6068#include <cstdint> // uint8_t, uint64_t
6069#include <tuple> // tie
6070#include <utility> // move
6071
6072// #include <nlohmann/detail/abi_macros.hpp>
6073
6074
6075NLOHMANN_JSON_NAMESPACE_BEGIN
6076
6079template<typename BinaryType>
6080class byte_container_with_subtype : public BinaryType {
6081public:
6082 using container_type = BinaryType;
6083 using subtype_type = std::uint64_t;
6084
6086 byte_container_with_subtype() noexcept(noexcept(container_type()))
6087 : container_type() {}
6088
6090 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
6091 : container_type(b) {}
6092
6094 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
6095 : container_type(std::move(b)) {}
6096
6098 byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
6099 : container_type(b)
6100 , m_subtype(subtype_)
6101 , m_has_subtype(true) {}
6102
6104 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
6105 : container_type(std::move(b))
6106 , m_subtype(subtype_)
6107 , m_has_subtype(true) {}
6108
6109 bool operator==(const byte_container_with_subtype& rhs) const {
6110 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
6111 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
6112 }
6113
6114 bool operator!=(const byte_container_with_subtype& rhs) const {
6115 return !(rhs == *this);
6116 }
6117
6120 void set_subtype(subtype_type subtype_) noexcept {
6121 m_subtype = subtype_;
6122 m_has_subtype = true;
6123 }
6124
6127 constexpr subtype_type subtype() const noexcept {
6128 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
6129 }
6130
6133 constexpr bool has_subtype() const noexcept {
6134 return m_has_subtype;
6135 }
6136
6139 void clear_subtype() noexcept {
6140 m_subtype = 0;
6141 m_has_subtype = false;
6142 }
6143
6144private:
6145 subtype_type m_subtype = 0;
6146 bool m_has_subtype = false;
6147};
6148
6149NLOHMANN_JSON_NAMESPACE_END
6150
6151// #include <nlohmann/detail/conversions/from_json.hpp>
6152
6153// #include <nlohmann/detail/conversions/to_json.hpp>
6154
6155// #include <nlohmann/detail/exceptions.hpp>
6156
6157// #include <nlohmann/detail/hash.hpp>
6158// __ _____ _____ _____
6159// __| | __| | | | JSON for Modern C++
6160// | | |__ | | | | | | version 3.12.0
6161// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6162//
6163// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
6164// SPDX-License-Identifier: MIT
6165
6166
6167
6168#include <cstdint> // uint8_t
6169#include <cstddef> // size_t
6170#include <functional> // hash
6171
6172// #include <nlohmann/detail/abi_macros.hpp>
6173
6174// #include <nlohmann/detail/value_t.hpp>
6175
6176
6177NLOHMANN_JSON_NAMESPACE_BEGIN
6178namespace detail {
6179
6180 // boost::hash_combine
6181 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept {
6182 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6183 return seed;
6184 }
6185
6197 template<typename BasicJsonType>
6198 std::size_t hash(const BasicJsonType& j) {
6199 using string_t = typename BasicJsonType::string_t;
6200 using number_integer_t = typename BasicJsonType::number_integer_t;
6201 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6202 using number_float_t = typename BasicJsonType::number_float_t;
6203
6204 const auto type = static_cast<std::size_t>(j.type());
6205 switch (j.type()) {
6206 case BasicJsonType::value_t::null:
6207 case BasicJsonType::value_t::discarded:
6208 {
6209 return combine(type, 0);
6210 }
6211
6212 case BasicJsonType::value_t::object:
6213 {
6214 auto seed = combine(type, j.size());
6215 for (const auto& element : j.items()) {
6216 const auto h = std::hash<string_t>{}(element.key());
6217 seed = combine(seed, h);
6218 seed = combine(seed, hash(element.value()));
6219 }
6220 return seed;
6221 }
6222
6223 case BasicJsonType::value_t::array:
6224 {
6225 auto seed = combine(type, j.size());
6226 for (const auto& element : j) {
6227 seed = combine(seed, hash(element));
6228 }
6229 return seed;
6230 }
6231
6232 case BasicJsonType::value_t::string:
6233 {
6234 const auto h = std::hash<string_t>{}(j.template get_ref<const string_t&>());
6235 return combine(type, h);
6236 }
6237
6238 case BasicJsonType::value_t::boolean:
6239 {
6240 const auto h = std::hash<bool>{}(j.template get<bool>());
6241 return combine(type, h);
6242 }
6243
6244 case BasicJsonType::value_t::number_integer:
6245 {
6246 const auto h = std::hash<number_integer_t>{}(j.template get<number_integer_t>());
6247 return combine(type, h);
6248 }
6249
6250 case BasicJsonType::value_t::number_unsigned:
6251 {
6252 const auto h = std::hash<number_unsigned_t>{}(j.template get<number_unsigned_t>());
6253 return combine(type, h);
6254 }
6255
6256 case BasicJsonType::value_t::number_float:
6257 {
6258 const auto h = std::hash<number_float_t>{}(j.template get<number_float_t>());
6259 return combine(type, h);
6260 }
6261
6262 case BasicJsonType::value_t::binary:
6263 {
6264 auto seed = combine(type, j.get_binary().size());
6265 const auto h = std::hash<bool>{}(j.get_binary().has_subtype());
6266 seed = combine(seed, h);
6267 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6268 for (const auto byte : j.get_binary()) {
6269 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6270 }
6271 return seed;
6272 }
6273
6274 default: // LCOV_EXCL_LINE
6275 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6276 return 0; // LCOV_EXCL_LINE
6277 }
6278 }
6279
6280} // namespace detail
6281NLOHMANN_JSON_NAMESPACE_END
6282
6283// #include <nlohmann/detail/input/binary_reader.hpp>
6284// __ _____ _____ _____
6285// __| | __| | | | JSON for Modern C++
6286// | | |__ | | | | | | version 3.12.0
6287// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6288//
6289// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
6290// SPDX-License-Identifier: MIT
6291
6292
6293
6294#include <algorithm> // generate_n
6295#include <array> // array
6296#include <cmath> // ldexp
6297#include <cstddef> // size_t
6298#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6299#include <cstdio> // snprintf
6300#include <cstring> // memcpy
6301#include <iterator> // back_inserter
6302#include <limits> // numeric_limits
6303#include <string> // char_traits, string
6304#include <utility> // make_pair, move
6305#include <vector> // vector
6306#ifdef __cpp_lib_byteswap
6307#include <bit> //byteswap
6308#endif
6309
6310// #include <nlohmann/detail/exceptions.hpp>
6311
6312// #include <nlohmann/detail/input/input_adapters.hpp>
6313// __ _____ _____ _____
6314// __| | __| | | | JSON for Modern C++
6315// | | |__ | | | | | | version 3.12.0
6316// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6317//
6318// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
6319// SPDX-License-Identifier: MIT
6320
6321
6322
6323#include <array> // array
6324#include <cstddef> // size_t
6325#include <cstring> // strlen
6326#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6327#include <memory> // shared_ptr, make_shared, addressof
6328#include <numeric> // accumulate
6329#include <streambuf> // streambuf
6330#include <string> // string, char_traits
6331#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6332#include <utility> // pair, declval
6333
6334#ifndef JSON_NO_IO
6335#include <cstdio> // FILE *
6336#include <istream> // istream
6337#endif // JSON_NO_IO
6338
6339// #include <nlohmann/detail/exceptions.hpp>
6340
6341// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6342
6343// #include <nlohmann/detail/macro_scope.hpp>
6344
6345// #include <nlohmann/detail/meta/type_traits.hpp>
6346
6347
6348NLOHMANN_JSON_NAMESPACE_BEGIN
6349namespace detail {
6350
6352 enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
6353
6355 // input adapters //
6357
6358#ifndef JSON_NO_IO
6363 class file_input_adapter {
6364 public:
6365 using char_type = char;
6366
6367 JSON_HEDLEY_NON_NULL(2)
6368 explicit file_input_adapter(std::FILE* f) noexcept
6369 : m_file(f) {
6370 JSON_ASSERT(m_file != nullptr);
6371 }
6372
6373 // make class move-only
6374 file_input_adapter(const file_input_adapter&) = delete;
6375 file_input_adapter(file_input_adapter&&) noexcept = default;
6376 file_input_adapter& operator=(const file_input_adapter&) = delete;
6377 file_input_adapter& operator=(file_input_adapter&&) = delete;
6378 ~file_input_adapter() = default;
6379
6380 std::char_traits<char>::int_type get_character() noexcept {
6381 return std::fgetc(m_file);
6382 }
6383
6384 // returns the number of characters successfully read
6385 template<class T>
6386 std::size_t get_elements(T* dest, std::size_t count = 1) {
6387 return fread(dest, 1, sizeof(T) * count, m_file);
6388 }
6389
6390 private:
6392 std::FILE* m_file;
6393 };
6394
6404 class input_stream_adapter {
6405 public:
6406 using char_type = char;
6407
6408 ~input_stream_adapter() {
6409 // clear stream flags; we use underlying streambuf I/O, do not
6410 // maintain ifstream flags, except eof
6411 if (is != nullptr) {
6412 is->clear(is->rdstate() & std::ios::eofbit);
6413 }
6414 }
6415
6416 explicit input_stream_adapter(std::istream& i)
6417 : is(&i), sb(i.rdbuf()) {}
6418
6419 // deleted because of pointer members
6420 input_stream_adapter(const input_stream_adapter&) = delete;
6421 input_stream_adapter& operator=(input_stream_adapter&) = delete;
6422 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
6423
6424 input_stream_adapter(input_stream_adapter&& rhs) noexcept
6425 : is(rhs.is), sb(rhs.sb) {
6426 rhs.is = nullptr;
6427 rhs.sb = nullptr;
6428 }
6429
6430 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6431 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6432 // end up as the same value, e.g., 0xFFFFFFFF.
6433 std::char_traits<char>::int_type get_character() {
6434 auto res = sb->sbumpc();
6435 // set eof manually, as we don't use the istream interface.
6436 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof())) {
6437 is->clear(is->rdstate() | std::ios::eofbit);
6438 }
6439 return res;
6440 }
6441
6442 template<class T>
6443 std::size_t get_elements(T* dest, std::size_t count = 1) {
6444 auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
6445 if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T))) {
6446 is->clear(is->rdstate() | std::ios::eofbit);
6447 }
6448 return res;
6449 }
6450
6451 private:
6453 std::istream* is = nullptr;
6454 std::streambuf* sb = nullptr;
6455 };
6456#endif // JSON_NO_IO
6457
6458 // General-purpose iterator-based adapter. It might not be as fast as
6459 // theoretically possible for some containers, but it is extremely versatile.
6460 template<typename IteratorType>
6461 class iterator_input_adapter {
6462 public:
6463 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6464
6465 iterator_input_adapter(IteratorType first, IteratorType last)
6466 : current(std::move(first)), end(std::move(last)) {}
6467
6468 typename char_traits<char_type>::int_type get_character() {
6469 if (JSON_HEDLEY_LIKELY(current != end)) {
6470 auto result = char_traits<char_type>::to_int_type(*current);
6471 std::advance(current, 1);
6472 return result;
6473 }
6474
6476 }
6477
6478 // for general iterators, we cannot really do something better than falling back to processing the range one-by-one
6479 template<class T>
6480 std::size_t get_elements(T* dest, std::size_t count = 1) {
6481 auto* ptr = reinterpret_cast<char*>(dest);
6482 for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index) {
6483 if (JSON_HEDLEY_LIKELY(current != end)) {
6484 ptr[read_index] = static_cast<char>(*current);
6485 std::advance(current, 1);
6486 }
6487 else {
6488 return read_index;
6489 }
6490 }
6491 return count * sizeof(T);
6492 }
6493
6494 private:
6495 IteratorType current;
6496 IteratorType end;
6497
6498 template<typename BaseInputAdapter, size_t T>
6499 friend struct wide_string_input_helper;
6500
6501 bool empty() const {
6502 return current == end;
6503 }
6504 };
6505
6506 template<typename BaseInputAdapter, size_t T>
6508
6509 template<typename BaseInputAdapter>
6510 struct wide_string_input_helper<BaseInputAdapter, 4> {
6511 // UTF-32
6512 static void fill_buffer(BaseInputAdapter& input,
6513 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6514 size_t& utf8_bytes_index,
6515 size_t& utf8_bytes_filled) {
6516 utf8_bytes_index = 0;
6517
6518 if (JSON_HEDLEY_UNLIKELY(input.empty())) {
6519 utf8_bytes[0] = std::char_traits<char>::eof();
6520 utf8_bytes_filled = 1;
6521 }
6522 else {
6523 // get the current character
6524 const auto wc = input.get_character();
6525
6526 // UTF-32 to UTF-8 encoding
6527 if (wc < 0x80) {
6528 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6529 utf8_bytes_filled = 1;
6530 }
6531 else if (wc <= 0x7FF) {
6532 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6533 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6534 utf8_bytes_filled = 2;
6535 }
6536 else if (wc <= 0xFFFF) {
6537 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6538 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6539 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6540 utf8_bytes_filled = 3;
6541 }
6542 else if (wc <= 0x10FFFF) {
6543 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6544 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6545 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6546 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6547 utf8_bytes_filled = 4;
6548 }
6549 else {
6550 // unknown character
6551 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6552 utf8_bytes_filled = 1;
6553 }
6554 }
6555 }
6556 };
6557
6558 template<typename BaseInputAdapter>
6559 struct wide_string_input_helper<BaseInputAdapter, 2> {
6560 // UTF-16
6561 static void fill_buffer(BaseInputAdapter& input,
6562 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6563 size_t& utf8_bytes_index,
6564 size_t& utf8_bytes_filled) {
6565 utf8_bytes_index = 0;
6566
6567 if (JSON_HEDLEY_UNLIKELY(input.empty())) {
6568 utf8_bytes[0] = std::char_traits<char>::eof();
6569 utf8_bytes_filled = 1;
6570 }
6571 else {
6572 // get the current character
6573 const auto wc = input.get_character();
6574
6575 // UTF-16 to UTF-8 encoding
6576 if (wc < 0x80) {
6577 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6578 utf8_bytes_filled = 1;
6579 }
6580 else if (wc <= 0x7FF) {
6581 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6582 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6583 utf8_bytes_filled = 2;
6584 }
6585 else if (0xD800 > wc || wc >= 0xE000) {
6586 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6587 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6588 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6589 utf8_bytes_filled = 3;
6590 }
6591 else {
6592 if (JSON_HEDLEY_UNLIKELY(!input.empty())) {
6593 const auto wc2 = static_cast<unsigned int>(input.get_character());
6594 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6595 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6596 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6597 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6598 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6599 utf8_bytes_filled = 4;
6600 }
6601 else {
6602 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6603 utf8_bytes_filled = 1;
6604 }
6605 }
6606 }
6607 }
6608 };
6609
6610 // Wraps another input adapter to convert wide character types into individual bytes.
6611 template<typename BaseInputAdapter, typename WideCharType>
6612 class wide_string_input_adapter {
6613 public:
6614 using char_type = char;
6615
6616 wide_string_input_adapter(BaseInputAdapter base)
6617 : base_adapter(base) {}
6618
6619 typename std::char_traits<char>::int_type get_character() noexcept {
6620 // check if the buffer needs to be filled
6621 if (utf8_bytes_index == utf8_bytes_filled) {
6622 fill_buffer<sizeof(WideCharType)>();
6623
6624 JSON_ASSERT(utf8_bytes_filled > 0);
6625 JSON_ASSERT(utf8_bytes_index == 0);
6626 }
6627
6628 // use buffer
6629 JSON_ASSERT(utf8_bytes_filled > 0);
6630 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6631 return utf8_bytes[utf8_bytes_index++];
6632 }
6633
6634 // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
6635 template<class T>
6636 std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1) {
6637 JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
6638 }
6639
6640 private:
6641 BaseInputAdapter base_adapter;
6642
6643 template<size_t T>
6644 void fill_buffer() {
6645 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6646 }
6647
6649 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = { {0, 0, 0, 0} };
6650
6652 std::size_t utf8_bytes_index = 0;
6654 std::size_t utf8_bytes_filled = 0;
6655 };
6656
6657 template<typename IteratorType, typename Enable = void>
6659 using iterator_type = IteratorType;
6660 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6661 using adapter_type = iterator_input_adapter<iterator_type>;
6662
6663 static adapter_type create(IteratorType first, IteratorType last) {
6664 return adapter_type(std::move(first), std::move(last));
6665 }
6666 };
6667
6668 template<typename T>
6670 using value_type = typename std::iterator_traits<T>::value_type;
6671 enum // NOLINT(cppcoreguidelines-use-enum-class)
6672 {
6673 value = sizeof(value_type) > 1
6674 };
6675 };
6676
6677 template<typename IteratorType>
6678 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>> {
6679 using iterator_type = IteratorType;
6680 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6681 using base_adapter_type = iterator_input_adapter<iterator_type>;
6683
6684 static adapter_type create(IteratorType first, IteratorType last) {
6685 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6686 }
6687 };
6688
6689 // General purpose iterator-based input
6690 template<typename IteratorType>
6691 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last) {
6693 return factory_type::create(first, last);
6694 }
6695
6696 // Convenience shorthand from container to iterator
6697 // Enables ADL on begin(container) and end(container)
6698 // Encloses the using declarations in namespace for not to leak them to outside scope
6699
6700 namespace container_input_adapter_factory_impl {
6701
6702 using std::begin;
6703 using std::end;
6704
6705 template<typename ContainerType, typename Enable = void>
6707
6708 template<typename ContainerType>
6709 struct container_input_adapter_factory< ContainerType,
6710 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6711 {
6712 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6713
6714 static adapter_type create(const ContainerType& container) {
6715 return input_adapter(begin(container), end(container));
6716 }
6717 };
6718
6719 } // namespace container_input_adapter_factory_impl
6720
6721 template<typename ContainerType>
6724 }
6725
6726 // specialization for std::string
6727 using string_input_adapter_type = decltype(input_adapter(std::declval<std::string>()));
6728
6729#ifndef JSON_NO_IO
6730 // Special cases with fast paths
6731 inline file_input_adapter input_adapter(std::FILE* file) {
6732 if (file == nullptr) {
6733 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));
6734 }
6735 return file_input_adapter(file);
6736 }
6737
6738 inline input_stream_adapter input_adapter(std::istream& stream) {
6739 return input_stream_adapter(stream);
6740 }
6741
6742 inline input_stream_adapter input_adapter(std::istream&& stream) {
6743 return input_stream_adapter(stream);
6744 }
6745#endif // JSON_NO_IO
6746
6747 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6748
6749 // Null-delimited strings, and the like.
6750 template < typename CharT,
6751 typename std::enable_if <
6752 std::is_pointer<CharT>::value &&
6753 !std::is_array<CharT>::value&&
6754 std::is_integral<typename std::remove_pointer<CharT>::type>::value &&
6755 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6756 int >::type = 0 >
6757 contiguous_bytes_input_adapter input_adapter(CharT b) {
6758 if (b == nullptr) {
6759 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));
6760 }
6761 auto length = std::strlen(reinterpret_cast<const char*>(b));
6762 const auto* ptr = reinterpret_cast<const char*>(b);
6763 return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck]
6764 }
6765
6766 template<typename T, std::size_t N>
6767 auto input_adapter(T(&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6768 {
6769 return input_adapter(array, array + N);
6770 }
6771
6772 // This class only handles inputs of input_buffer_adapter type.
6773 // It's required so that expressions like {ptr, len} can be implicitly cast
6774 // to the correct adapter.
6775 class span_input_adapter {
6776 public:
6777 template < typename CharT,
6778 typename std::enable_if <
6779 std::is_pointer<CharT>::value&&
6780 std::is_integral<typename std::remove_pointer<CharT>::type>::value &&
6781 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6782 int >::type = 0 >
6783 span_input_adapter(CharT b, std::size_t l)
6784 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6785
6786 template<class IteratorType,
6787 typename std::enable_if<
6788 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6789 int>::type = 0>
6790 span_input_adapter(IteratorType first, IteratorType last)
6791 : ia(input_adapter(first, last)) {}
6792
6793 contiguous_bytes_input_adapter&& get() {
6794 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6795 }
6796
6797 private:
6798 contiguous_bytes_input_adapter ia;
6799 };
6800
6801} // namespace detail
6802NLOHMANN_JSON_NAMESPACE_END
6803
6804// #include <nlohmann/detail/input/json_sax.hpp>
6805// __ _____ _____ _____
6806// __| | __| | | | JSON for Modern C++
6807// | | |__ | | | | | | version 3.12.0
6808// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6809//
6810// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
6811// SPDX-License-Identifier: MIT
6812
6813
6814
6815#include <cstddef>
6816#include <string> // string
6817#include <type_traits> // enable_if_t
6818#include <utility> // move
6819#include <vector> // vector
6820
6821// #include <nlohmann/detail/exceptions.hpp>
6822
6823// #include <nlohmann/detail/input/lexer.hpp>
6824// __ _____ _____ _____
6825// __| | __| | | | JSON for Modern C++
6826// | | |__ | | | | | | version 3.12.0
6827// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6828//
6829// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
6830// SPDX-License-Identifier: MIT
6831
6832
6833
6834#include <array> // array
6835#include <clocale> // localeconv
6836#include <cstddef> // size_t
6837#include <cstdio> // snprintf
6838#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
6839#include <initializer_list> // initializer_list
6840#include <string> // char_traits, string
6841#include <utility> // move
6842#include <vector> // vector
6843
6844// #include <nlohmann/detail/input/input_adapters.hpp>
6845
6846// #include <nlohmann/detail/input/position_t.hpp>
6847
6848// #include <nlohmann/detail/macro_scope.hpp>
6849
6850// #include <nlohmann/detail/meta/type_traits.hpp>
6851
6852
6853NLOHMANN_JSON_NAMESPACE_BEGIN
6854namespace detail {
6855
6857 // lexer //
6859
6860 template<typename BasicJsonType>
6862 public:
6883
6885 JSON_HEDLEY_RETURNS_NON_NULL
6886 JSON_HEDLEY_CONST
6887 static const char* token_type_name(const token_type t) noexcept {
6888 switch (t) {
6890 return "<uninitialized>";
6892 return "true literal";
6894 return "false literal";
6896 return "null literal";
6898 return "string literal";
6902 return "number literal";
6904 return "'['";
6906 return "'{'";
6908 return "']'";
6910 return "'}'";
6912 return "':'";
6914 return "','";
6916 return "<parse error>";
6918 return "end of input";
6920 return "'[', '{', or a literal";
6921 // LCOV_EXCL_START
6922 default: // catch non-enum values
6923 return "unknown token";
6924 // LCOV_EXCL_STOP
6925 }
6926 }
6927 };
6928
6933 template<typename BasicJsonType, typename InputAdapterType>
6934 class lexer : public lexer_base<BasicJsonType> {
6935 using number_integer_t = typename BasicJsonType::number_integer_t;
6936 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6937 using number_float_t = typename BasicJsonType::number_float_t;
6938 using string_t = typename BasicJsonType::string_t;
6939 using char_type = typename InputAdapterType::char_type;
6940 using char_int_type = typename char_traits<char_type>::int_type;
6941
6942 public:
6943 using token_type = typename lexer_base<BasicJsonType>::token_type;
6944
6945 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
6946 : ia(std::move(adapter))
6947 , ignore_comments(ignore_comments_)
6948 , decimal_point_char(static_cast<char_int_type>(get_decimal_point())) {}
6949
6950 // deleted because of pointer members
6951 lexer(const lexer&) = delete;
6952 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6953 lexer& operator=(lexer&) = delete;
6954 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6955 ~lexer() = default;
6956
6957 private:
6959 // locales
6961
6963 JSON_HEDLEY_PURE
6964 static char get_decimal_point() noexcept {
6965 const auto* loc = localeconv();
6966 JSON_ASSERT(loc != nullptr);
6967 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
6968 }
6969
6971 // scan functions
6973
6989 int get_codepoint() {
6990 // this function only makes sense after reading `\u`
6991 JSON_ASSERT(current == 'u');
6992 int codepoint = 0;
6993
6994 const auto factors = { 12u, 8u, 4u, 0u };
6995 for (const auto factor : factors) {
6996 get();
6997
6998 if (current >= '0' && current <= '9') {
6999 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7000 }
7001 else if (current >= 'A' && current <= 'F') {
7002 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7003 }
7004 else if (current >= 'a' && current <= 'f') {
7005 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7006 }
7007 else {
7008 return -1;
7009 }
7010 }
7011
7012 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7013 return codepoint;
7014 }
7015
7031 bool next_byte_in_range(std::initializer_list<char_int_type> ranges) {
7032 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7033 add(current);
7034
7035 for (auto range = ranges.begin(); range != ranges.end(); ++range) {
7036 get();
7037 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7038 {
7039 add(current);
7040 }
7041 else {
7042 error_message = "invalid string: ill-formed UTF-8 byte";
7043 return false;
7044 }
7045 }
7046
7047 return true;
7048 }
7049
7065 token_type scan_string() {
7066 // reset token_buffer (ignore opening quote)
7067 reset();
7068
7069 // we entered the function by reading an open quote
7070 JSON_ASSERT(current == '\"');
7071
7072 while (true) {
7073 // get the next character
7074 switch (get()) {
7075 // end of file while parsing the string
7077 {
7078 error_message = "invalid string: missing closing quote";
7079 return token_type::parse_error;
7080 }
7081
7082 // closing quote
7083 case '\"':
7084 {
7085 return token_type::value_string;
7086 }
7087
7088 // escapes
7089 case '\\':
7090 {
7091 switch (get()) {
7092 // quotation mark
7093 case '\"':
7094 add('\"');
7095 break;
7096 // reverse solidus
7097 case '\\':
7098 add('\\');
7099 break;
7100 // solidus
7101 case '/':
7102 add('/');
7103 break;
7104 // backspace
7105 case 'b':
7106 add('\b');
7107 break;
7108 // form feed
7109 case 'f':
7110 add('\f');
7111 break;
7112 // line feed
7113 case 'n':
7114 add('\n');
7115 break;
7116 // carriage return
7117 case 'r':
7118 add('\r');
7119 break;
7120 // tab
7121 case 't':
7122 add('\t');
7123 break;
7124
7125 // unicode escapes
7126 case 'u':
7127 {
7128 const int codepoint1 = get_codepoint();
7129 int codepoint = codepoint1; // start with codepoint1
7130
7131 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) {
7132 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7133 return token_type::parse_error;
7134 }
7135
7136 // check if code point is a high surrogate
7137 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) {
7138 // expect next \uxxxx entry
7139 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) {
7140 const int codepoint2 = get_codepoint();
7141
7142 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) {
7143 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7144 return token_type::parse_error;
7145 }
7146
7147 // check if codepoint2 is a low surrogate
7148 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) {
7149 // overwrite codepoint
7150 codepoint = static_cast<int>(
7151 // high surrogate occupies the most significant 22 bits
7152 (static_cast<unsigned int>(codepoint1) << 10u)
7153 // low surrogate occupies the least significant 15 bits
7154 + static_cast<unsigned int>(codepoint2)
7155 // there is still the 0xD800, 0xDC00, and 0x10000 noise
7156 // in the result, so we have to subtract with:
7157 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7158 -0x35FDC00u);
7159 }
7160 else {
7161 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7162 return token_type::parse_error;
7163 }
7164 }
7165 else {
7166 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7167 return token_type::parse_error;
7168 }
7169 }
7170 else {
7171 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) {
7172 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7173 return token_type::parse_error;
7174 }
7175 }
7176
7177 // the result of the above calculation yields a proper codepoint
7178 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7179
7180 // translate codepoint into bytes
7181 if (codepoint < 0x80) {
7182 // 1-byte characters: 0xxxxxxx (ASCII)
7183 add(static_cast<char_int_type>(codepoint));
7184 }
7185 else if (codepoint <= 0x7FF) {
7186 // 2-byte characters: 110xxxxx 10xxxxxx
7187 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7188 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7189 }
7190 else if (codepoint <= 0xFFFF) {
7191 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7192 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7193 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7194 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7195 }
7196 else {
7197 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7198 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7199 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7200 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7201 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7202 }
7203
7204 break;
7205 }
7206
7207 // other characters after escape
7208 default:
7209 error_message = "invalid string: forbidden character after backslash";
7210 return token_type::parse_error;
7211 }
7212
7213 break;
7214 }
7215
7216 // invalid control characters
7217 case 0x00:
7218 {
7219 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7220 return token_type::parse_error;
7221 }
7222
7223 case 0x01:
7224 {
7225 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7226 return token_type::parse_error;
7227 }
7228
7229 case 0x02:
7230 {
7231 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7232 return token_type::parse_error;
7233 }
7234
7235 case 0x03:
7236 {
7237 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7238 return token_type::parse_error;
7239 }
7240
7241 case 0x04:
7242 {
7243 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7244 return token_type::parse_error;
7245 }
7246
7247 case 0x05:
7248 {
7249 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7250 return token_type::parse_error;
7251 }
7252
7253 case 0x06:
7254 {
7255 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7256 return token_type::parse_error;
7257 }
7258
7259 case 0x07:
7260 {
7261 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7262 return token_type::parse_error;
7263 }
7264
7265 case 0x08:
7266 {
7267 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7268 return token_type::parse_error;
7269 }
7270
7271 case 0x09:
7272 {
7273 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7274 return token_type::parse_error;
7275 }
7276
7277 case 0x0A:
7278 {
7279 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7280 return token_type::parse_error;
7281 }
7282
7283 case 0x0B:
7284 {
7285 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7286 return token_type::parse_error;
7287 }
7288
7289 case 0x0C:
7290 {
7291 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7292 return token_type::parse_error;
7293 }
7294
7295 case 0x0D:
7296 {
7297 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7298 return token_type::parse_error;
7299 }
7300
7301 case 0x0E:
7302 {
7303 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7304 return token_type::parse_error;
7305 }
7306
7307 case 0x0F:
7308 {
7309 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7310 return token_type::parse_error;
7311 }
7312
7313 case 0x10:
7314 {
7315 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7316 return token_type::parse_error;
7317 }
7318
7319 case 0x11:
7320 {
7321 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7322 return token_type::parse_error;
7323 }
7324
7325 case 0x12:
7326 {
7327 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7328 return token_type::parse_error;
7329 }
7330
7331 case 0x13:
7332 {
7333 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7334 return token_type::parse_error;
7335 }
7336
7337 case 0x14:
7338 {
7339 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7340 return token_type::parse_error;
7341 }
7342
7343 case 0x15:
7344 {
7345 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7346 return token_type::parse_error;
7347 }
7348
7349 case 0x16:
7350 {
7351 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7352 return token_type::parse_error;
7353 }
7354
7355 case 0x17:
7356 {
7357 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7358 return token_type::parse_error;
7359 }
7360
7361 case 0x18:
7362 {
7363 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7364 return token_type::parse_error;
7365 }
7366
7367 case 0x19:
7368 {
7369 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7370 return token_type::parse_error;
7371 }
7372
7373 case 0x1A:
7374 {
7375 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7376 return token_type::parse_error;
7377 }
7378
7379 case 0x1B:
7380 {
7381 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7382 return token_type::parse_error;
7383 }
7384
7385 case 0x1C:
7386 {
7387 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7388 return token_type::parse_error;
7389 }
7390
7391 case 0x1D:
7392 {
7393 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7394 return token_type::parse_error;
7395 }
7396
7397 case 0x1E:
7398 {
7399 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7400 return token_type::parse_error;
7401 }
7402
7403 case 0x1F:
7404 {
7405 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7406 return token_type::parse_error;
7407 }
7408
7409 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7410 case 0x20:
7411 case 0x21:
7412 case 0x23:
7413 case 0x24:
7414 case 0x25:
7415 case 0x26:
7416 case 0x27:
7417 case 0x28:
7418 case 0x29:
7419 case 0x2A:
7420 case 0x2B:
7421 case 0x2C:
7422 case 0x2D:
7423 case 0x2E:
7424 case 0x2F:
7425 case 0x30:
7426 case 0x31:
7427 case 0x32:
7428 case 0x33:
7429 case 0x34:
7430 case 0x35:
7431 case 0x36:
7432 case 0x37:
7433 case 0x38:
7434 case 0x39:
7435 case 0x3A:
7436 case 0x3B:
7437 case 0x3C:
7438 case 0x3D:
7439 case 0x3E:
7440 case 0x3F:
7441 case 0x40:
7442 case 0x41:
7443 case 0x42:
7444 case 0x43:
7445 case 0x44:
7446 case 0x45:
7447 case 0x46:
7448 case 0x47:
7449 case 0x48:
7450 case 0x49:
7451 case 0x4A:
7452 case 0x4B:
7453 case 0x4C:
7454 case 0x4D:
7455 case 0x4E:
7456 case 0x4F:
7457 case 0x50:
7458 case 0x51:
7459 case 0x52:
7460 case 0x53:
7461 case 0x54:
7462 case 0x55:
7463 case 0x56:
7464 case 0x57:
7465 case 0x58:
7466 case 0x59:
7467 case 0x5A:
7468 case 0x5B:
7469 case 0x5D:
7470 case 0x5E:
7471 case 0x5F:
7472 case 0x60:
7473 case 0x61:
7474 case 0x62:
7475 case 0x63:
7476 case 0x64:
7477 case 0x65:
7478 case 0x66:
7479 case 0x67:
7480 case 0x68:
7481 case 0x69:
7482 case 0x6A:
7483 case 0x6B:
7484 case 0x6C:
7485 case 0x6D:
7486 case 0x6E:
7487 case 0x6F:
7488 case 0x70:
7489 case 0x71:
7490 case 0x72:
7491 case 0x73:
7492 case 0x74:
7493 case 0x75:
7494 case 0x76:
7495 case 0x77:
7496 case 0x78:
7497 case 0x79:
7498 case 0x7A:
7499 case 0x7B:
7500 case 0x7C:
7501 case 0x7D:
7502 case 0x7E:
7503 case 0x7F:
7504 {
7505 add(current);
7506 break;
7507 }
7508
7509 // U+0080..U+07FF: bytes C2..DF 80..BF
7510 case 0xC2:
7511 case 0xC3:
7512 case 0xC4:
7513 case 0xC5:
7514 case 0xC6:
7515 case 0xC7:
7516 case 0xC8:
7517 case 0xC9:
7518 case 0xCA:
7519 case 0xCB:
7520 case 0xCC:
7521 case 0xCD:
7522 case 0xCE:
7523 case 0xCF:
7524 case 0xD0:
7525 case 0xD1:
7526 case 0xD2:
7527 case 0xD3:
7528 case 0xD4:
7529 case 0xD5:
7530 case 0xD6:
7531 case 0xD7:
7532 case 0xD8:
7533 case 0xD9:
7534 case 0xDA:
7535 case 0xDB:
7536 case 0xDC:
7537 case 0xDD:
7538 case 0xDE:
7539 case 0xDF:
7540 {
7541 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({ 0x80, 0xBF }))) {
7542 return token_type::parse_error;
7543 }
7544 break;
7545 }
7546
7547 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7548 case 0xE0:
7549 {
7550 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0xA0, 0xBF, 0x80, 0xBF })))) {
7551 return token_type::parse_error;
7552 }
7553 break;
7554 }
7555
7556 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7557 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7558 case 0xE1:
7559 case 0xE2:
7560 case 0xE3:
7561 case 0xE4:
7562 case 0xE5:
7563 case 0xE6:
7564 case 0xE7:
7565 case 0xE8:
7566 case 0xE9:
7567 case 0xEA:
7568 case 0xEB:
7569 case 0xEC:
7570 case 0xEE:
7571 case 0xEF:
7572 {
7573 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x80, 0xBF, 0x80, 0xBF })))) {
7574 return token_type::parse_error;
7575 }
7576 break;
7577 }
7578
7579 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7580 case 0xED:
7581 {
7582 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x80, 0x9F, 0x80, 0xBF })))) {
7583 return token_type::parse_error;
7584 }
7585 break;
7586 }
7587
7588 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7589 case 0xF0:
7590 {
7591 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF })))) {
7592 return token_type::parse_error;
7593 }
7594 break;
7595 }
7596
7597 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7598 case 0xF1:
7599 case 0xF2:
7600 case 0xF3:
7601 {
7602 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF })))) {
7603 return token_type::parse_error;
7604 }
7605 break;
7606 }
7607
7608 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7609 case 0xF4:
7610 {
7611 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF })))) {
7612 return token_type::parse_error;
7613 }
7614 break;
7615 }
7616
7617 // the remaining bytes (80..C1 and F5..FF) are ill-formed
7618 default:
7619 {
7620 error_message = "invalid string: ill-formed UTF-8 byte";
7621 return token_type::parse_error;
7622 }
7623 }
7624 }
7625 }
7626
7631 bool scan_comment() {
7632 switch (get()) {
7633 // single-line comments skip input until a newline or EOF is read
7634 case '/':
7635 {
7636 while (true) {
7637 switch (get()) {
7638 case '\n':
7639 case '\r':
7641 case '\0':
7642 return true;
7643
7644 default:
7645 break;
7646 }
7647 }
7648
7649 JSON_HEDLEY_UNREACHABLE();
7650 }
7651
7652 // multi-line comments skip input until */ is read
7653 case '*':
7654 {
7655 while (true) {
7656 switch (get()) {
7658 case '\0':
7659 {
7660 error_message = "invalid comment; missing closing '*/'";
7661 return false;
7662 }
7663
7664 case '*':
7665 {
7666 switch (get()) {
7667 case '/':
7668 return true;
7669
7670 default:
7671 {
7672 unget();
7673 continue;
7674 }
7675 }
7676 }
7677
7678 default:
7679 continue;
7680 }
7681 }
7682
7683 JSON_HEDLEY_UNREACHABLE();
7684 }
7685
7686 // unexpected character after reading '/'
7687 default:
7688 {
7689 error_message = "invalid comment; expecting '/' or '*' after '/'";
7690 return false;
7691 }
7692 }
7693 }
7694
7695 JSON_HEDLEY_NON_NULL(2)
7696 static void strtof(float& f, const char* str, char** endptr) noexcept {
7697 f = std::strtof(str, endptr);
7698 }
7699
7700 JSON_HEDLEY_NON_NULL(2)
7701 static void strtof(double& f, const char* str, char** endptr) noexcept {
7702 f = std::strtod(str, endptr);
7703 }
7704
7705 JSON_HEDLEY_NON_NULL(2)
7706 static void strtof(long double& f, const char* str, char** endptr) noexcept {
7707 f = std::strtold(str, endptr);
7708 }
7709
7750 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.
7751 {
7752 // reset token_buffer to store the number's bytes
7753 reset();
7754
7755 // the type of the parsed number; initially set to unsigned; will be
7756 // changed if minus sign, decimal point, or exponent is read
7757 token_type number_type = token_type::value_unsigned;
7758
7759 // state (init): we just found out we need to scan a number
7760 switch (current) {
7761 case '-':
7762 {
7763 add(current);
7764 goto scan_number_minus;
7765 }
7766
7767 case '0':
7768 {
7769 add(current);
7770 goto scan_number_zero;
7771 }
7772
7773 case '1':
7774 case '2':
7775 case '3':
7776 case '4':
7777 case '5':
7778 case '6':
7779 case '7':
7780 case '8':
7781 case '9':
7782 {
7783 add(current);
7784 goto scan_number_any1;
7785 }
7786
7787 // all other characters are rejected outside scan_number()
7788 default: // LCOV_EXCL_LINE
7789 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
7790 }
7791
7792 scan_number_minus:
7793 // state: we just parsed a leading minus sign
7794 number_type = token_type::value_integer;
7795 switch (get()) {
7796 case '0':
7797 {
7798 add(current);
7799 goto scan_number_zero;
7800 }
7801
7802 case '1':
7803 case '2':
7804 case '3':
7805 case '4':
7806 case '5':
7807 case '6':
7808 case '7':
7809 case '8':
7810 case '9':
7811 {
7812 add(current);
7813 goto scan_number_any1;
7814 }
7815
7816 default:
7817 {
7818 error_message = "invalid number; expected digit after '-'";
7819 return token_type::parse_error;
7820 }
7821 }
7822
7823 scan_number_zero:
7824 // state: we just parse a zero (maybe with a leading minus sign)
7825 switch (get()) {
7826 case '.':
7827 {
7828 add(decimal_point_char);
7829 decimal_point_position = token_buffer.size() - 1;
7830 goto scan_number_decimal1;
7831 }
7832
7833 case 'e':
7834 case 'E':
7835 {
7836 add(current);
7837 goto scan_number_exponent;
7838 }
7839
7840 default:
7841 goto scan_number_done;
7842 }
7843
7844 scan_number_any1:
7845 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
7846 switch (get()) {
7847 case '0':
7848 case '1':
7849 case '2':
7850 case '3':
7851 case '4':
7852 case '5':
7853 case '6':
7854 case '7':
7855 case '8':
7856 case '9':
7857 {
7858 add(current);
7859 goto scan_number_any1;
7860 }
7861
7862 case '.':
7863 {
7864 add(decimal_point_char);
7865 decimal_point_position = token_buffer.size() - 1;
7866 goto scan_number_decimal1;
7867 }
7868
7869 case 'e':
7870 case 'E':
7871 {
7872 add(current);
7873 goto scan_number_exponent;
7874 }
7875
7876 default:
7877 goto scan_number_done;
7878 }
7879
7880 scan_number_decimal1:
7881 // state: we just parsed a decimal point
7882 number_type = token_type::value_float;
7883 switch (get()) {
7884 case '0':
7885 case '1':
7886 case '2':
7887 case '3':
7888 case '4':
7889 case '5':
7890 case '6':
7891 case '7':
7892 case '8':
7893 case '9':
7894 {
7895 add(current);
7896 goto scan_number_decimal2;
7897 }
7898
7899 default:
7900 {
7901 error_message = "invalid number; expected digit after '.'";
7902 return token_type::parse_error;
7903 }
7904 }
7905
7906 scan_number_decimal2:
7907 // we just parsed at least one number after a decimal point
7908 switch (get()) {
7909 case '0':
7910 case '1':
7911 case '2':
7912 case '3':
7913 case '4':
7914 case '5':
7915 case '6':
7916 case '7':
7917 case '8':
7918 case '9':
7919 {
7920 add(current);
7921 goto scan_number_decimal2;
7922 }
7923
7924 case 'e':
7925 case 'E':
7926 {
7927 add(current);
7928 goto scan_number_exponent;
7929 }
7930
7931 default:
7932 goto scan_number_done;
7933 }
7934
7935 scan_number_exponent:
7936 // we just parsed an exponent
7937 number_type = token_type::value_float;
7938 switch (get()) {
7939 case '+':
7940 case '-':
7941 {
7942 add(current);
7943 goto scan_number_sign;
7944 }
7945
7946 case '0':
7947 case '1':
7948 case '2':
7949 case '3':
7950 case '4':
7951 case '5':
7952 case '6':
7953 case '7':
7954 case '8':
7955 case '9':
7956 {
7957 add(current);
7958 goto scan_number_any2;
7959 }
7960
7961 default:
7962 {
7963 error_message =
7964 "invalid number; expected '+', '-', or digit after exponent";
7965 return token_type::parse_error;
7966 }
7967 }
7968
7969 scan_number_sign:
7970 // we just parsed an exponent sign
7971 switch (get()) {
7972 case '0':
7973 case '1':
7974 case '2':
7975 case '3':
7976 case '4':
7977 case '5':
7978 case '6':
7979 case '7':
7980 case '8':
7981 case '9':
7982 {
7983 add(current);
7984 goto scan_number_any2;
7985 }
7986
7987 default:
7988 {
7989 error_message = "invalid number; expected digit after exponent sign";
7990 return token_type::parse_error;
7991 }
7992 }
7993
7994 scan_number_any2:
7995 // we just parsed a number after the exponent or exponent sign
7996 switch (get()) {
7997 case '0':
7998 case '1':
7999 case '2':
8000 case '3':
8001 case '4':
8002 case '5':
8003 case '6':
8004 case '7':
8005 case '8':
8006 case '9':
8007 {
8008 add(current);
8009 goto scan_number_any2;
8010 }
8011
8012 default:
8013 goto scan_number_done;
8014 }
8015
8016 scan_number_done:
8017 // unget the character after the number (we only read it to know that
8018 // we are done scanning a number)
8019 unget();
8020
8021 char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8022 errno = 0;
8023
8024 // try to parse integers first and fall back to floats
8025 if (number_type == token_type::value_unsigned) {
8026 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8027
8028 // we checked the number format before
8029 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8030
8031 if (errno != ERANGE) {
8032 value_unsigned = static_cast<number_unsigned_t>(x);
8033 if (value_unsigned == x) {
8034 return token_type::value_unsigned;
8035 }
8036 }
8037 }
8038 else if (number_type == token_type::value_integer) {
8039 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8040
8041 // we checked the number format before
8042 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8043
8044 if (errno != ERANGE) {
8045 value_integer = static_cast<number_integer_t>(x);
8046 if (value_integer == x) {
8047 return token_type::value_integer;
8048 }
8049 }
8050 }
8051
8052 // this code is reached if we parse a floating-point number or if an
8053 // integer conversion above failed
8054 strtof(value_float, token_buffer.data(), &endptr);
8055
8056 // we checked the number format before
8057 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8058
8059 return token_type::value_float;
8060 }
8061
8067 JSON_HEDLEY_NON_NULL(2)
8068 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8069 token_type return_type) {
8070 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8071 for (std::size_t i = 1; i < length; ++i) {
8072 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i])) {
8073 error_message = "invalid literal";
8074 return token_type::parse_error;
8075 }
8076 }
8077 return return_type;
8078 }
8079
8081 // input management
8083
8085 void reset() noexcept {
8086 token_buffer.clear();
8087 token_string.clear();
8088 decimal_point_position = std::string::npos;
8089 token_string.push_back(char_traits<char_type>::to_char_type(current));
8090 }
8091
8092 /*
8093 @brief get next character from the input
8094
8095 This function provides the interface to the used input adapter. It does
8096 not throw in case the input reached EOF, but returns a
8097 `char_traits<char>::eof()` in that case. Stores the scanned characters
8098 for use in error messages.
8099
8100 @return character read from the input
8101 */
8102 char_int_type get() {
8103 ++position.chars_read_total;
8104 ++position.chars_read_current_line;
8105
8106 if (next_unget) {
8107 // only reset the next_unget variable and work with current
8108 next_unget = false;
8109 }
8110 else {
8111 current = ia.get_character();
8112 }
8113
8114 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof())) {
8115 token_string.push_back(char_traits<char_type>::to_char_type(current));
8116 }
8117
8118 if (current == '\n') {
8119 ++position.lines_read;
8120 position.chars_read_current_line = 0;
8121 }
8122
8123 return current;
8124 }
8125
8134 void unget() {
8135 next_unget = true;
8136
8137 --position.chars_read_total;
8138
8139 // in case we "unget" a newline, we have to also decrement the lines_read
8140 if (position.chars_read_current_line == 0) {
8141 if (position.lines_read > 0) {
8142 --position.lines_read;
8143 }
8144 }
8145 else {
8146 --position.chars_read_current_line;
8147 }
8148
8149 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof())) {
8150 JSON_ASSERT(!token_string.empty());
8151 token_string.pop_back();
8152 }
8153 }
8154
8156 void add(char_int_type c) {
8157 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8158 }
8159
8160 public:
8162 // value getters
8164
8166 constexpr number_integer_t get_number_integer() const noexcept {
8167 return value_integer;
8168 }
8169
8171 constexpr number_unsigned_t get_number_unsigned() const noexcept {
8172 return value_unsigned;
8173 }
8174
8176 constexpr number_float_t get_number_float() const noexcept {
8177 return value_float;
8178 }
8179
8181 string_t& get_string() {
8182 // translate decimal points from locale back to '.' (#4084)
8183 if (decimal_point_char != '.' && decimal_point_position != std::string::npos) {
8184 token_buffer[decimal_point_position] = '.';
8185 }
8186 return token_buffer;
8187 }
8188
8190 // diagnostics
8192
8194 constexpr position_t get_position() const noexcept {
8195 return position;
8196 }
8197
8201 std::string get_token_string() const {
8202 // escape control characters
8203 std::string result;
8204 for (const auto c : token_string) {
8205 if (static_cast<unsigned char>(c) <= '\x1F') {
8206 // escape control characters
8207 std::array<char, 9> cs{ {} };
8208 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8209 result += cs.data();
8210 }
8211 else {
8212 // add character as is
8213 result.push_back(static_cast<std::string::value_type>(c));
8214 }
8215 }
8216
8217 return result;
8218 }
8219
8221 JSON_HEDLEY_RETURNS_NON_NULL
8222 constexpr const char* get_error_message() const noexcept {
8223 return error_message;
8224 }
8225
8227 // actual scanner
8229
8234 bool skip_bom() {
8235 if (get() == 0xEF) {
8236 // check if we completely parse the BOM
8237 return get() == 0xBB && get() == 0xBF;
8238 }
8239
8240 // the first character is not the beginning of the BOM; unget it to
8241 // process is later
8242 unget();
8243 return true;
8244 }
8245
8246 void skip_whitespace() {
8247 do {
8248 get();
8249 } while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8250 }
8251
8252 token_type scan() {
8253 // initially, skip the BOM
8254 if (position.chars_read_total == 0 && !skip_bom()) {
8255 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8256 return token_type::parse_error;
8257 }
8258
8259 // read the next character and ignore whitespace
8260 skip_whitespace();
8261
8262 // ignore comments
8263 while (ignore_comments && current == '/') {
8264 if (!scan_comment()) {
8265 return token_type::parse_error;
8266 }
8267
8268 // skip following whitespace
8269 skip_whitespace();
8270 }
8271
8272 switch (current) {
8273 // structural characters
8274 case '[':
8275 return token_type::begin_array;
8276 case ']':
8277 return token_type::end_array;
8278 case '{':
8279 return token_type::begin_object;
8280 case '}':
8281 return token_type::end_object;
8282 case ':':
8283 return token_type::name_separator;
8284 case ',':
8285 return token_type::value_separator;
8286
8287 // literals
8288 case 't':
8289 {
8290 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')} };
8291 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8292 }
8293 case 'f':
8294 {
8295 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')} };
8296 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8297 }
8298 case 'n':
8299 {
8300 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')} };
8301 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8302 }
8303
8304 // string
8305 case '\"':
8306 return scan_string();
8307
8308 // number
8309 case '-':
8310 case '0':
8311 case '1':
8312 case '2':
8313 case '3':
8314 case '4':
8315 case '5':
8316 case '6':
8317 case '7':
8318 case '8':
8319 case '9':
8320 return scan_number();
8321
8322 // end of input (the null byte is needed when parsing from
8323 // string literals)
8324 case '\0':
8325 case char_traits<char_type>::eof():
8326 return token_type::end_of_input;
8327
8328 // error
8329 default:
8330 error_message = "invalid literal";
8331 return token_type::parse_error;
8332 }
8333 }
8334
8335 private:
8337 InputAdapterType ia;
8338
8340 const bool ignore_comments = false;
8341
8343 char_int_type current = char_traits<char_type>::eof();
8344
8346 bool next_unget = false;
8347
8349 position_t position{};
8350
8352 std::vector<char_type> token_string{};
8353
8355 string_t token_buffer{};
8356
8358 const char* error_message = "";
8359
8360 // number values
8361 number_integer_t value_integer = 0;
8362 number_unsigned_t value_unsigned = 0;
8363 number_float_t value_float = 0;
8364
8366 const char_int_type decimal_point_char = '.';
8368 std::size_t decimal_point_position = std::string::npos;
8369 };
8370
8371} // namespace detail
8372NLOHMANN_JSON_NAMESPACE_END
8373
8374// #include <nlohmann/detail/macro_scope.hpp>
8375
8376// #include <nlohmann/detail/string_concat.hpp>
8377
8378NLOHMANN_JSON_NAMESPACE_BEGIN
8379
8388template<typename BasicJsonType>
8389struct json_sax {
8390 using number_integer_t = typename BasicJsonType::number_integer_t;
8391 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8392 using number_float_t = typename BasicJsonType::number_float_t;
8393 using string_t = typename BasicJsonType::string_t;
8394 using binary_t = typename BasicJsonType::binary_t;
8395
8400 virtual bool null() = 0;
8401
8407 virtual bool boolean(bool val) = 0;
8408
8414 virtual bool number_integer(number_integer_t val) = 0;
8415
8421 virtual bool number_unsigned(number_unsigned_t val) = 0;
8422
8429 virtual bool number_float(number_float_t val, const string_t& s) = 0;
8430
8437 virtual bool string(string_t& val) = 0;
8438
8445 virtual bool binary(binary_t& val) = 0;
8446
8453 virtual bool start_object(std::size_t elements) = 0;
8454
8461 virtual bool key(string_t& val) = 0;
8462
8467 virtual bool end_object() = 0;
8468
8475 virtual bool start_array(std::size_t elements) = 0;
8476
8481 virtual bool end_array() = 0;
8482
8490 virtual bool parse_error(std::size_t position,
8491 const std::string& last_token,
8492 const detail::exception& ex) = 0;
8493
8494 json_sax() = default;
8495 json_sax(const json_sax&) = default;
8496 json_sax(json_sax&&) noexcept = default;
8497 json_sax& operator=(const json_sax&) = default;
8498 json_sax& operator=(json_sax&&) noexcept = default;
8499 virtual ~json_sax() = default;
8500};
8501
8502namespace detail {
8503 constexpr std::size_t unknown_size() {
8504 return (std::numeric_limits<std::size_t>::max)();
8505 }
8506
8520 template<typename BasicJsonType, typename InputAdapterType>
8522 public:
8523 using number_integer_t = typename BasicJsonType::number_integer_t;
8524 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8525 using number_float_t = typename BasicJsonType::number_float_t;
8526 using string_t = typename BasicJsonType::string_t;
8527 using binary_t = typename BasicJsonType::binary_t;
8529
8535 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr)
8536 : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_) {}
8537
8538 // make class move-only
8540 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8541 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
8542 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8543 ~json_sax_dom_parser() = default;
8544
8545 bool null() {
8546 handle_value(nullptr);
8547 return true;
8548 }
8549
8550 bool boolean(bool val) {
8551 handle_value(val);
8552 return true;
8553 }
8554
8555 bool number_integer(number_integer_t val) {
8556 handle_value(val);
8557 return true;
8558 }
8559
8560 bool number_unsigned(number_unsigned_t val) {
8561 handle_value(val);
8562 return true;
8563 }
8564
8565 bool number_float(number_float_t val, const string_t& /*unused*/) {
8566 handle_value(val);
8567 return true;
8568 }
8569
8570 bool string(string_t& val) {
8571 handle_value(val);
8572 return true;
8573 }
8574
8575 bool binary(binary_t& val) {
8576 handle_value(std::move(val));
8577 return true;
8578 }
8579
8580 bool start_object(std::size_t len) {
8581 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
8582
8583#if JSON_DIAGNOSTIC_POSITIONS
8584 // Manually set the start position of the object here.
8585 // Ensure this is after the call to handle_value to ensure correct start position.
8586 if (m_lexer_ref) {
8587 // Lexer has read the first character of the object, so
8588 // subtract 1 from the position to get the correct start position.
8589 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8590 }
8591#endif
8592
8593 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size())) {
8594 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
8595 }
8596
8597 return true;
8598 }
8599
8600 bool key(string_t& val) {
8601 JSON_ASSERT(!ref_stack.empty());
8602 JSON_ASSERT(ref_stack.back()->is_object());
8603
8604 // add null at the given key and store the reference for later
8605 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
8606 return true;
8607 }
8608
8609 bool end_object() {
8610 JSON_ASSERT(!ref_stack.empty());
8611 JSON_ASSERT(ref_stack.back()->is_object());
8612
8613#if JSON_DIAGNOSTIC_POSITIONS
8614 if (m_lexer_ref) {
8615 // Lexer's position is past the closing brace, so set that as the end position.
8616 ref_stack.back()->end_position = m_lexer_ref->get_position();
8617 }
8618#endif
8619
8620 ref_stack.back()->set_parents();
8621 ref_stack.pop_back();
8622 return true;
8623 }
8624
8625 bool start_array(std::size_t len) {
8626 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
8627
8628#if JSON_DIAGNOSTIC_POSITIONS
8629 // Manually set the start position of the array here.
8630 // Ensure this is after the call to handle_value to ensure correct start position.
8631 if (m_lexer_ref) {
8632 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8633 }
8634#endif
8635
8636 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size())) {
8637 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
8638 }
8639
8640 return true;
8641 }
8642
8643 bool end_array() {
8644 JSON_ASSERT(!ref_stack.empty());
8645 JSON_ASSERT(ref_stack.back()->is_array());
8646
8647#if JSON_DIAGNOSTIC_POSITIONS
8648 if (m_lexer_ref) {
8649 // Lexer's position is past the closing bracket, so set that as the end position.
8650 ref_stack.back()->end_position = m_lexer_ref->get_position();
8651 }
8652#endif
8653
8654 ref_stack.back()->set_parents();
8655 ref_stack.pop_back();
8656 return true;
8657 }
8658
8659 template<class Exception>
8660 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
8661 const Exception& ex) {
8662 errored = true;
8663 static_cast<void>(ex);
8664 if (allow_exceptions) {
8665 JSON_THROW(ex);
8666 }
8667 return false;
8668 }
8669
8670 constexpr bool is_errored() const {
8671 return errored;
8672 }
8673
8674 private:
8675
8676#if JSON_DIAGNOSTIC_POSITIONS
8677 void handle_diagnostic_positions_for_json_value(BasicJsonType& v) {
8678 if (m_lexer_ref) {
8679 // Lexer has read past the current field value, so set the end position to the current position.
8680 // The start position will be set below based on the length of the string representation
8681 // of the value.
8682 v.end_position = m_lexer_ref->get_position();
8683
8684 switch (v.type()) {
8685 case value_t::boolean:
8686 {
8687 // 4 and 5 are the string length of "true" and "false"
8688 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
8689 break;
8690 }
8691
8692 case value_t::null:
8693 {
8694 // 4 is the string length of "null"
8695 v.start_position = v.end_position - 4;
8696 break;
8697 }
8698
8699 case value_t::string:
8700 {
8701 // include the length of the quotes, which is 2
8702 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
8703 break;
8704 }
8705
8706 // As we handle the start and end positions for values created during parsing,
8707 // we do not expect the following value type to be called. Regardless, set the positions
8708 // in case this is created manually or through a different constructor. Exclude from lcov
8709 // since the exact condition of this switch is esoteric.
8710 // LCOV_EXCL_START
8711 case value_t::discarded:
8712 {
8713 v.end_position = std::string::npos;
8714 v.start_position = v.end_position;
8715 break;
8716 }
8717 // LCOV_EXCL_STOP
8718 case value_t::binary:
8719 case value_t::number_integer:
8720 case value_t::number_unsigned:
8721 case value_t::number_float:
8722 {
8723 v.start_position = v.end_position - m_lexer_ref->get_string().size();
8724 break;
8725 }
8726 case value_t::object:
8727 case value_t::array:
8728 {
8729 // object and array are handled in start_object() and start_array() handlers
8730 // skip setting the values here.
8731 break;
8732 }
8733 default: // LCOV_EXCL_LINE
8734 // Handle all possible types discretely, default handler should never be reached.
8735 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
8736 }
8737 }
8738 }
8739#endif
8740
8747 template<typename Value>
8748 JSON_HEDLEY_RETURNS_NON_NULL
8749 BasicJsonType* handle_value(Value&& v) {
8750 if (ref_stack.empty()) {
8751 root = BasicJsonType(std::forward<Value>(v));
8752
8753#if JSON_DIAGNOSTIC_POSITIONS
8754 handle_diagnostic_positions_for_json_value(root);
8755#endif
8756
8757 return &root;
8758 }
8759
8760 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
8761
8762 if (ref_stack.back()->is_array()) {
8763 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
8764
8765#if JSON_DIAGNOSTIC_POSITIONS
8766 handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back());
8767#endif
8768
8769 return &(ref_stack.back()->m_data.m_value.array->back());
8770 }
8771
8772 JSON_ASSERT(ref_stack.back()->is_object());
8773 JSON_ASSERT(object_element);
8774 *object_element = BasicJsonType(std::forward<Value>(v));
8775
8776#if JSON_DIAGNOSTIC_POSITIONS
8777 handle_diagnostic_positions_for_json_value(*object_element);
8778#endif
8779
8780 return object_element;
8781 }
8782
8784 BasicJsonType& root;
8786 std::vector<BasicJsonType*> ref_stack{};
8788 BasicJsonType* object_element = nullptr;
8790 bool errored = false;
8792 const bool allow_exceptions = true;
8794 lexer_t* m_lexer_ref = nullptr;
8795 };
8796
8797 template<typename BasicJsonType, typename InputAdapterType>
8798 class json_sax_dom_callback_parser {
8799 public:
8800 using number_integer_t = typename BasicJsonType::number_integer_t;
8801 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8802 using number_float_t = typename BasicJsonType::number_float_t;
8803 using string_t = typename BasicJsonType::string_t;
8804 using binary_t = typename BasicJsonType::binary_t;
8805 using parser_callback_t = typename BasicJsonType::parser_callback_t;
8806 using parse_event_t = typename BasicJsonType::parse_event_t;
8808
8809 json_sax_dom_callback_parser(BasicJsonType& r,
8810 parser_callback_t cb,
8811 const bool allow_exceptions_ = true,
8812 lexer_t* lexer_ = nullptr)
8813 : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_) {
8814 keep_stack.push_back(true);
8815 }
8816
8817 // make class move-only
8818 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
8819 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8820 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
8821 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8822 ~json_sax_dom_callback_parser() = default;
8823
8824 bool null() {
8825 handle_value(nullptr);
8826 return true;
8827 }
8828
8829 bool boolean(bool val) {
8830 handle_value(val);
8831 return true;
8832 }
8833
8834 bool number_integer(number_integer_t val) {
8835 handle_value(val);
8836 return true;
8837 }
8838
8839 bool number_unsigned(number_unsigned_t val) {
8840 handle_value(val);
8841 return true;
8842 }
8843
8844 bool number_float(number_float_t val, const string_t& /*unused*/) {
8845 handle_value(val);
8846 return true;
8847 }
8848
8849 bool string(string_t& val) {
8850 handle_value(val);
8851 return true;
8852 }
8853
8854 bool binary(binary_t& val) {
8855 handle_value(std::move(val));
8856 return true;
8857 }
8858
8859 bool start_object(std::size_t len) {
8860 // check callback for object start
8861 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
8862 keep_stack.push_back(keep);
8863
8864 auto val = handle_value(BasicJsonType::value_t::object, true);
8865 ref_stack.push_back(val.second);
8866
8867 if (ref_stack.back()) {
8868
8869#if JSON_DIAGNOSTIC_POSITIONS
8870 // Manually set the start position of the object here.
8871 // Ensure this is after the call to handle_value to ensure correct start position.
8872 if (m_lexer_ref) {
8873 // Lexer has read the first character of the object, so
8874 // subtract 1 from the position to get the correct start position.
8875 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8876 }
8877#endif
8878
8879 // check object limit
8880 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size())) {
8881 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
8882 }
8883 }
8884 return true;
8885 }
8886
8887 bool key(string_t& val) {
8888 BasicJsonType k = BasicJsonType(val);
8889
8890 // check callback for the key
8891 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
8892 key_keep_stack.push_back(keep);
8893
8894 // add discarded value at the given key and store the reference for later
8895 if (keep && ref_stack.back()) {
8896 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
8897 }
8898
8899 return true;
8900 }
8901
8902 bool end_object() {
8903 if (ref_stack.back()) {
8904 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) {
8905 // discard object
8906 *ref_stack.back() = discarded;
8907
8908#if JSON_DIAGNOSTIC_POSITIONS
8909 // Set start/end positions for discarded object.
8910 handle_diagnostic_positions_for_json_value(*ref_stack.back());
8911#endif
8912 }
8913 else {
8914
8915#if JSON_DIAGNOSTIC_POSITIONS
8916 if (m_lexer_ref) {
8917 // Lexer's position is past the closing brace, so set that as the end position.
8918 ref_stack.back()->end_position = m_lexer_ref->get_position();
8919 }
8920#endif
8921
8922 ref_stack.back()->set_parents();
8923 }
8924 }
8925
8926 JSON_ASSERT(!ref_stack.empty());
8927 JSON_ASSERT(!keep_stack.empty());
8928 ref_stack.pop_back();
8929 keep_stack.pop_back();
8930
8931 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) {
8932 // remove discarded value
8933 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) {
8934 if (it->is_discarded()) {
8935 ref_stack.back()->erase(it);
8936 break;
8937 }
8938 }
8939 }
8940
8941 return true;
8942 }
8943
8944 bool start_array(std::size_t len) {
8945 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
8946 keep_stack.push_back(keep);
8947
8948 auto val = handle_value(BasicJsonType::value_t::array, true);
8949 ref_stack.push_back(val.second);
8950
8951 if (ref_stack.back()) {
8952
8953#if JSON_DIAGNOSTIC_POSITIONS
8954 // Manually set the start position of the array here.
8955 // Ensure this is after the call to handle_value to ensure correct start position.
8956 if (m_lexer_ref) {
8957 // Lexer has read the first character of the array, so
8958 // subtract 1 from the position to get the correct start position.
8959 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8960 }
8961#endif
8962
8963 // check array limit
8964 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size())) {
8965 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
8966 }
8967 }
8968
8969 return true;
8970 }
8971
8972 bool end_array() {
8973 bool keep = true;
8974
8975 if (ref_stack.back()) {
8976 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
8977 if (keep) {
8978
8979#if JSON_DIAGNOSTIC_POSITIONS
8980 if (m_lexer_ref) {
8981 // Lexer's position is past the closing bracket, so set that as the end position.
8982 ref_stack.back()->end_position = m_lexer_ref->get_position();
8983 }
8984#endif
8985
8986 ref_stack.back()->set_parents();
8987 }
8988 else {
8989 // discard array
8990 *ref_stack.back() = discarded;
8991
8992#if JSON_DIAGNOSTIC_POSITIONS
8993 // Set start/end positions for discarded array.
8994 handle_diagnostic_positions_for_json_value(*ref_stack.back());
8995#endif
8996 }
8997 }
8998
8999 JSON_ASSERT(!ref_stack.empty());
9000 JSON_ASSERT(!keep_stack.empty());
9001 ref_stack.pop_back();
9002 keep_stack.pop_back();
9003
9004 // remove discarded value
9005 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) {
9006 ref_stack.back()->m_data.m_value.array->pop_back();
9007 }
9008
9009 return true;
9010 }
9011
9012 template<class Exception>
9013 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9014 const Exception& ex) {
9015 errored = true;
9016 static_cast<void>(ex);
9017 if (allow_exceptions) {
9018 JSON_THROW(ex);
9019 }
9020 return false;
9021 }
9022
9023 constexpr bool is_errored() const {
9024 return errored;
9025 }
9026
9027 private:
9028
9029#if JSON_DIAGNOSTIC_POSITIONS
9030 void handle_diagnostic_positions_for_json_value(BasicJsonType& v) {
9031 if (m_lexer_ref) {
9032 // Lexer has read past the current field value, so set the end position to the current position.
9033 // The start position will be set below based on the length of the string representation
9034 // of the value.
9035 v.end_position = m_lexer_ref->get_position();
9036
9037 switch (v.type()) {
9038 case value_t::boolean:
9039 {
9040 // 4 and 5 are the string length of "true" and "false"
9041 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9042 break;
9043 }
9044
9045 case value_t::null:
9046 {
9047 // 4 is the string length of "null"
9048 v.start_position = v.end_position - 4;
9049 break;
9050 }
9051
9052 case value_t::string:
9053 {
9054 // include the length of the quotes, which is 2
9055 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9056 break;
9057 }
9058
9059 case value_t::discarded:
9060 {
9061 v.end_position = std::string::npos;
9062 v.start_position = v.end_position;
9063 break;
9064 }
9065
9066 case value_t::binary:
9070 {
9071 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9072 break;
9073 }
9074
9075 case value_t::object:
9076 case value_t::array:
9077 {
9078 // object and array are handled in start_object() and start_array() handlers
9079 // skip setting the values here.
9080 break;
9081 }
9082 default: // LCOV_EXCL_LINE
9083 // Handle all possible types discretely, default handler should never be reached.
9084 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9085 }
9086 }
9087 }
9088#endif
9089
9105 template<typename Value>
9106 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false) {
9107 JSON_ASSERT(!keep_stack.empty());
9108
9109 // do not handle this value if we know it would be added to a discarded
9110 // container
9111 if (!keep_stack.back()) {
9112 return { false, nullptr };
9113 }
9114
9115 // create value
9116 auto value = BasicJsonType(std::forward<Value>(v));
9117
9118#if JSON_DIAGNOSTIC_POSITIONS
9119 handle_diagnostic_positions_for_json_value(value);
9120#endif
9121
9122 // check callback
9123 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
9124
9125 // do not handle this value if we just learnt it shall be discarded
9126 if (!keep) {
9127 return { false, nullptr };
9128 }
9129
9130 if (ref_stack.empty()) {
9131 root = std::move(value);
9132 return { true, &root };
9133 }
9134
9135 // skip this value if we already decided to skip the parent
9136 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
9137 if (!ref_stack.back()) {
9138 return { false, nullptr };
9139 }
9140
9141 // we now only expect arrays and objects
9142 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9143
9144 // array
9145 if (ref_stack.back()->is_array()) {
9146 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
9147 return { true, &(ref_stack.back()->m_data.m_value.array->back()) };
9148 }
9149
9150 // object
9151 JSON_ASSERT(ref_stack.back()->is_object());
9152 // check if we should store an element for the current key
9153 JSON_ASSERT(!key_keep_stack.empty());
9154 const bool store_element = key_keep_stack.back();
9155 key_keep_stack.pop_back();
9156
9157 if (!store_element) {
9158 return { false, nullptr };
9159 }
9160
9161 JSON_ASSERT(object_element);
9162 *object_element = std::move(value);
9163 return { true, object_element };
9164 }
9165
9167 BasicJsonType& root;
9169 std::vector<BasicJsonType*> ref_stack{};
9171 std::vector<bool> keep_stack{}; // NOLINT(readability-redundant-member-init)
9173 std::vector<bool> key_keep_stack{}; // NOLINT(readability-redundant-member-init)
9175 BasicJsonType* object_element = nullptr;
9177 bool errored = false;
9179 const parser_callback_t callback = nullptr;
9181 const bool allow_exceptions = true;
9183 BasicJsonType discarded = BasicJsonType::value_t::discarded;
9185 lexer_t* m_lexer_ref = nullptr;
9186 };
9187
9188 template<typename BasicJsonType>
9190 public:
9191 using number_integer_t = typename BasicJsonType::number_integer_t;
9192 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9193 using number_float_t = typename BasicJsonType::number_float_t;
9194 using string_t = typename BasicJsonType::string_t;
9195 using binary_t = typename BasicJsonType::binary_t;
9196
9197 bool null() {
9198 return true;
9199 }
9200
9201 bool boolean(bool /*unused*/) {
9202 return true;
9203 }
9204
9205 bool number_integer(number_integer_t /*unused*/) {
9206 return true;
9207 }
9208
9209 bool number_unsigned(number_unsigned_t /*unused*/) {
9210 return true;
9211 }
9212
9213 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) {
9214 return true;
9215 }
9216
9217 bool string(string_t& /*unused*/) {
9218 return true;
9219 }
9220
9221 bool binary(binary_t& /*unused*/) {
9222 return true;
9223 }
9224
9225 bool start_object(std::size_t /*unused*/ = detail::unknown_size()) {
9226 return true;
9227 }
9228
9229 bool key(string_t& /*unused*/) {
9230 return true;
9231 }
9232
9233 bool end_object() {
9234 return true;
9235 }
9236
9237 bool start_array(std::size_t /*unused*/ = detail::unknown_size()) {
9238 return true;
9239 }
9240
9241 bool end_array() {
9242 return true;
9243 }
9244
9245 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) {
9246 return false;
9247 }
9248 };
9249
9250} // namespace detail
9251NLOHMANN_JSON_NAMESPACE_END
9252
9253// #include <nlohmann/detail/input/lexer.hpp>
9254
9255// #include <nlohmann/detail/macro_scope.hpp>
9256
9257// #include <nlohmann/detail/meta/is_sax.hpp>
9258// __ _____ _____ _____
9259// __| | __| | | | JSON for Modern C++
9260// | | |__ | | | | | | version 3.12.0
9261// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9262//
9263// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
9264// SPDX-License-Identifier: MIT
9265
9266
9267
9268#include <cstdint> // size_t
9269#include <utility> // declval
9270#include <string> // string
9271
9272// #include <nlohmann/detail/abi_macros.hpp>
9273
9274// #include <nlohmann/detail/meta/detected.hpp>
9275
9276// #include <nlohmann/detail/meta/type_traits.hpp>
9277
9278
9279NLOHMANN_JSON_NAMESPACE_BEGIN
9280namespace detail {
9281
9282 template<typename T>
9283 using null_function_t = decltype(std::declval<T&>().null());
9284
9285 template<typename T>
9286 using boolean_function_t =
9287 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9288
9289 template<typename T, typename Integer>
9290 using number_integer_function_t =
9291 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9292
9293 template<typename T, typename Unsigned>
9294 using number_unsigned_function_t =
9295 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9296
9297 template<typename T, typename Float, typename String>
9298 using number_float_function_t = decltype(std::declval<T&>().number_float(
9299 std::declval<Float>(), std::declval<const String&>()));
9300
9301 template<typename T, typename String>
9302 using string_function_t =
9303 decltype(std::declval<T&>().string(std::declval<String&>()));
9304
9305 template<typename T, typename Binary>
9306 using binary_function_t =
9307 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9308
9309 template<typename T>
9310 using start_object_function_t =
9311 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9312
9313 template<typename T, typename String>
9314 using key_function_t =
9315 decltype(std::declval<T&>().key(std::declval<String&>()));
9316
9317 template<typename T>
9318 using end_object_function_t = decltype(std::declval<T&>().end_object());
9319
9320 template<typename T>
9321 using start_array_function_t =
9322 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9323
9324 template<typename T>
9325 using end_array_function_t = decltype(std::declval<T&>().end_array());
9326
9327 template<typename T, typename Exception>
9328 using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9329 std::declval<std::size_t>(), std::declval<const std::string&>(),
9330 std::declval<const Exception&>()));
9331
9332 template<typename SAX, typename BasicJsonType>
9333 struct is_sax {
9334 private:
9336 "BasicJsonType must be of type basic_json<...>");
9337
9338 using number_integer_t = typename BasicJsonType::number_integer_t;
9339 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9340 using number_float_t = typename BasicJsonType::number_float_t;
9341 using string_t = typename BasicJsonType::string_t;
9342 using binary_t = typename BasicJsonType::binary_t;
9343 using exception_t = typename BasicJsonType::exception;
9344
9345 public:
9346 static constexpr bool value =
9347 is_detected_exact<bool, null_function_t, SAX>::value&&
9348 is_detected_exact<bool, boolean_function_t, SAX>::value&&
9349 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value&&
9350 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value&&
9351 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value&&
9352 is_detected_exact<bool, string_function_t, SAX, string_t>::value&&
9353 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value&&
9354 is_detected_exact<bool, start_object_function_t, SAX>::value&&
9355 is_detected_exact<bool, key_function_t, SAX, string_t>::value&&
9356 is_detected_exact<bool, end_object_function_t, SAX>::value&&
9357 is_detected_exact<bool, start_array_function_t, SAX>::value&&
9358 is_detected_exact<bool, end_array_function_t, SAX>::value&&
9359 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
9360 };
9361
9362 template<typename SAX, typename BasicJsonType>
9364 private:
9366 "BasicJsonType must be of type basic_json<...>");
9367
9368 using number_integer_t = typename BasicJsonType::number_integer_t;
9369 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9370 using number_float_t = typename BasicJsonType::number_float_t;
9371 using string_t = typename BasicJsonType::string_t;
9372 using binary_t = typename BasicJsonType::binary_t;
9373 using exception_t = typename BasicJsonType::exception;
9374
9375 public:
9376 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
9377 "Missing/invalid function: bool null()");
9378 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9379 "Missing/invalid function: bool boolean(bool)");
9380 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9381 "Missing/invalid function: bool boolean(bool)");
9382 static_assert(
9383 is_detected_exact<bool, number_integer_function_t, SAX,
9384 number_integer_t>::value,
9385 "Missing/invalid function: bool number_integer(number_integer_t)");
9386 static_assert(
9387 is_detected_exact<bool, number_unsigned_function_t, SAX,
9388 number_unsigned_t>::value,
9389 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9390 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9391 number_float_t, string_t>::value,
9392 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9393 static_assert(
9394 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
9395 "Missing/invalid function: bool string(string_t&)");
9396 static_assert(
9397 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
9398 "Missing/invalid function: bool binary(binary_t&)");
9399 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
9400 "Missing/invalid function: bool start_object(std::size_t)");
9401 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
9402 "Missing/invalid function: bool key(string_t&)");
9403 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
9404 "Missing/invalid function: bool end_object()");
9405 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
9406 "Missing/invalid function: bool start_array(std::size_t)");
9407 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
9408 "Missing/invalid function: bool end_array()");
9409 static_assert(
9410 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
9411 "Missing/invalid function: bool parse_error(std::size_t, const "
9412 "std::string&, const exception&)");
9413 };
9414
9415} // namespace detail
9416NLOHMANN_JSON_NAMESPACE_END
9417
9418// #include <nlohmann/detail/meta/type_traits.hpp>
9419
9420// #include <nlohmann/detail/string_concat.hpp>
9421
9422// #include <nlohmann/detail/value_t.hpp>
9423
9424
9425NLOHMANN_JSON_NAMESPACE_BEGIN
9426namespace detail {
9427
9434
9442 inline bool little_endianness(int num = 1) noexcept {
9443 return *reinterpret_cast<char*>(&num) == 1;
9444 }
9445
9447 // binary reader //
9449
9453 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType, InputAdapterType>>
9455 using number_integer_t = typename BasicJsonType::number_integer_t;
9456 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9457 using number_float_t = typename BasicJsonType::number_float_t;
9458 using string_t = typename BasicJsonType::string_t;
9459 using binary_t = typename BasicJsonType::binary_t;
9460 using json_sax_t = SAX;
9461 using char_type = typename InputAdapterType::char_type;
9462 using char_int_type = typename char_traits<char_type>::int_type;
9463
9464 public:
9470 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format) {
9472 }
9473
9474 // make class move-only
9475 binary_reader(const binary_reader&) = delete;
9476 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9477 binary_reader& operator=(const binary_reader&) = delete;
9478 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9479 ~binary_reader() = default;
9480
9489 JSON_HEDLEY_NON_NULL(3)
9490 bool sax_parse(const input_format_t format,
9491 json_sax_t* sax_,
9492 const bool strict = true,
9493 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) {
9494 sax = sax_;
9495 bool result = false;
9496
9497 switch (format) {
9498 case input_format_t::bson:
9499 result = parse_bson_internal();
9500 break;
9501
9502 case input_format_t::cbor:
9503 result = parse_cbor_internal(true, tag_handler);
9504 break;
9505
9506 case input_format_t::msgpack:
9507 result = parse_msgpack_internal();
9508 break;
9509
9510 case input_format_t::ubjson:
9511 case input_format_t::bjdata:
9512 result = parse_ubjson_internal();
9513 break;
9514
9515 case input_format_t::json: // LCOV_EXCL_LINE
9516 default: // LCOV_EXCL_LINE
9517 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9518 }
9519
9520 // strict mode: next byte must be EOF
9521 if (result && strict) {
9522 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata) {
9523 get_ignore_noop();
9524 }
9525 else {
9526 get();
9527 }
9528
9529 if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof())) {
9530 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9531 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9532 }
9533 }
9534
9535 return result;
9536 }
9537
9538 private:
9540 // BSON //
9542
9547 bool parse_bson_internal() {
9548 std::int32_t document_size{};
9549 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9550
9551 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size()))) {
9552 return false;
9553 }
9554
9555 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) {
9556 return false;
9557 }
9558
9559 return sax->end_object();
9560 }
9561
9569 bool get_bson_cstr(string_t& result) {
9570 auto out = std::back_inserter(result);
9571 while (true) {
9572 get();
9573 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) {
9574 return false;
9575 }
9576 if (current == 0x00) {
9577 return true;
9578 }
9579 *out++ = static_cast<typename string_t::value_type>(current);
9580 }
9581 }
9582
9594 template<typename NumberType>
9595 bool get_bson_string(const NumberType len, string_t& result) {
9596 if (JSON_HEDLEY_UNLIKELY(len < 1)) {
9597 auto last_token = get_token_string();
9598 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9599 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
9600 }
9601
9602 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
9603 }
9604
9614 template<typename NumberType>
9615 bool get_bson_binary(const NumberType len, binary_t& result) {
9616 if (JSON_HEDLEY_UNLIKELY(len < 0)) {
9617 auto last_token = get_token_string();
9618 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9619 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
9620 }
9621
9622 // All BSON binary values have a subtype
9623 std::uint8_t subtype{};
9624 get_number<std::uint8_t>(input_format_t::bson, subtype);
9625 result.set_subtype(subtype);
9626
9627 return get_binary(input_format_t::bson, len, result);
9628 }
9629
9640 bool parse_bson_element_internal(const char_int_type element_type,
9641 const std::size_t element_type_parse_position) {
9642 switch (element_type) {
9643 case 0x01: // double
9644 {
9645 double number{};
9646 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9647 }
9648
9649 case 0x02: // string
9650 {
9651 std::int32_t len{};
9652 string_t value;
9653 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
9654 }
9655
9656 case 0x03: // object
9657 {
9658 return parse_bson_internal();
9659 }
9660
9661 case 0x04: // array
9662 {
9663 return parse_bson_array();
9664 }
9665
9666 case 0x05: // binary
9667 {
9668 std::int32_t len{};
9669 binary_t value;
9670 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9671 }
9672
9673 case 0x08: // boolean
9674 {
9675 return sax->boolean(get() != 0);
9676 }
9677
9678 case 0x0A: // null
9679 {
9680 return sax->null();
9681 }
9682
9683 case 0x10: // int32
9684 {
9685 std::int32_t value{};
9686 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9687 }
9688
9689 case 0x12: // int64
9690 {
9691 std::int64_t value{};
9692 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9693 }
9694
9695 case 0x11: // uint64
9696 {
9697 std::uint64_t value{};
9698 return get_number<std::uint64_t, true>(input_format_t::bson, value) && sax->number_unsigned(value);
9699 }
9700
9701 default: // anything else is not supported (yet)
9702 {
9703 std::array<char, 3> cr{ {} };
9704 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9705 const std::string cr_str{ cr.data() };
9706 return sax->parse_error(element_type_parse_position, cr_str,
9707 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
9708 }
9709 }
9710 }
9711
9724 bool parse_bson_element_list(const bool is_array) {
9725 string_t key;
9726
9727 while (auto element_type = get()) {
9728 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) {
9729 return false;
9730 }
9731
9732 const std::size_t element_type_parse_position = chars_read;
9733 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) {
9734 return false;
9735 }
9736
9737 if (!is_array && !sax->key(key)) {
9738 return false;
9739 }
9740
9741 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) {
9742 return false;
9743 }
9744
9745 // get_bson_cstr only appends
9746 key.clear();
9747 }
9748
9749 return true;
9750 }
9751
9756 bool parse_bson_array() {
9757 std::int32_t document_size{};
9758 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9759
9760 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size()))) {
9761 return false;
9762 }
9763
9764 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) {
9765 return false;
9766 }
9767
9768 return sax->end_array();
9769 }
9770
9772 // CBOR //
9774
9783
9784 template<typename NumberType>
9785 bool get_cbor_negative_integer() {
9786 NumberType number{};
9787 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, number))) {
9788 return false;
9789 }
9790 const auto max_val = static_cast<NumberType>((std::numeric_limits<number_integer_t>::max)());
9791 if (number > max_val) {
9792 return sax->parse_error(chars_read, get_token_string(),
9793 parse_error::create(112, chars_read,
9794 exception_message(input_format_t::cbor, "negative integer overflow", "value"), nullptr));
9795 }
9796 return sax->number_integer(static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(number));
9797 }
9798
9799 bool parse_cbor_internal(const bool get_char,
9800 const cbor_tag_handler_t tag_handler) {
9801 switch (get_char ? get() : current) {
9802 // EOF
9803 case char_traits<char_type>::eof():
9804 return unexpect_eof(input_format_t::cbor, "value");
9805
9806 // Integer 0x00..0x17 (0..23)
9807 case 0x00:
9808 case 0x01:
9809 case 0x02:
9810 case 0x03:
9811 case 0x04:
9812 case 0x05:
9813 case 0x06:
9814 case 0x07:
9815 case 0x08:
9816 case 0x09:
9817 case 0x0A:
9818 case 0x0B:
9819 case 0x0C:
9820 case 0x0D:
9821 case 0x0E:
9822 case 0x0F:
9823 case 0x10:
9824 case 0x11:
9825 case 0x12:
9826 case 0x13:
9827 case 0x14:
9828 case 0x15:
9829 case 0x16:
9830 case 0x17:
9831 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9832
9833 case 0x18: // Unsigned integer (one-byte uint8_t follows)
9834 {
9835 std::uint8_t number{};
9836 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9837 }
9838
9839 case 0x19: // Unsigned integer (two-byte uint16_t follows)
9840 {
9841 std::uint16_t number{};
9842 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9843 }
9844
9845 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9846 {
9847 std::uint32_t number{};
9848 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9849 }
9850
9851 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9852 {
9853 std::uint64_t number{};
9854 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9855 }
9856
9857 // Negative integer -1-0x00..-1-0x17 (-1..-24)
9858 case 0x20:
9859 case 0x21:
9860 case 0x22:
9861 case 0x23:
9862 case 0x24:
9863 case 0x25:
9864 case 0x26:
9865 case 0x27:
9866 case 0x28:
9867 case 0x29:
9868 case 0x2A:
9869 case 0x2B:
9870 case 0x2C:
9871 case 0x2D:
9872 case 0x2E:
9873 case 0x2F:
9874 case 0x30:
9875 case 0x31:
9876 case 0x32:
9877 case 0x33:
9878 case 0x34:
9879 case 0x35:
9880 case 0x36:
9881 case 0x37:
9882 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9883
9884 case 0x38: // Negative integer (one-byte uint8_t follows)
9885 return get_cbor_negative_integer<std::uint8_t>();
9886
9887 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9888 return get_cbor_negative_integer<std::uint16_t>();
9889
9890 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9891 return get_cbor_negative_integer<std::uint32_t>();
9892
9893 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9894 return get_cbor_negative_integer<std::uint64_t>();
9895
9896 // Binary data (0x00..0x17 bytes follow)
9897 case 0x40:
9898 case 0x41:
9899 case 0x42:
9900 case 0x43:
9901 case 0x44:
9902 case 0x45:
9903 case 0x46:
9904 case 0x47:
9905 case 0x48:
9906 case 0x49:
9907 case 0x4A:
9908 case 0x4B:
9909 case 0x4C:
9910 case 0x4D:
9911 case 0x4E:
9912 case 0x4F:
9913 case 0x50:
9914 case 0x51:
9915 case 0x52:
9916 case 0x53:
9917 case 0x54:
9918 case 0x55:
9919 case 0x56:
9920 case 0x57:
9921 case 0x58: // Binary data (one-byte uint8_t for n follows)
9922 case 0x59: // Binary data (two-byte uint16_t for n follow)
9923 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9924 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9925 case 0x5F: // Binary data (indefinite length)
9926 {
9927 binary_t b;
9928 return get_cbor_binary(b) && sax->binary(b);
9929 }
9930
9931 // UTF-8 string (0x00..0x17 bytes follow)
9932 case 0x60:
9933 case 0x61:
9934 case 0x62:
9935 case 0x63:
9936 case 0x64:
9937 case 0x65:
9938 case 0x66:
9939 case 0x67:
9940 case 0x68:
9941 case 0x69:
9942 case 0x6A:
9943 case 0x6B:
9944 case 0x6C:
9945 case 0x6D:
9946 case 0x6E:
9947 case 0x6F:
9948 case 0x70:
9949 case 0x71:
9950 case 0x72:
9951 case 0x73:
9952 case 0x74:
9953 case 0x75:
9954 case 0x76:
9955 case 0x77:
9956 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9957 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9958 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9959 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9960 case 0x7F: // UTF-8 string (indefinite length)
9961 {
9962 string_t s;
9963 return get_cbor_string(s) && sax->string(s);
9964 }
9965
9966 // array (0x00..0x17 data items follow)
9967 case 0x80:
9968 case 0x81:
9969 case 0x82:
9970 case 0x83:
9971 case 0x84:
9972 case 0x85:
9973 case 0x86:
9974 case 0x87:
9975 case 0x88:
9976 case 0x89:
9977 case 0x8A:
9978 case 0x8B:
9979 case 0x8C:
9980 case 0x8D:
9981 case 0x8E:
9982 case 0x8F:
9983 case 0x90:
9984 case 0x91:
9985 case 0x92:
9986 case 0x93:
9987 case 0x94:
9988 case 0x95:
9989 case 0x96:
9990 case 0x97:
9991 return get_cbor_array(
9992 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9993
9994 case 0x98: // array (one-byte uint8_t for n follows)
9995 {
9996 std::uint8_t len{};
9997 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9998 }
9999
10000 case 0x99: // array (two-byte uint16_t for n follow)
10001 {
10002 std::uint16_t len{};
10003 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10004 }
10005
10006 case 0x9A: // array (four-byte uint32_t for n follow)
10007 {
10008 std::uint32_t len{};
10009 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10010 }
10011
10012 case 0x9B: // array (eight-byte uint64_t for n follow)
10013 {
10014 std::uint64_t len{};
10015 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10016 }
10017
10018 case 0x9F: // array (indefinite length)
10019 return get_cbor_array(detail::unknown_size(), tag_handler);
10020
10021 // map (0x00..0x17 pairs of data items follow)
10022 case 0xA0:
10023 case 0xA1:
10024 case 0xA2:
10025 case 0xA3:
10026 case 0xA4:
10027 case 0xA5:
10028 case 0xA6:
10029 case 0xA7:
10030 case 0xA8:
10031 case 0xA9:
10032 case 0xAA:
10033 case 0xAB:
10034 case 0xAC:
10035 case 0xAD:
10036 case 0xAE:
10037 case 0xAF:
10038 case 0xB0:
10039 case 0xB1:
10040 case 0xB2:
10041 case 0xB3:
10042 case 0xB4:
10043 case 0xB5:
10044 case 0xB6:
10045 case 0xB7:
10046 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10047
10048 case 0xB8: // map (one-byte uint8_t for n follows)
10049 {
10050 std::uint8_t len{};
10051 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10052 }
10053
10054 case 0xB9: // map (two-byte uint16_t for n follow)
10055 {
10056 std::uint16_t len{};
10057 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10058 }
10059
10060 case 0xBA: // map (four-byte uint32_t for n follow)
10061 {
10062 std::uint32_t len{};
10063 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10064 }
10065
10066 case 0xBB: // map (eight-byte uint64_t for n follow)
10067 {
10068 std::uint64_t len{};
10069 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10070 }
10071
10072 case 0xBF: // map (indefinite length)
10073 return get_cbor_object(detail::unknown_size(), tag_handler);
10074
10075 case 0xC6: // tagged item
10076 case 0xC7:
10077 case 0xC8:
10078 case 0xC9:
10079 case 0xCA:
10080 case 0xCB:
10081 case 0xCC:
10082 case 0xCD:
10083 case 0xCE:
10084 case 0xCF:
10085 case 0xD0:
10086 case 0xD1:
10087 case 0xD2:
10088 case 0xD3:
10089 case 0xD4:
10090 case 0xD8: // tagged item (1 byte follows)
10091 case 0xD9: // tagged item (2 bytes follow)
10092 case 0xDA: // tagged item (4 bytes follow)
10093 case 0xDB: // tagged item (8 bytes follow)
10094 {
10095 switch (tag_handler) {
10096 case cbor_tag_handler_t::error:
10097 {
10098 auto last_token = get_token_string();
10099 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10100 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10101 }
10102
10103 case cbor_tag_handler_t::ignore:
10104 {
10105 // ignore binary subtype
10106 switch (current) {
10107 case 0xD8:
10108 {
10109 std::uint8_t subtype_to_ignore{};
10110 get_number(input_format_t::cbor, subtype_to_ignore);
10111 break;
10112 }
10113 case 0xD9:
10114 {
10115 std::uint16_t subtype_to_ignore{};
10116 get_number(input_format_t::cbor, subtype_to_ignore);
10117 break;
10118 }
10119 case 0xDA:
10120 {
10121 std::uint32_t subtype_to_ignore{};
10122 get_number(input_format_t::cbor, subtype_to_ignore);
10123 break;
10124 }
10125 case 0xDB:
10126 {
10127 std::uint64_t subtype_to_ignore{};
10128 get_number(input_format_t::cbor, subtype_to_ignore);
10129 break;
10130 }
10131 default:
10132 break;
10133 }
10134 return parse_cbor_internal(true, tag_handler);
10135 }
10136
10137 case cbor_tag_handler_t::store:
10138 {
10139 binary_t b;
10140 // use binary subtype and store in a binary container
10141 switch (current) {
10142 case 0xD8:
10143 {
10144 std::uint8_t subtype{};
10145 get_number(input_format_t::cbor, subtype);
10146 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10147 break;
10148 }
10149 case 0xD9:
10150 {
10151 std::uint16_t subtype{};
10152 get_number(input_format_t::cbor, subtype);
10153 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10154 break;
10155 }
10156 case 0xDA:
10157 {
10158 std::uint32_t subtype{};
10159 get_number(input_format_t::cbor, subtype);
10160 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10161 break;
10162 }
10163 case 0xDB:
10164 {
10165 std::uint64_t subtype{};
10166 get_number(input_format_t::cbor, subtype);
10167 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10168 break;
10169 }
10170 default:
10171 return parse_cbor_internal(true, tag_handler);
10172 }
10173 get();
10174 return get_cbor_binary(b) && sax->binary(b);
10175 }
10176
10177 default: // LCOV_EXCL_LINE
10178 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10179 return false; // LCOV_EXCL_LINE
10180 }
10181 }
10182
10183 case 0xF4: // false
10184 return sax->boolean(false);
10185
10186 case 0xF5: // true
10187 return sax->boolean(true);
10188
10189 case 0xF6: // null
10190 return sax->null();
10191
10192 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10193 {
10194 const auto byte1_raw = get();
10195 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) {
10196 return false;
10197 }
10198 const auto byte2_raw = get();
10199 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) {
10200 return false;
10201 }
10202
10203 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10204 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10205
10206 // Code from RFC 7049, Appendix D, Figure 3:
10207 // As half-precision floating-point numbers were only added
10208 // to IEEE 754 in 2008, today's programming platforms often
10209 // still only have limited support for them. It is very
10210 // easy to include at least decoding support for them even
10211 // without such support. An example of a small decoder for
10212 // half-precision floating-point numbers in the C language
10213 // is shown in Fig. 3.
10214 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10215 const double val = [&half] {
10216 const int exp = (half >> 10u) & 0x1Fu;
10217 const unsigned int mant = half & 0x3FFu;
10218 JSON_ASSERT(0 <= exp && exp <= 32);
10219 JSON_ASSERT(mant <= 1024);
10220 switch (exp) {
10221 case 0:
10222 return std::ldexp(mant, -24);
10223 case 31:
10224 return (mant == 0)
10225 ? std::numeric_limits<double>::infinity()
10226 : std::numeric_limits<double>::quiet_NaN();
10227 default:
10228 return std::ldexp(mant + 1024, exp - 25);
10229 }
10230 }();
10231 return sax->number_float((half & 0x8000u) != 0
10232 ? static_cast<number_float_t>(-val)
10233 : static_cast<number_float_t>(val), "");
10234 }
10235
10236 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10237 {
10238 float number{};
10239 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10240 }
10241
10242 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10243 {
10244 double number{};
10245 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10246 }
10247
10248 default: // anything else (0xFF is handled inside the other types)
10249 {
10250 auto last_token = get_token_string();
10251 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10252 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10253 }
10254 }
10255 }
10256
10268 bool get_cbor_string(string_t& result) {
10269 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) {
10270 return false;
10271 }
10272
10273 switch (current) {
10274 // UTF-8 string (0x00..0x17 bytes follow)
10275 case 0x60:
10276 case 0x61:
10277 case 0x62:
10278 case 0x63:
10279 case 0x64:
10280 case 0x65:
10281 case 0x66:
10282 case 0x67:
10283 case 0x68:
10284 case 0x69:
10285 case 0x6A:
10286 case 0x6B:
10287 case 0x6C:
10288 case 0x6D:
10289 case 0x6E:
10290 case 0x6F:
10291 case 0x70:
10292 case 0x71:
10293 case 0x72:
10294 case 0x73:
10295 case 0x74:
10296 case 0x75:
10297 case 0x76:
10298 case 0x77:
10299 {
10300 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10301 }
10302
10303 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10304 {
10305 std::uint8_t len{};
10306 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10307 }
10308
10309 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10310 {
10311 std::uint16_t len{};
10312 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10313 }
10314
10315 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10316 {
10317 std::uint32_t len{};
10318 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10319 }
10320
10321 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10322 {
10323 std::uint64_t len{};
10324 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10325 }
10326
10327 case 0x7F: // UTF-8 string (indefinite length)
10328 {
10329 while (get() != 0xFF) {
10330 string_t chunk;
10331 if (!get_cbor_string(chunk)) {
10332 return false;
10333 }
10334 result.append(chunk);
10335 }
10336 return true;
10337 }
10338
10339 default:
10340 {
10341 auto last_token = get_token_string();
10342 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10343 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10344 }
10345 }
10346 }
10347
10359 bool get_cbor_binary(binary_t& result) {
10360 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) {
10361 return false;
10362 }
10363
10364 switch (current) {
10365 // Binary data (0x00..0x17 bytes follow)
10366 case 0x40:
10367 case 0x41:
10368 case 0x42:
10369 case 0x43:
10370 case 0x44:
10371 case 0x45:
10372 case 0x46:
10373 case 0x47:
10374 case 0x48:
10375 case 0x49:
10376 case 0x4A:
10377 case 0x4B:
10378 case 0x4C:
10379 case 0x4D:
10380 case 0x4E:
10381 case 0x4F:
10382 case 0x50:
10383 case 0x51:
10384 case 0x52:
10385 case 0x53:
10386 case 0x54:
10387 case 0x55:
10388 case 0x56:
10389 case 0x57:
10390 {
10391 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10392 }
10393
10394 case 0x58: // Binary data (one-byte uint8_t for n follows)
10395 {
10396 std::uint8_t len{};
10397 return get_number(input_format_t::cbor, len) &&
10398 get_binary(input_format_t::cbor, len, result);
10399 }
10400
10401 case 0x59: // Binary data (two-byte uint16_t for n follow)
10402 {
10403 std::uint16_t len{};
10404 return get_number(input_format_t::cbor, len) &&
10405 get_binary(input_format_t::cbor, len, result);
10406 }
10407
10408 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10409 {
10410 std::uint32_t len{};
10411 return get_number(input_format_t::cbor, len) &&
10412 get_binary(input_format_t::cbor, len, result);
10413 }
10414
10415 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10416 {
10417 std::uint64_t len{};
10418 return get_number(input_format_t::cbor, len) &&
10419 get_binary(input_format_t::cbor, len, result);
10420 }
10421
10422 case 0x5F: // Binary data (indefinite length)
10423 {
10424 while (get() != 0xFF) {
10425 binary_t chunk;
10426 if (!get_cbor_binary(chunk)) {
10427 return false;
10428 }
10429 result.insert(result.end(), chunk.begin(), chunk.end());
10430 }
10431 return true;
10432 }
10433
10434 default:
10435 {
10436 auto last_token = get_token_string();
10437 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10438 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));
10439 }
10440 }
10441 }
10442
10449 bool get_cbor_array(const std::size_t len,
10450 const cbor_tag_handler_t tag_handler) {
10451 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) {
10452 return false;
10453 }
10454
10455 if (len != detail::unknown_size()) {
10456 for (std::size_t i = 0; i < len; ++i) {
10457 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) {
10458 return false;
10459 }
10460 }
10461 }
10462 else {
10463 while (get() != 0xFF) {
10464 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) {
10465 return false;
10466 }
10467 }
10468 }
10469
10470 return sax->end_array();
10471 }
10472
10479 bool get_cbor_object(const std::size_t len,
10480 const cbor_tag_handler_t tag_handler) {
10481 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) {
10482 return false;
10483 }
10484
10485 if (len != 0) {
10486 string_t key;
10487 if (len != detail::unknown_size()) {
10488 for (std::size_t i = 0; i < len; ++i) {
10489 get();
10490 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) {
10491 return false;
10492 }
10493
10494 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) {
10495 return false;
10496 }
10497 key.clear();
10498 }
10499 }
10500 else {
10501 while (get() != 0xFF) {
10502 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) {
10503 return false;
10504 }
10505
10506 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) {
10507 return false;
10508 }
10509 key.clear();
10510 }
10511 }
10512 }
10513
10514 return sax->end_object();
10515 }
10516
10518 // MsgPack //
10520
10524 bool parse_msgpack_internal() {
10525 switch (get()) {
10526 // EOF
10527 case char_traits<char_type>::eof():
10528 return unexpect_eof(input_format_t::msgpack, "value");
10529
10530 // positive fixint
10531 case 0x00:
10532 case 0x01:
10533 case 0x02:
10534 case 0x03:
10535 case 0x04:
10536 case 0x05:
10537 case 0x06:
10538 case 0x07:
10539 case 0x08:
10540 case 0x09:
10541 case 0x0A:
10542 case 0x0B:
10543 case 0x0C:
10544 case 0x0D:
10545 case 0x0E:
10546 case 0x0F:
10547 case 0x10:
10548 case 0x11:
10549 case 0x12:
10550 case 0x13:
10551 case 0x14:
10552 case 0x15:
10553 case 0x16:
10554 case 0x17:
10555 case 0x18:
10556 case 0x19:
10557 case 0x1A:
10558 case 0x1B:
10559 case 0x1C:
10560 case 0x1D:
10561 case 0x1E:
10562 case 0x1F:
10563 case 0x20:
10564 case 0x21:
10565 case 0x22:
10566 case 0x23:
10567 case 0x24:
10568 case 0x25:
10569 case 0x26:
10570 case 0x27:
10571 case 0x28:
10572 case 0x29:
10573 case 0x2A:
10574 case 0x2B:
10575 case 0x2C:
10576 case 0x2D:
10577 case 0x2E:
10578 case 0x2F:
10579 case 0x30:
10580 case 0x31:
10581 case 0x32:
10582 case 0x33:
10583 case 0x34:
10584 case 0x35:
10585 case 0x36:
10586 case 0x37:
10587 case 0x38:
10588 case 0x39:
10589 case 0x3A:
10590 case 0x3B:
10591 case 0x3C:
10592 case 0x3D:
10593 case 0x3E:
10594 case 0x3F:
10595 case 0x40:
10596 case 0x41:
10597 case 0x42:
10598 case 0x43:
10599 case 0x44:
10600 case 0x45:
10601 case 0x46:
10602 case 0x47:
10603 case 0x48:
10604 case 0x49:
10605 case 0x4A:
10606 case 0x4B:
10607 case 0x4C:
10608 case 0x4D:
10609 case 0x4E:
10610 case 0x4F:
10611 case 0x50:
10612 case 0x51:
10613 case 0x52:
10614 case 0x53:
10615 case 0x54:
10616 case 0x55:
10617 case 0x56:
10618 case 0x57:
10619 case 0x58:
10620 case 0x59:
10621 case 0x5A:
10622 case 0x5B:
10623 case 0x5C:
10624 case 0x5D:
10625 case 0x5E:
10626 case 0x5F:
10627 case 0x60:
10628 case 0x61:
10629 case 0x62:
10630 case 0x63:
10631 case 0x64:
10632 case 0x65:
10633 case 0x66:
10634 case 0x67:
10635 case 0x68:
10636 case 0x69:
10637 case 0x6A:
10638 case 0x6B:
10639 case 0x6C:
10640 case 0x6D:
10641 case 0x6E:
10642 case 0x6F:
10643 case 0x70:
10644 case 0x71:
10645 case 0x72:
10646 case 0x73:
10647 case 0x74:
10648 case 0x75:
10649 case 0x76:
10650 case 0x77:
10651 case 0x78:
10652 case 0x79:
10653 case 0x7A:
10654 case 0x7B:
10655 case 0x7C:
10656 case 0x7D:
10657 case 0x7E:
10658 case 0x7F:
10659 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10660
10661 // fixmap
10662 case 0x80:
10663 case 0x81:
10664 case 0x82:
10665 case 0x83:
10666 case 0x84:
10667 case 0x85:
10668 case 0x86:
10669 case 0x87:
10670 case 0x88:
10671 case 0x89:
10672 case 0x8A:
10673 case 0x8B:
10674 case 0x8C:
10675 case 0x8D:
10676 case 0x8E:
10677 case 0x8F:
10678 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10679
10680 // fixarray
10681 case 0x90:
10682 case 0x91:
10683 case 0x92:
10684 case 0x93:
10685 case 0x94:
10686 case 0x95:
10687 case 0x96:
10688 case 0x97:
10689 case 0x98:
10690 case 0x99:
10691 case 0x9A:
10692 case 0x9B:
10693 case 0x9C:
10694 case 0x9D:
10695 case 0x9E:
10696 case 0x9F:
10697 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10698
10699 // fixstr
10700 case 0xA0:
10701 case 0xA1:
10702 case 0xA2:
10703 case 0xA3:
10704 case 0xA4:
10705 case 0xA5:
10706 case 0xA6:
10707 case 0xA7:
10708 case 0xA8:
10709 case 0xA9:
10710 case 0xAA:
10711 case 0xAB:
10712 case 0xAC:
10713 case 0xAD:
10714 case 0xAE:
10715 case 0xAF:
10716 case 0xB0:
10717 case 0xB1:
10718 case 0xB2:
10719 case 0xB3:
10720 case 0xB4:
10721 case 0xB5:
10722 case 0xB6:
10723 case 0xB7:
10724 case 0xB8:
10725 case 0xB9:
10726 case 0xBA:
10727 case 0xBB:
10728 case 0xBC:
10729 case 0xBD:
10730 case 0xBE:
10731 case 0xBF:
10732 case 0xD9: // str 8
10733 case 0xDA: // str 16
10734 case 0xDB: // str 32
10735 {
10736 string_t s;
10737 return get_msgpack_string(s) && sax->string(s);
10738 }
10739
10740 case 0xC0: // nil
10741 return sax->null();
10742
10743 case 0xC2: // false
10744 return sax->boolean(false);
10745
10746 case 0xC3: // true
10747 return sax->boolean(true);
10748
10749 case 0xC4: // bin 8
10750 case 0xC5: // bin 16
10751 case 0xC6: // bin 32
10752 case 0xC7: // ext 8
10753 case 0xC8: // ext 16
10754 case 0xC9: // ext 32
10755 case 0xD4: // fixext 1
10756 case 0xD5: // fixext 2
10757 case 0xD6: // fixext 4
10758 case 0xD7: // fixext 8
10759 case 0xD8: // fixext 16
10760 {
10761 binary_t b;
10762 return get_msgpack_binary(b) && sax->binary(b);
10763 }
10764
10765 case 0xCA: // float 32
10766 {
10767 float number{};
10768 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10769 }
10770
10771 case 0xCB: // float 64
10772 {
10773 double number{};
10774 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10775 }
10776
10777 case 0xCC: // uint 8
10778 {
10779 std::uint8_t number{};
10780 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10781 }
10782
10783 case 0xCD: // uint 16
10784 {
10785 std::uint16_t number{};
10786 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10787 }
10788
10789 case 0xCE: // uint 32
10790 {
10791 std::uint32_t number{};
10792 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10793 }
10794
10795 case 0xCF: // uint 64
10796 {
10797 std::uint64_t number{};
10798 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10799 }
10800
10801 case 0xD0: // int 8
10802 {
10803 std::int8_t number{};
10804 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10805 }
10806
10807 case 0xD1: // int 16
10808 {
10809 std::int16_t number{};
10810 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10811 }
10812
10813 case 0xD2: // int 32
10814 {
10815 std::int32_t number{};
10816 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10817 }
10818
10819 case 0xD3: // int 64
10820 {
10821 std::int64_t number{};
10822 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10823 }
10824
10825 case 0xDC: // array 16
10826 {
10827 std::uint16_t len{};
10828 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
10829 }
10830
10831 case 0xDD: // array 32
10832 {
10833 std::uint32_t len{};
10834 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10835 }
10836
10837 case 0xDE: // map 16
10838 {
10839 std::uint16_t len{};
10840 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
10841 }
10842
10843 case 0xDF: // map 32
10844 {
10845 std::uint32_t len{};
10846 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10847 }
10848
10849 // negative fixint
10850 case 0xE0:
10851 case 0xE1:
10852 case 0xE2:
10853 case 0xE3:
10854 case 0xE4:
10855 case 0xE5:
10856 case 0xE6:
10857 case 0xE7:
10858 case 0xE8:
10859 case 0xE9:
10860 case 0xEA:
10861 case 0xEB:
10862 case 0xEC:
10863 case 0xED:
10864 case 0xEE:
10865 case 0xEF:
10866 case 0xF0:
10867 case 0xF1:
10868 case 0xF2:
10869 case 0xF3:
10870 case 0xF4:
10871 case 0xF5:
10872 case 0xF6:
10873 case 0xF7:
10874 case 0xF8:
10875 case 0xF9:
10876 case 0xFA:
10877 case 0xFB:
10878 case 0xFC:
10879 case 0xFD:
10880 case 0xFE:
10881 case 0xFF:
10882 return sax->number_integer(static_cast<std::int8_t>(current));
10883
10884 default: // anything else
10885 {
10886 auto last_token = get_token_string();
10887 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10888 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
10889 }
10890 }
10891 }
10892
10903 bool get_msgpack_string(string_t& result) {
10904 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) {
10905 return false;
10906 }
10907
10908 switch (current) {
10909 // fixstr
10910 case 0xA0:
10911 case 0xA1:
10912 case 0xA2:
10913 case 0xA3:
10914 case 0xA4:
10915 case 0xA5:
10916 case 0xA6:
10917 case 0xA7:
10918 case 0xA8:
10919 case 0xA9:
10920 case 0xAA:
10921 case 0xAB:
10922 case 0xAC:
10923 case 0xAD:
10924 case 0xAE:
10925 case 0xAF:
10926 case 0xB0:
10927 case 0xB1:
10928 case 0xB2:
10929 case 0xB3:
10930 case 0xB4:
10931 case 0xB5:
10932 case 0xB6:
10933 case 0xB7:
10934 case 0xB8:
10935 case 0xB9:
10936 case 0xBA:
10937 case 0xBB:
10938 case 0xBC:
10939 case 0xBD:
10940 case 0xBE:
10941 case 0xBF:
10942 {
10943 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
10944 }
10945
10946 case 0xD9: // str 8
10947 {
10948 std::uint8_t len{};
10949 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10950 }
10951
10952 case 0xDA: // str 16
10953 {
10954 std::uint16_t len{};
10955 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10956 }
10957
10958 case 0xDB: // str 32
10959 {
10960 std::uint32_t len{};
10961 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10962 }
10963
10964 default:
10965 {
10966 auto last_token = get_token_string();
10967 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10968 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
10969 }
10970 }
10971 }
10972
10983 bool get_msgpack_binary(binary_t& result) {
10984 // helper function to set the subtype
10985 auto assign_and_return_true = [&result](std::int8_t subtype) {
10986 result.set_subtype(static_cast<std::uint8_t>(subtype));
10987 return true;
10988 };
10989
10990 switch (current) {
10991 case 0xC4: // bin 8
10992 {
10993 std::uint8_t len{};
10994 return get_number(input_format_t::msgpack, len) &&
10995 get_binary(input_format_t::msgpack, len, result);
10996 }
10997
10998 case 0xC5: // bin 16
10999 {
11000 std::uint16_t len{};
11001 return get_number(input_format_t::msgpack, len) &&
11002 get_binary(input_format_t::msgpack, len, result);
11003 }
11004
11005 case 0xC6: // bin 32
11006 {
11007 std::uint32_t len{};
11008 return get_number(input_format_t::msgpack, len) &&
11009 get_binary(input_format_t::msgpack, len, result);
11010 }
11011
11012 case 0xC7: // ext 8
11013 {
11014 std::uint8_t len{};
11015 std::int8_t subtype{};
11016 return get_number(input_format_t::msgpack, len) &&
11017 get_number(input_format_t::msgpack, subtype) &&
11018 get_binary(input_format_t::msgpack, len, result) &&
11019 assign_and_return_true(subtype);
11020 }
11021
11022 case 0xC8: // ext 16
11023 {
11024 std::uint16_t len{};
11025 std::int8_t subtype{};
11026 return get_number(input_format_t::msgpack, len) &&
11027 get_number(input_format_t::msgpack, subtype) &&
11028 get_binary(input_format_t::msgpack, len, result) &&
11029 assign_and_return_true(subtype);
11030 }
11031
11032 case 0xC9: // ext 32
11033 {
11034 std::uint32_t len{};
11035 std::int8_t subtype{};
11036 return get_number(input_format_t::msgpack, len) &&
11037 get_number(input_format_t::msgpack, subtype) &&
11038 get_binary(input_format_t::msgpack, len, result) &&
11039 assign_and_return_true(subtype);
11040 }
11041
11042 case 0xD4: // fixext 1
11043 {
11044 std::int8_t subtype{};
11045 return get_number(input_format_t::msgpack, subtype) &&
11046 get_binary(input_format_t::msgpack, 1, result) &&
11047 assign_and_return_true(subtype);
11048 }
11049
11050 case 0xD5: // fixext 2
11051 {
11052 std::int8_t subtype{};
11053 return get_number(input_format_t::msgpack, subtype) &&
11054 get_binary(input_format_t::msgpack, 2, result) &&
11055 assign_and_return_true(subtype);
11056 }
11057
11058 case 0xD6: // fixext 4
11059 {
11060 std::int8_t subtype{};
11061 return get_number(input_format_t::msgpack, subtype) &&
11062 get_binary(input_format_t::msgpack, 4, result) &&
11063 assign_and_return_true(subtype);
11064 }
11065
11066 case 0xD7: // fixext 8
11067 {
11068 std::int8_t subtype{};
11069 return get_number(input_format_t::msgpack, subtype) &&
11070 get_binary(input_format_t::msgpack, 8, result) &&
11071 assign_and_return_true(subtype);
11072 }
11073
11074 case 0xD8: // fixext 16
11075 {
11076 std::int8_t subtype{};
11077 return get_number(input_format_t::msgpack, subtype) &&
11078 get_binary(input_format_t::msgpack, 16, result) &&
11079 assign_and_return_true(subtype);
11080 }
11081
11082 default: // LCOV_EXCL_LINE
11083 return false; // LCOV_EXCL_LINE
11084 }
11085 }
11086
11091 bool get_msgpack_array(const std::size_t len) {
11092 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) {
11093 return false;
11094 }
11095
11096 for (std::size_t i = 0; i < len; ++i) {
11097 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) {
11098 return false;
11099 }
11100 }
11101
11102 return sax->end_array();
11103 }
11104
11109 bool get_msgpack_object(const std::size_t len) {
11110 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) {
11111 return false;
11112 }
11113
11114 string_t key;
11115 for (std::size_t i = 0; i < len; ++i) {
11116 get();
11117 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) {
11118 return false;
11119 }
11120
11121 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) {
11122 return false;
11123 }
11124 key.clear();
11125 }
11126
11127 return sax->end_object();
11128 }
11129
11131 // UBJSON //
11133
11141 bool parse_ubjson_internal(const bool get_char = true) {
11142 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11143 }
11144
11159 bool get_ubjson_string(string_t& result, const bool get_char = true) {
11160 if (get_char) {
11161 get(); // TODO(niels): may we ignore N here?
11162 }
11163
11164 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) {
11165 return false;
11166 }
11167
11168 switch (current) {
11169 case 'U':
11170 {
11171 std::uint8_t len{};
11172 return get_number(input_format, len) && get_string(input_format, len, result);
11173 }
11174
11175 case 'i':
11176 {
11177 std::int8_t len{};
11178 return get_number(input_format, len) && get_string(input_format, len, result);
11179 }
11180
11181 case 'I':
11182 {
11183 std::int16_t len{};
11184 return get_number(input_format, len) && get_string(input_format, len, result);
11185 }
11186
11187 case 'l':
11188 {
11189 std::int32_t len{};
11190 return get_number(input_format, len) && get_string(input_format, len, result);
11191 }
11192
11193 case 'L':
11194 {
11195 std::int64_t len{};
11196 return get_number(input_format, len) && get_string(input_format, len, result);
11197 }
11198
11199 case 'u':
11200 {
11201 if (input_format != input_format_t::bjdata) {
11202 break;
11203 }
11204 std::uint16_t len{};
11205 return get_number(input_format, len) && get_string(input_format, len, result);
11206 }
11207
11208 case 'm':
11209 {
11210 if (input_format != input_format_t::bjdata) {
11211 break;
11212 }
11213 std::uint32_t len{};
11214 return get_number(input_format, len) && get_string(input_format, len, result);
11215 }
11216
11217 case 'M':
11218 {
11219 if (input_format != input_format_t::bjdata) {
11220 break;
11221 }
11222 std::uint64_t len{};
11223 return get_number(input_format, len) && get_string(input_format, len, result);
11224 }
11225
11226 default:
11227 break;
11228 }
11229 auto last_token = get_token_string();
11230 std::string message;
11231
11232 if (input_format != input_format_t::bjdata) {
11233 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11234 }
11235 else {
11236 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11237 }
11238 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11239 }
11240
11245 bool get_ubjson_ndarray_size(std::vector<size_t>& dim) {
11246 std::pair<std::size_t, char_int_type> size_and_type;
11247 size_t dimlen = 0;
11248 bool no_ndarray = true;
11249
11250 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray))) {
11251 return false;
11252 }
11253
11254 if (size_and_type.first != npos) {
11255 if (size_and_type.second != 0) {
11256 if (size_and_type.second != 'N') {
11257 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11258 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second))) {
11259 return false;
11260 }
11261 dim.push_back(dimlen);
11262 }
11263 }
11264 }
11265 else {
11266 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11267 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray))) {
11268 return false;
11269 }
11270 dim.push_back(dimlen);
11271 }
11272 }
11273 }
11274 else {
11275 while (current != ']') {
11276 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current))) {
11277 return false;
11278 }
11279 dim.push_back(dimlen);
11280 get_ignore_noop();
11281 }
11282 }
11283 return true;
11284 }
11285
11297 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0) {
11298 if (prefix == 0) {
11299 prefix = get_ignore_noop();
11300 }
11301
11302 switch (prefix) {
11303 case 'U':
11304 {
11305 std::uint8_t number{};
11306 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11307 return false;
11308 }
11309 result = static_cast<std::size_t>(number);
11310 return true;
11311 }
11312
11313 case 'i':
11314 {
11315 std::int8_t number{};
11316 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11317 return false;
11318 }
11319 if (number < 0) {
11320 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11321 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11322 }
11323 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11324 return true;
11325 }
11326
11327 case 'I':
11328 {
11329 std::int16_t number{};
11330 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11331 return false;
11332 }
11333 if (number < 0) {
11334 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11335 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11336 }
11337 result = static_cast<std::size_t>(number);
11338 return true;
11339 }
11340
11341 case 'l':
11342 {
11343 std::int32_t number{};
11344 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11345 return false;
11346 }
11347 if (number < 0) {
11348 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11349 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11350 }
11351 result = static_cast<std::size_t>(number);
11352 return true;
11353 }
11354
11355 case 'L':
11356 {
11357 std::int64_t number{};
11358 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11359 return false;
11360 }
11361 if (number < 0) {
11362 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11363 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11364 }
11365 if (!value_in_range_of<std::size_t>(number)) {
11366 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11367 exception_message(input_format, "integer value overflow", "size"), nullptr));
11368 }
11369 result = static_cast<std::size_t>(number);
11370 return true;
11371 }
11372
11373 case 'u':
11374 {
11375 if (input_format != input_format_t::bjdata) {
11376 break;
11377 }
11378 std::uint16_t number{};
11379 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11380 return false;
11381 }
11382 result = static_cast<std::size_t>(number);
11383 return true;
11384 }
11385
11386 case 'm':
11387 {
11388 if (input_format != input_format_t::bjdata) {
11389 break;
11390 }
11391 std::uint32_t number{};
11392 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11393 return false;
11394 }
11395 result = conditional_static_cast<std::size_t>(number);
11396 return true;
11397 }
11398
11399 case 'M':
11400 {
11401 if (input_format != input_format_t::bjdata) {
11402 break;
11403 }
11404 std::uint64_t number{};
11405 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11406 return false;
11407 }
11408 if (!value_in_range_of<std::size_t>(number)) {
11409 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11410 exception_message(input_format, "integer value overflow", "size"), nullptr));
11411 }
11412 result = detail::conditional_static_cast<std::size_t>(number);
11413 return true;
11414 }
11415
11416 case '[':
11417 {
11418 if (input_format != input_format_t::bjdata) {
11419 break;
11420 }
11421 if (is_ndarray) // ndarray dimensional vector can only contain integers and cannot embed another array
11422 {
11423 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));
11424 }
11425 std::vector<size_t> dim;
11426 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) {
11427 return false;
11428 }
11429 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11430 {
11431 result = dim.at(dim.size() - 1);
11432 return true;
11433 }
11434 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11435 {
11436 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11437 {
11438 if (i == 0) {
11439 result = 0;
11440 return true;
11441 }
11442 }
11443
11444 string_t key = "_ArraySize_";
11445 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size()))) {
11446 return false;
11447 }
11448 result = 1;
11449 for (auto i : dim) {
11450 // Pre-multiplication overflow check: if i > 0 and result > SIZE_MAX/i, then result*i would overflow.
11451 // This check must happen before multiplication since overflow detection after the fact is unreliable
11452 // as modular arithmetic can produce any value, not just 0 or SIZE_MAX.
11453 if (JSON_HEDLEY_UNLIKELY(i > 0 && result > (std::numeric_limits<std::size_t>::max)() / i)) {
11454 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));
11455 }
11456 result *= i;
11457 // Additional post-multiplication check to catch any edge cases the pre-check might miss
11458 if (result == 0 || result == npos) {
11459 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));
11460 }
11461 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i)))) {
11462 return false;
11463 }
11464 }
11465 is_ndarray = true;
11466 return sax->end_array();
11467 }
11468 result = 0;
11469 return true;
11470 }
11471
11472 default:
11473 break;
11474 }
11475 auto last_token = get_token_string();
11476 std::string message;
11477
11478 if (input_format != input_format_t::bjdata) {
11479 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11480 }
11481 else {
11482 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11483 }
11484 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
11485 }
11486
11498 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false) {
11499 result.first = npos; // size
11500 result.second = 0; // type
11501 bool is_ndarray = false;
11502
11503 get_ignore_noop();
11504
11505 if (current == '$') {
11506 result.second = get(); // must not ignore 'N', because 'N' maybe the type
11507 if (input_format == input_format_t::bjdata
11508 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second))) {
11509 auto last_token = get_token_string();
11510 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11511 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
11512 }
11513
11514 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type"))) {
11515 return false;
11516 }
11517
11518 get_ignore_noop();
11519 if (JSON_HEDLEY_UNLIKELY(current != '#')) {
11520 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) {
11521 return false;
11522 }
11523 auto last_token = get_token_string();
11524 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11525 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
11526 }
11527
11528 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11529 if (input_format == input_format_t::bjdata && is_ndarray) {
11530 if (inside_ndarray) {
11531 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11532 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
11533 }
11534 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
11535 }
11536 return is_error;
11537 }
11538
11539 if (current == '#') {
11540 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11541 if (input_format == input_format_t::bjdata && is_ndarray) {
11542 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11543 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
11544 }
11545 return is_error;
11546 }
11547
11548 return true;
11549 }
11550
11555 bool get_ubjson_value(const char_int_type prefix) {
11556 switch (prefix) {
11557 case char_traits<char_type>::eof(): // EOF
11558 return unexpect_eof(input_format, "value");
11559
11560 case 'T': // true
11561 return sax->boolean(true);
11562 case 'F': // false
11563 return sax->boolean(false);
11564
11565 case 'Z': // null
11566 return sax->null();
11567
11568 case 'B': // byte
11569 {
11570 if (input_format != input_format_t::bjdata) {
11571 break;
11572 }
11573 std::uint8_t number{};
11574 return get_number(input_format, number) && sax->number_unsigned(number);
11575 }
11576
11577 case 'U':
11578 {
11579 std::uint8_t number{};
11580 return get_number(input_format, number) && sax->number_unsigned(number);
11581 }
11582
11583 case 'i':
11584 {
11585 std::int8_t number{};
11586 return get_number(input_format, number) && sax->number_integer(number);
11587 }
11588
11589 case 'I':
11590 {
11591 std::int16_t number{};
11592 return get_number(input_format, number) && sax->number_integer(number);
11593 }
11594
11595 case 'l':
11596 {
11597 std::int32_t number{};
11598 return get_number(input_format, number) && sax->number_integer(number);
11599 }
11600
11601 case 'L':
11602 {
11603 std::int64_t number{};
11604 return get_number(input_format, number) && sax->number_integer(number);
11605 }
11606
11607 case 'u':
11608 {
11609 if (input_format != input_format_t::bjdata) {
11610 break;
11611 }
11612 std::uint16_t number{};
11613 return get_number(input_format, number) && sax->number_unsigned(number);
11614 }
11615
11616 case 'm':
11617 {
11618 if (input_format != input_format_t::bjdata) {
11619 break;
11620 }
11621 std::uint32_t number{};
11622 return get_number(input_format, number) && sax->number_unsigned(number);
11623 }
11624
11625 case 'M':
11626 {
11627 if (input_format != input_format_t::bjdata) {
11628 break;
11629 }
11630 std::uint64_t number{};
11631 return get_number(input_format, number) && sax->number_unsigned(number);
11632 }
11633
11634 case 'h':
11635 {
11636 if (input_format != input_format_t::bjdata) {
11637 break;
11638 }
11639 const auto byte1_raw = get();
11640 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) {
11641 return false;
11642 }
11643 const auto byte2_raw = get();
11644 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) {
11645 return false;
11646 }
11647
11648 const auto byte1 = static_cast<unsigned char>(byte1_raw);
11649 const auto byte2 = static_cast<unsigned char>(byte2_raw);
11650
11651 // Code from RFC 7049, Appendix D, Figure 3:
11652 // As half-precision floating-point numbers were only added
11653 // to IEEE 754 in 2008, today's programming platforms often
11654 // still only have limited support for them. It is very
11655 // easy to include at least decoding support for them even
11656 // without such support. An example of a small decoder for
11657 // half-precision floating-point numbers in the C language
11658 // is shown in Fig. 3.
11659 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11660 const double val = [&half] {
11661 const int exp = (half >> 10u) & 0x1Fu;
11662 const unsigned int mant = half & 0x3FFu;
11663 JSON_ASSERT(0 <= exp && exp <= 32);
11664 JSON_ASSERT(mant <= 1024);
11665 switch (exp) {
11666 case 0:
11667 return std::ldexp(mant, -24);
11668 case 31:
11669 return (mant == 0)
11670 ? std::numeric_limits<double>::infinity()
11671 : std::numeric_limits<double>::quiet_NaN();
11672 default:
11673 return std::ldexp(mant + 1024, exp - 25);
11674 }
11675 }();
11676 return sax->number_float((half & 0x8000u) != 0
11677 ? static_cast<number_float_t>(-val)
11678 : static_cast<number_float_t>(val), "");
11679 }
11680
11681 case 'd':
11682 {
11683 float number{};
11684 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11685 }
11686
11687 case 'D':
11688 {
11689 double number{};
11690 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11691 }
11692
11693 case 'H':
11694 {
11695 return get_ubjson_high_precision_number();
11696 }
11697
11698 case 'C': // char
11699 {
11700 get();
11701 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char"))) {
11702 return false;
11703 }
11704 if (JSON_HEDLEY_UNLIKELY(current > 127)) {
11705 auto last_token = get_token_string();
11706 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11707 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
11708 }
11709 string_t s(1, static_cast<typename string_t::value_type>(current));
11710 return sax->string(s);
11711 }
11712
11713 case 'S': // string
11714 {
11715 string_t s;
11716 return get_ubjson_string(s) && sax->string(s);
11717 }
11718
11719 case '[': // array
11720 return get_ubjson_array();
11721
11722 case '{': // object
11723 return get_ubjson_object();
11724
11725 default: // anything else
11726 break;
11727 }
11728 auto last_token = get_token_string();
11729 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));
11730 }
11731
11735 bool get_ubjson_array() {
11736 std::pair<std::size_t, char_int_type> size_and_type;
11737 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) {
11738 return false;
11739 }
11740
11741 // 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):
11742 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
11743
11744 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) {
11745 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
11746 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) {
11747 return p.first < t;
11748 });
11749 string_t key = "_ArrayType_";
11750 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second)) {
11751 auto last_token = get_token_string();
11752 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11753 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
11754 }
11755
11756 string_t type = it->second; // sax->string() takes a reference
11757 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type))) {
11758 return false;
11759 }
11760
11761 if (size_and_type.second == 'C' || size_and_type.second == 'B') {
11762 size_and_type.second = 'U';
11763 }
11764
11765 key = "_ArrayData_";
11766 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first))) {
11767 return false;
11768 }
11769
11770 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11771 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) {
11772 return false;
11773 }
11774 }
11775
11776 return (sax->end_array() && sax->end_object());
11777 }
11778
11779 // If BJData type marker is 'B' decode as binary
11780 if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second == 'B') {
11781 binary_t result;
11782 return get_binary(input_format, size_and_type.first, result) && sax->binary(result);
11783 }
11784
11785 if (size_and_type.first != npos) {
11786 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) {
11787 return false;
11788 }
11789
11790 if (size_and_type.second != 0) {
11791 if (size_and_type.second != 'N') {
11792 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11793 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) {
11794 return false;
11795 }
11796 }
11797 }
11798 }
11799 else {
11800 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11801 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) {
11802 return false;
11803 }
11804 }
11805 }
11806 }
11807 else {
11808 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size()))) {
11809 return false;
11810 }
11811
11812 while (current != ']') {
11813 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) {
11814 return false;
11815 }
11816 get_ignore_noop();
11817 }
11818 }
11819
11820 return sax->end_array();
11821 }
11822
11826 bool get_ubjson_object() {
11827 std::pair<std::size_t, char_int_type> size_and_type;
11828 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) {
11829 return false;
11830 }
11831
11832 // do not accept ND-array size in objects in BJData
11833 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) {
11834 auto last_token = get_token_string();
11835 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11836 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
11837 }
11838
11839 string_t key;
11840 if (size_and_type.first != npos) {
11841 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) {
11842 return false;
11843 }
11844
11845 if (size_and_type.second != 0) {
11846 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11847 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) {
11848 return false;
11849 }
11850 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) {
11851 return false;
11852 }
11853 key.clear();
11854 }
11855 }
11856 else {
11857 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11858 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) {
11859 return false;
11860 }
11861 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) {
11862 return false;
11863 }
11864 key.clear();
11865 }
11866 }
11867 }
11868 else {
11869 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size()))) {
11870 return false;
11871 }
11872
11873 while (current != '}') {
11874 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) {
11875 return false;
11876 }
11877 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) {
11878 return false;
11879 }
11880 get_ignore_noop();
11881 key.clear();
11882 }
11883 }
11884
11885 return sax->end_object();
11886 }
11887
11888 // Note, no reader for UBJSON binary types is implemented because they do
11889 // not exist
11890
11891 bool get_ubjson_high_precision_number() {
11892 // get the size of the following number string
11893 std::size_t size{};
11894 bool no_ndarray = true;
11895 auto res = get_ubjson_size_value(size, no_ndarray);
11896 if (JSON_HEDLEY_UNLIKELY(!res)) {
11897 return res;
11898 }
11899
11900 // get number string
11901 std::vector<char> number_vector;
11902 for (std::size_t i = 0; i < size; ++i) {
11903 get();
11904 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) {
11905 return false;
11906 }
11907 number_vector.push_back(static_cast<char>(current));
11908 }
11909
11910 // parse number string
11911 using ia_type = decltype(detail::input_adapter(number_vector));
11912 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11913 const auto result_number = number_lexer.scan();
11914 const auto number_string = number_lexer.get_token_string();
11915 const auto result_remainder = number_lexer.scan();
11916
11917 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
11918
11919 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) {
11920 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11921 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11922 }
11923
11924 switch (result_number) {
11925 case token_type::value_integer:
11926 return sax->number_integer(number_lexer.get_number_integer());
11927 case token_type::value_unsigned:
11928 return sax->number_unsigned(number_lexer.get_number_unsigned());
11929 case token_type::value_float:
11930 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11931 case token_type::uninitialized:
11932 case token_type::literal_true:
11933 case token_type::literal_false:
11934 case token_type::literal_null:
11935 case token_type::value_string:
11936 case token_type::begin_array:
11937 case token_type::begin_object:
11938 case token_type::end_array:
11939 case token_type::end_object:
11940 case token_type::name_separator:
11941 case token_type::value_separator:
11942 case token_type::parse_error:
11943 case token_type::end_of_input:
11944 case token_type::literal_or_value:
11945 default:
11946 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11947 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11948 }
11949 }
11950
11952 // Utility functions //
11954
11964 char_int_type get() {
11965 ++chars_read;
11966 return current = ia.get_character();
11967 }
11968
11977 template<class T>
11978 bool get_to(T& dest, const input_format_t format, const char* context) {
11979 auto new_chars_read = ia.get_elements(&dest);
11980 chars_read += new_chars_read;
11981 if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T))) {
11982 // in case of failure, advance position by 1 to report the failing location
11983 ++chars_read;
11984 sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
11985 return false;
11986 }
11987 return true;
11988 }
11989
11993 char_int_type get_ignore_noop() {
11994 do {
11995 get();
11996 } while (current == 'N');
11997
11998 return current;
11999 }
12000
12001 template<class NumberType>
12002 static void byte_swap(NumberType& number) {
12003 constexpr std::size_t sz = sizeof(number);
12004#ifdef __cpp_lib_byteswap
12005 if constexpr (sz == 1) {
12006 return;
12007 }
12008 else if constexpr (std::is_integral_v<NumberType>) {
12009 number = std::byteswap(number);
12010 return;
12011 }
12012 else {
12013#endif
12014 auto* ptr = reinterpret_cast<std::uint8_t*>(&number);
12015 for (std::size_t i = 0; i < sz / 2; ++i) {
12016 std::swap(ptr[i], ptr[sz - i - 1]);
12017 }
12018#ifdef __cpp_lib_byteswap
12019 }
12020#endif
12021 }
12022
12023 /*
12024 @brief read a number from the input
12025
12026 @tparam NumberType the type of the number
12027 @param[in] format the current format (for diagnostics)
12028 @param[out] result number of type @a NumberType
12029
12030 @return whether conversion completed
12031
12032 @note This function needs to respect the system's endianness, because
12033 bytes in CBOR, MessagePack, and UBJSON are stored in network order
12034 (big endian) and therefore need reordering on little endian systems.
12035 On the other hand, BSON and BJData use little endian and should reorder
12036 on big endian systems.
12037 */
12038 template<typename NumberType, bool InputIsLittleEndian = false>
12039 bool get_number(const input_format_t format, NumberType& result) {
12040 // read in the original format
12041
12042 if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number"))) {
12043 return false;
12044 }
12045 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) {
12046 byte_swap(result);
12047 }
12048 return true;
12049 }
12050
12065 template<typename NumberType>
12066 bool get_string(const input_format_t format,
12067 const NumberType len,
12068 string_t& result) {
12069 bool success = true;
12070 for (NumberType i = 0; i < len; i++) {
12071 get();
12072 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) {
12073 success = false;
12074 break;
12075 }
12076 result.push_back(static_cast<typename string_t::value_type>(current));
12077 }
12078 return success;
12079 }
12080
12095 template<typename NumberType>
12096 bool get_binary(const input_format_t format,
12097 const NumberType len,
12098 binary_t& result) {
12099 bool success = true;
12100 for (NumberType i = 0; i < len; i++) {
12101 get();
12102 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) {
12103 success = false;
12104 break;
12105 }
12106 result.push_back(static_cast<typename binary_t::value_type>(current));
12107 }
12108 return success;
12109 }
12110
12116 JSON_HEDLEY_NON_NULL(3)
12117 bool unexpect_eof(const input_format_t format, const char* context) const {
12118 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof())) {
12119 return sax->parse_error(chars_read, "<end of file>",
12120 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12121 }
12122 return true;
12123 }
12124
12128 std::string get_token_string() const {
12129 std::array<char, 3> cr{ {} };
12130 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12131 return std::string{ cr.data() };
12132 }
12133
12140 std::string exception_message(const input_format_t format,
12141 const std::string& detail,
12142 const std::string& context) const {
12143 std::string error_msg = "syntax error while parsing ";
12144
12145 switch (format) {
12146 case input_format_t::cbor:
12147 error_msg += "CBOR";
12148 break;
12149
12150 case input_format_t::msgpack:
12151 error_msg += "MessagePack";
12152 break;
12153
12154 case input_format_t::ubjson:
12155 error_msg += "UBJSON";
12156 break;
12157
12158 case input_format_t::bson:
12159 error_msg += "BSON";
12160 break;
12161
12162 case input_format_t::bjdata:
12163 error_msg += "BJData";
12164 break;
12165
12166 case input_format_t::json: // LCOV_EXCL_LINE
12167 default: // LCOV_EXCL_LINE
12168 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12169 }
12170
12171 return concat(error_msg, ' ', context, ": ", detail);
12172 }
12173
12174 private:
12175 static JSON_INLINE_VARIABLE constexpr std::size_t npos = detail::unknown_size();
12176
12178 InputAdapterType ia;
12179
12181 char_int_type current = char_traits<char_type>::eof();
12182
12184 std::size_t chars_read = 0;
12185
12187 const bool is_little_endian = little_endianness();
12188
12190 const input_format_t input_format = input_format_t::json;
12191
12193 json_sax_t* sax = nullptr;
12194
12195 // excluded markers in bjdata optimized type
12196#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12197 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12198
12199#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12200 make_array<bjd_type>( \
12201 bjd_type{'B', "byte"}, \
12202 bjd_type{'C', "char"}, \
12203 bjd_type{'D', "double"}, \
12204 bjd_type{'I', "int16"}, \
12205 bjd_type{'L', "int64"}, \
12206 bjd_type{'M', "uint64"}, \
12207 bjd_type{'U', "uint8"}, \
12208 bjd_type{'d', "single"}, \
12209 bjd_type{'i', "int8"}, \
12210 bjd_type{'l', "int32"}, \
12211 bjd_type{'m', "uint32"}, \
12212 bjd_type{'u', "uint16"})
12213
12214 JSON_PRIVATE_UNLESS_TESTED:
12215 // lookup tables
12216 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12217 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12218 JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
12219
12220 using bjd_type = std::pair<char_int_type, string_t>;
12221 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12222 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12223 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
12224
12225#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12226#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12227 };
12228
12229#ifndef JSON_HAS_CPP_17
12230 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12231 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12232#endif
12233
12234} // namespace detail
12235NLOHMANN_JSON_NAMESPACE_END
12236
12237// #include <nlohmann/detail/input/input_adapters.hpp>
12238
12239// #include <nlohmann/detail/input/lexer.hpp>
12240
12241// #include <nlohmann/detail/input/parser.hpp>
12242// __ _____ _____ _____
12243// __| | __| | | | JSON for Modern C++
12244// | | |__ | | | | | | version 3.12.0
12245// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12246//
12247// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
12248// SPDX-License-Identifier: MIT
12249
12250
12251
12252#include <cmath> // isfinite
12253#include <cstdint> // uint8_t
12254#include <functional> // function
12255#include <string> // string
12256#include <utility> // move
12257#include <vector> // vector
12258
12259// #include <nlohmann/detail/exceptions.hpp>
12260
12261// #include <nlohmann/detail/input/input_adapters.hpp>
12262
12263// #include <nlohmann/detail/input/json_sax.hpp>
12264
12265// #include <nlohmann/detail/input/lexer.hpp>
12266
12267// #include <nlohmann/detail/macro_scope.hpp>
12268
12269// #include <nlohmann/detail/meta/is_sax.hpp>
12270
12271// #include <nlohmann/detail/string_concat.hpp>
12272
12273// #include <nlohmann/detail/value_t.hpp>
12274
12275
12276NLOHMANN_JSON_NAMESPACE_BEGIN
12277namespace detail {
12279 // parser //
12281
12282 enum class parse_event_t : std::uint8_t {
12284 object_start,
12286 object_end,
12288 array_start,
12290 array_end,
12292 key,
12294 value
12295 };
12296
12297 template<typename BasicJsonType>
12298 using parser_callback_t =
12299 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12300
12306 template<typename BasicJsonType, typename InputAdapterType>
12307 class parser {
12308 using number_integer_t = typename BasicJsonType::number_integer_t;
12309 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12310 using number_float_t = typename BasicJsonType::number_float_t;
12311 using string_t = typename BasicJsonType::string_t;
12313 using token_type = typename lexer_t::token_type;
12314
12315 public:
12317 explicit parser(InputAdapterType&& adapter,
12318 parser_callback_t<BasicJsonType> cb = nullptr,
12319 const bool allow_exceptions_ = true,
12320 const bool ignore_comments = false,
12321 const bool ignore_trailing_commas_ = false)
12322 : callback(std::move(cb))
12323 , m_lexer(std::move(adapter), ignore_comments)
12324 , allow_exceptions(allow_exceptions_)
12325 , ignore_trailing_commas(ignore_trailing_commas_) {
12326 // read first token
12327 get_token();
12328 }
12329
12340 void parse(const bool strict, BasicJsonType& result) {
12341 if (callback) {
12342 json_sax_dom_callback_parser<BasicJsonType, InputAdapterType> sdp(result, callback, allow_exceptions, &m_lexer);
12343 sax_parse_internal(&sdp);
12344
12345 // in strict mode, input must be completely read
12346 if (strict && (get_token() != token_type::end_of_input)) {
12347 sdp.parse_error(m_lexer.get_position(),
12348 m_lexer.get_token_string(),
12349 parse_error::create(101, m_lexer.get_position(),
12350 exception_message(token_type::end_of_input, "value"), nullptr));
12351 }
12352
12353 // in case of an error, return a discarded value
12354 if (sdp.is_errored()) {
12355 result = value_t::discarded;
12356 return;
12357 }
12358
12359 // set top-level value to null if it was discarded by the callback
12360 // function
12361 if (result.is_discarded()) {
12362 result = nullptr;
12363 }
12364 }
12365 else {
12366 json_sax_dom_parser<BasicJsonType, InputAdapterType> sdp(result, allow_exceptions, &m_lexer);
12367 sax_parse_internal(&sdp);
12368
12369 // in strict mode, input must be completely read
12370 if (strict && (get_token() != token_type::end_of_input)) {
12371 sdp.parse_error(m_lexer.get_position(),
12372 m_lexer.get_token_string(),
12373 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12374 }
12375
12376 // in case of an error, return a discarded value
12377 if (sdp.is_errored()) {
12378 result = value_t::discarded;
12379 return;
12380 }
12381 }
12382
12383 result.assert_invariant();
12384 }
12385
12392 bool accept(const bool strict = true) {
12394 return sax_parse(&sax_acceptor, strict);
12395 }
12396
12397 template<typename SAX>
12398 JSON_HEDLEY_NON_NULL(2)
12399 bool sax_parse(SAX* sax, const bool strict = true) {
12401 const bool result = sax_parse_internal(sax);
12402
12403 // strict mode: next byte must be EOF
12404 if (result && strict && (get_token() != token_type::end_of_input)) {
12405 return sax->parse_error(m_lexer.get_position(),
12406 m_lexer.get_token_string(),
12407 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12408 }
12409
12410 return result;
12411 }
12412
12413 private:
12414 template<typename SAX>
12415 JSON_HEDLEY_NON_NULL(2)
12416 bool sax_parse_internal(SAX* sax) {
12417 // stack to remember the hierarchy of structured values we are parsing
12418 // true = array; false = object
12419 std::vector<bool> states;
12420 // value to avoid a goto (see comment where set to true)
12421 bool skip_to_state_evaluation = false;
12422
12423 while (true) {
12424 if (!skip_to_state_evaluation) {
12425 // invariant: get_token() was called before each iteration
12426 switch (last_token) {
12427 case token_type::begin_object:
12428 {
12429 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size()))) {
12430 return false;
12431 }
12432
12433 // closing } -> we are done
12434 if (get_token() == token_type::end_object) {
12435 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) {
12436 return false;
12437 }
12438 break;
12439 }
12440
12441 // parse key
12442 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) {
12443 return sax->parse_error(m_lexer.get_position(),
12444 m_lexer.get_token_string(),
12445 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12446 }
12447 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) {
12448 return false;
12449 }
12450
12451 // parse separator (:)
12452 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) {
12453 return sax->parse_error(m_lexer.get_position(),
12454 m_lexer.get_token_string(),
12455 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12456 }
12457
12458 // remember we are now inside an object
12459 states.push_back(false);
12460
12461 // parse values
12462 get_token();
12463 continue;
12464 }
12465
12466 case token_type::begin_array:
12467 {
12468 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size()))) {
12469 return false;
12470 }
12471
12472 // closing ] -> we are done
12473 if (get_token() == token_type::end_array) {
12474 if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) {
12475 return false;
12476 }
12477 break;
12478 }
12479
12480 // remember we are now inside an array
12481 states.push_back(true);
12482
12483 // parse values (no need to call get_token)
12484 continue;
12485 }
12486
12487 case token_type::value_float:
12488 {
12489 const auto res = m_lexer.get_number_float();
12490
12491 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) {
12492 return sax->parse_error(m_lexer.get_position(),
12493 m_lexer.get_token_string(),
12494 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
12495 }
12496
12497 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) {
12498 return false;
12499 }
12500
12501 break;
12502 }
12503
12504 case token_type::literal_false:
12505 {
12506 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) {
12507 return false;
12508 }
12509 break;
12510 }
12511
12512 case token_type::literal_null:
12513 {
12514 if (JSON_HEDLEY_UNLIKELY(!sax->null())) {
12515 return false;
12516 }
12517 break;
12518 }
12519
12520 case token_type::literal_true:
12521 {
12522 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) {
12523 return false;
12524 }
12525 break;
12526 }
12527
12528 case token_type::value_integer:
12529 {
12530 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) {
12531 return false;
12532 }
12533 break;
12534 }
12535
12536 case token_type::value_string:
12537 {
12538 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) {
12539 return false;
12540 }
12541 break;
12542 }
12543
12544 case token_type::value_unsigned:
12545 {
12546 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) {
12547 return false;
12548 }
12549 break;
12550 }
12551
12552 case token_type::parse_error:
12553 {
12554 // using "uninitialized" to avoid an "expected" message
12555 return sax->parse_error(m_lexer.get_position(),
12556 m_lexer.get_token_string(),
12557 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
12558 }
12559 case token_type::end_of_input:
12560 {
12561 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1)) {
12562 return sax->parse_error(m_lexer.get_position(),
12563 m_lexer.get_token_string(),
12564 parse_error::create(101, m_lexer.get_position(),
12565 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
12566 }
12567
12568 return sax->parse_error(m_lexer.get_position(),
12569 m_lexer.get_token_string(),
12570 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12571 }
12572 case token_type::uninitialized:
12573 case token_type::end_array:
12574 case token_type::end_object:
12575 case token_type::name_separator:
12576 case token_type::value_separator:
12577 case token_type::literal_or_value:
12578 default: // the last token was unexpected
12579 {
12580 return sax->parse_error(m_lexer.get_position(),
12581 m_lexer.get_token_string(),
12582 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12583 }
12584 }
12585 }
12586 else {
12587 skip_to_state_evaluation = false;
12588 }
12589
12590 // we reached this line after we successfully parsed a value
12591 if (states.empty()) {
12592 // empty stack: we reached the end of the hierarchy: done
12593 return true;
12594 }
12595
12596 if (states.back()) // array
12597 {
12598 // comma -> next value
12599 // or end of array (ignore_trailing_commas = true)
12600 if (get_token() == token_type::value_separator) {
12601 // parse a new value
12602 get_token();
12603
12604 // if ignore_trailing_commas and last_token is ], we can continue to "closing ]"
12605 if (!(ignore_trailing_commas && last_token == token_type::end_array)) {
12606 continue;
12607 }
12608 }
12609
12610 // closing ]
12611 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) {
12612 if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) {
12613 return false;
12614 }
12615
12616 // We are done with this array. Before we can parse a
12617 // new value, we need to evaluate the new state first.
12618 // By setting skip_to_state_evaluation to false, we
12619 // are effectively jumping to the beginning of this if.
12620 JSON_ASSERT(!states.empty());
12621 states.pop_back();
12622 skip_to_state_evaluation = true;
12623 continue;
12624 }
12625
12626 return sax->parse_error(m_lexer.get_position(),
12627 m_lexer.get_token_string(),
12628 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
12629 }
12630
12631 // states.back() is false -> object
12632
12633 // comma -> next value
12634 // or end of object (ignore_trailing_commas = true)
12635 if (get_token() == token_type::value_separator) {
12636 get_token();
12637
12638 // if ignore_trailing_commas and last_token is }, we can continue to "closing }"
12639 if (!(ignore_trailing_commas && last_token == token_type::end_object)) {
12640 // parse key
12641 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) {
12642 return sax->parse_error(m_lexer.get_position(),
12643 m_lexer.get_token_string(),
12644 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12645 }
12646
12647 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) {
12648 return false;
12649 }
12650
12651 // parse separator (:)
12652 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) {
12653 return sax->parse_error(m_lexer.get_position(),
12654 m_lexer.get_token_string(),
12655 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12656 }
12657
12658 // parse values
12659 get_token();
12660 continue;
12661 }
12662 }
12663
12664 // closing }
12665 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) {
12666 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) {
12667 return false;
12668 }
12669
12670 // We are done with this object. Before we can parse a
12671 // new value, we need to evaluate the new state first.
12672 // By setting skip_to_state_evaluation to false, we
12673 // are effectively jumping to the beginning of this if.
12674 JSON_ASSERT(!states.empty());
12675 states.pop_back();
12676 skip_to_state_evaluation = true;
12677 continue;
12678 }
12679
12680 return sax->parse_error(m_lexer.get_position(),
12681 m_lexer.get_token_string(),
12682 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
12683 }
12684 }
12685
12687 token_type get_token() {
12688 return last_token = m_lexer.scan();
12689 }
12690
12691 std::string exception_message(const token_type expected, const std::string& context) {
12692 std::string error_msg = "syntax error ";
12693
12694 if (!context.empty()) {
12695 error_msg += concat("while parsing ", context, ' ');
12696 }
12697
12698 error_msg += "- ";
12699
12700 if (last_token == token_type::parse_error) {
12701 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12702 m_lexer.get_token_string(), '\'');
12703 }
12704 else {
12705 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12706 }
12707
12708 if (expected != token_type::uninitialized) {
12709 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12710 }
12711
12712 return error_msg;
12713 }
12714
12715 private:
12717 const parser_callback_t<BasicJsonType> callback = nullptr;
12719 token_type last_token = token_type::uninitialized;
12721 lexer_t m_lexer;
12723 const bool allow_exceptions = true;
12725 const bool ignore_trailing_commas = false;
12726 };
12727
12728} // namespace detail
12729NLOHMANN_JSON_NAMESPACE_END
12730
12731// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12732// __ _____ _____ _____
12733// __| | __| | | | JSON for Modern C++
12734// | | |__ | | | | | | version 3.12.0
12735// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12736//
12737// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
12738// SPDX-License-Identifier: MIT
12739
12740
12741
12742// #include <nlohmann/detail/abi_macros.hpp>
12743
12744// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12745// __ _____ _____ _____
12746// __| | __| | | | JSON for Modern C++
12747// | | |__ | | | | | | version 3.12.0
12748// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12749//
12750// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
12751// SPDX-License-Identifier: MIT
12752
12753
12754
12755#include <cstddef> // ptrdiff_t
12756#include <limits> // numeric_limits
12757
12758// #include <nlohmann/detail/macro_scope.hpp>
12759
12760
12761NLOHMANN_JSON_NAMESPACE_BEGIN
12762namespace detail {
12763
12764 /*
12765 @brief an iterator for primitive JSON types
12766
12767 This class models an iterator for primitive JSON types (boolean, number,
12768 string). Its only purpose is to allow the iterator/const_iterator classes
12769 to "iterate" over primitive values. Internally, the iterator is modeled by
12770 a `difference_type` variable. Value begin_value (`0`) models the begin and
12771 end_value (`1`) models past the end.
12772 */
12774 private:
12775 using difference_type = std::ptrdiff_t;
12776 static constexpr difference_type begin_value = 0;
12777 static constexpr difference_type end_value = begin_value + 1;
12778
12779 JSON_PRIVATE_UNLESS_TESTED:
12781 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12782
12783 public:
12784 constexpr difference_type get_value() const noexcept {
12785 return m_it;
12786 }
12787
12789 void set_begin() noexcept {
12790 m_it = begin_value;
12791 }
12792
12794 void set_end() noexcept {
12795 m_it = end_value;
12796 }
12797
12799 constexpr bool is_begin() const noexcept {
12800 return m_it == begin_value;
12801 }
12802
12804 constexpr bool is_end() const noexcept {
12805 return m_it == end_value;
12806 }
12807
12808 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept {
12809 return lhs.m_it == rhs.m_it;
12810 }
12811
12812 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept {
12813 return lhs.m_it < rhs.m_it;
12814 }
12815
12816 primitive_iterator_t operator+(difference_type n) noexcept {
12817 auto result = *this;
12818 result += n;
12819 return result;
12820 }
12821
12822 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept {
12823 return lhs.m_it - rhs.m_it;
12824 }
12825
12826 primitive_iterator_t& operator++() noexcept {
12827 ++m_it;
12828 return *this;
12829 }
12830
12831 primitive_iterator_t operator++(int)&noexcept // NOLINT(cert-dcl21-cpp)
12832 {
12833 auto result = *this;
12834 ++m_it;
12835 return result;
12836 }
12837
12838 primitive_iterator_t& operator--() noexcept {
12839 --m_it;
12840 return *this;
12841 }
12842
12843 primitive_iterator_t operator--(int)&noexcept // NOLINT(cert-dcl21-cpp)
12844 {
12845 auto result = *this;
12846 --m_it;
12847 return result;
12848 }
12849
12850 primitive_iterator_t& operator+=(difference_type n) noexcept {
12851 m_it += n;
12852 return *this;
12853 }
12854
12855 primitive_iterator_t& operator-=(difference_type n) noexcept {
12856 m_it -= n;
12857 return *this;
12858 }
12859 };
12860
12861} // namespace detail
12862NLOHMANN_JSON_NAMESPACE_END
12863
12864
12865NLOHMANN_JSON_NAMESPACE_BEGIN
12866namespace detail {
12867
12874 template<typename BasicJsonType> struct internal_iterator {
12876 typename BasicJsonType::object_t::iterator object_iterator{};
12878 typename BasicJsonType::array_t::iterator array_iterator{};
12880 primitive_iterator_t primitive_iterator{};
12881 };
12882
12883} // namespace detail
12884NLOHMANN_JSON_NAMESPACE_END
12885
12886// #include <nlohmann/detail/iterators/iter_impl.hpp>
12887// __ _____ _____ _____
12888// __| | __| | | | JSON for Modern C++
12889// | | |__ | | | | | | version 3.12.0
12890// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12891//
12892// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
12893// SPDX-License-Identifier: MIT
12894
12895
12896
12897#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
12898#include <type_traits> // conditional, is_const, remove_const
12899
12900// #include <nlohmann/detail/exceptions.hpp>
12901
12902// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12903
12904// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12905
12906// #include <nlohmann/detail/macro_scope.hpp>
12907
12908// #include <nlohmann/detail/meta/cpp_future.hpp>
12909
12910// #include <nlohmann/detail/meta/type_traits.hpp>
12911
12912// #include <nlohmann/detail/value_t.hpp>
12913
12914
12915NLOHMANN_JSON_NAMESPACE_BEGIN
12916namespace detail {
12917
12918 // forward declare to be able to friend it later on
12919 template<typename IteratorType> class iteration_proxy;
12920 template<typename IteratorType> class iteration_proxy_value;
12921
12938 template<typename BasicJsonType>
12939 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
12940 {
12942 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
12944 friend other_iter_impl;
12945 friend BasicJsonType;
12948
12949 using object_t = typename BasicJsonType::object_t;
12950 using array_t = typename BasicJsonType::array_t;
12951 // make sure BasicJsonType is basic_json or const basic_json
12953 "iter_impl only accepts (const) basic_json");
12954 // superficial check for the LegacyBidirectionalIterator named requirement
12955 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
12956 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
12957 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
12958
12959 public:
12965 using iterator_category = std::bidirectional_iterator_tag;
12966
12968 using value_type = typename BasicJsonType::value_type;
12970 using difference_type = typename BasicJsonType::difference_type;
12972 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
12973 typename BasicJsonType::const_pointer,
12974 typename BasicJsonType::pointer>::type;
12976 using reference =
12977 typename std::conditional<std::is_const<BasicJsonType>::value,
12978 typename BasicJsonType::const_reference,
12979 typename BasicJsonType::reference>::type;
12980
12981 iter_impl() = default;
12982 ~iter_impl() = default;
12983 iter_impl(iter_impl&&) noexcept = default;
12984 iter_impl& operator=(iter_impl&&) noexcept = default;
12985
12992 explicit iter_impl(pointer object) noexcept : m_object(object) {
12993 JSON_ASSERT(m_object != nullptr);
12994
12995 switch (m_object->m_data.m_type) {
12996 case value_t::object:
12997 {
12998 m_it.object_iterator = typename object_t::iterator();
12999 break;
13000 }
13001
13002 case value_t::array:
13003 {
13004 m_it.array_iterator = typename array_t::iterator();
13005 break;
13006 }
13007
13008 case value_t::null:
13009 case value_t::string:
13010 case value_t::boolean:
13014 case value_t::binary:
13015 case value_t::discarded:
13016 default:
13017 {
13018 m_it.primitive_iterator = primitive_iterator_t();
13019 break;
13020 }
13021 }
13022 }
13023
13032
13040 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
13041 : m_object(other.m_object), m_it(other.m_it) {}
13042
13049 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept {
13050 if (&other != this) {
13051 m_object = other.m_object;
13052 m_it = other.m_it;
13053 }
13054 return *this;
13055 }
13056
13062 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13063 : m_object(other.m_object), m_it(other.m_it) {}
13064
13071 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13072 {
13073 m_object = other.m_object;
13074 m_it = other.m_it;
13075 return *this;
13076 }
13077
13078 JSON_PRIVATE_UNLESS_TESTED:
13083 void set_begin() noexcept {
13084 JSON_ASSERT(m_object != nullptr);
13085
13086 switch (m_object->m_data.m_type) {
13087 case value_t::object:
13088 {
13089 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13090 break;
13091 }
13092
13093 case value_t::array:
13094 {
13095 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13096 break;
13097 }
13098
13099 case value_t::null:
13100 {
13101 // set to end so begin()==end() is true: null is empty
13102 m_it.primitive_iterator.set_end();
13103 break;
13104 }
13105
13106 case value_t::string:
13107 case value_t::boolean:
13108 case value_t::number_integer:
13109 case value_t::number_unsigned:
13110 case value_t::number_float:
13111 case value_t::binary:
13112 case value_t::discarded:
13113 default:
13114 {
13115 m_it.primitive_iterator.set_begin();
13116 break;
13117 }
13118 }
13119 }
13120
13125 void set_end() noexcept {
13126 JSON_ASSERT(m_object != nullptr);
13127
13128 switch (m_object->m_data.m_type) {
13129 case value_t::object:
13130 {
13131 m_it.object_iterator = m_object->m_data.m_value.object->end();
13132 break;
13133 }
13134
13135 case value_t::array:
13136 {
13137 m_it.array_iterator = m_object->m_data.m_value.array->end();
13138 break;
13139 }
13140
13141 case value_t::null:
13142 case value_t::string:
13143 case value_t::boolean:
13147 case value_t::binary:
13148 case value_t::discarded:
13149 default:
13150 {
13151 m_it.primitive_iterator.set_end();
13152 break;
13153 }
13154 }
13155 }
13156
13157 public:
13162 reference operator*() const {
13163 JSON_ASSERT(m_object != nullptr);
13164
13165 switch (m_object->m_data.m_type) {
13166 case value_t::object:
13167 {
13168 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13169 return m_it.object_iterator->second;
13170 }
13171
13172 case value_t::array:
13173 {
13174 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13175 return *m_it.array_iterator;
13176 }
13177
13178 case value_t::null:
13179 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13180
13181 case value_t::string:
13182 case value_t::boolean:
13186 case value_t::binary:
13187 case value_t::discarded:
13188 default:
13189 {
13190 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) {
13191 return *m_object;
13192 }
13193
13194 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13195 }
13196 }
13197 }
13198
13203 pointer operator->() const {
13204 JSON_ASSERT(m_object != nullptr);
13205
13206 switch (m_object->m_data.m_type) {
13207 case value_t::object:
13208 {
13209 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13210 return &(m_it.object_iterator->second);
13211 }
13212
13213 case value_t::array:
13214 {
13215 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13216 return &*m_it.array_iterator;
13217 }
13218
13219 case value_t::null:
13220 case value_t::string:
13221 case value_t::boolean:
13225 case value_t::binary:
13226 case value_t::discarded:
13227 default:
13228 {
13229 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) {
13230 return m_object;
13231 }
13232
13233 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13234 }
13235 }
13236 }
13237
13242 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13243 {
13244 auto result = *this;
13245 ++(*this);
13246 return result;
13247 }
13248
13253 iter_impl& operator++() {
13254 JSON_ASSERT(m_object != nullptr);
13255
13256 switch (m_object->m_data.m_type) {
13257 case value_t::object:
13258 {
13259 std::advance(m_it.object_iterator, 1);
13260 break;
13261 }
13262
13263 case value_t::array:
13264 {
13265 std::advance(m_it.array_iterator, 1);
13266 break;
13267 }
13268
13269 case value_t::null:
13270 case value_t::string:
13271 case value_t::boolean:
13275 case value_t::binary:
13276 case value_t::discarded:
13277 default:
13278 {
13279 ++m_it.primitive_iterator;
13280 break;
13281 }
13282 }
13283
13284 return *this;
13285 }
13286
13291 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13292 {
13293 auto result = *this;
13294 --(*this);
13295 return result;
13296 }
13297
13302 iter_impl& operator--() {
13303 JSON_ASSERT(m_object != nullptr);
13304
13305 switch (m_object->m_data.m_type) {
13306 case value_t::object:
13307 {
13308 std::advance(m_it.object_iterator, -1);
13309 break;
13310 }
13311
13312 case value_t::array:
13313 {
13314 std::advance(m_it.array_iterator, -1);
13315 break;
13316 }
13317
13318 case value_t::null:
13319 case value_t::string:
13320 case value_t::boolean:
13324 case value_t::binary:
13325 case value_t::discarded:
13326 default:
13327 {
13328 --m_it.primitive_iterator;
13329 break;
13330 }
13331 }
13332
13333 return *this;
13334 }
13335
13340 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 >
13341 bool operator==(const IterImpl& other) const {
13342 // if objects are not the same, the comparison is undefined
13343 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) {
13344 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13345 }
13346
13347 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
13348 if (m_object == nullptr) {
13349 return true;
13350 }
13351
13352 switch (m_object->m_data.m_type) {
13353 case value_t::object:
13354 return (m_it.object_iterator == other.m_it.object_iterator);
13355
13356 case value_t::array:
13357 return (m_it.array_iterator == other.m_it.array_iterator);
13358
13359 case value_t::null:
13360 case value_t::string:
13361 case value_t::boolean:
13365 case value_t::binary:
13366 case value_t::discarded:
13367 default:
13368 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
13369 }
13370 }
13371
13376 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 >
13377 bool operator!=(const IterImpl& other) const {
13378 return !operator==(other);
13379 }
13380
13385 bool operator<(const iter_impl& other) const {
13386 // if objects are not the same, the comparison is undefined
13387 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) {
13388 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13389 }
13390
13391 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
13392 if (m_object == nullptr) {
13393 // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false
13394 return false;
13395 }
13396
13397 switch (m_object->m_data.m_type) {
13398 case value_t::object:
13399 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
13400
13401 case value_t::array:
13402 return (m_it.array_iterator < other.m_it.array_iterator);
13403
13404 case value_t::null:
13405 case value_t::string:
13406 case value_t::boolean:
13410 case value_t::binary:
13411 case value_t::discarded:
13412 default:
13413 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
13414 }
13415 }
13416
13421 bool operator<=(const iter_impl& other) const {
13422 return !other.operator < (*this);
13423 }
13424
13429 bool operator>(const iter_impl& other) const {
13430 return !operator<=(other);
13431 }
13432
13437 bool operator>=(const iter_impl& other) const {
13438 return !operator<(other);
13439 }
13440
13445 iter_impl& operator+=(difference_type i) {
13446 JSON_ASSERT(m_object != nullptr);
13447
13448 switch (m_object->m_data.m_type) {
13449 case value_t::object:
13450 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13451
13452 case value_t::array:
13453 {
13454 std::advance(m_it.array_iterator, i);
13455 break;
13456 }
13457
13458 case value_t::null:
13459 case value_t::string:
13460 case value_t::boolean:
13464 case value_t::binary:
13465 case value_t::discarded:
13466 default:
13467 {
13468 m_it.primitive_iterator += i;
13469 break;
13470 }
13471 }
13472
13473 return *this;
13474 }
13475
13480 iter_impl& operator-=(difference_type i) {
13481 return operator+=(-i);
13482 }
13483
13488 iter_impl operator+(difference_type i) const {
13489 auto result = *this;
13490 result += i;
13491 return result;
13492 }
13493
13498 friend iter_impl operator+(difference_type i, const iter_impl& it) {
13499 auto result = it;
13500 result += i;
13501 return result;
13502 }
13503
13508 iter_impl operator-(difference_type i) const {
13509 auto result = *this;
13510 result -= i;
13511 return result;
13512 }
13513
13518 difference_type operator-(const iter_impl& other) const {
13519 JSON_ASSERT(m_object != nullptr);
13520
13521 switch (m_object->m_data.m_type) {
13522 case value_t::object:
13523 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13524
13525 case value_t::array:
13526 return m_it.array_iterator - other.m_it.array_iterator;
13527
13528 case value_t::null:
13529 case value_t::string:
13530 case value_t::boolean:
13534 case value_t::binary:
13535 case value_t::discarded:
13536 default:
13537 return m_it.primitive_iterator - other.m_it.primitive_iterator;
13538 }
13539 }
13540
13545 reference operator[](difference_type n) const {
13546 JSON_ASSERT(m_object != nullptr);
13547
13548 switch (m_object->m_data.m_type) {
13549 case value_t::object:
13550 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
13551
13552 case value_t::array:
13553 return *std::next(m_it.array_iterator, n);
13554
13555 case value_t::null:
13556 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13557
13558 case value_t::string:
13559 case value_t::boolean:
13563 case value_t::binary:
13564 case value_t::discarded:
13565 default:
13566 {
13567 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) {
13568 return *m_object;
13569 }
13570
13571 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13572 }
13573 }
13574 }
13575
13580 const typename object_t::key_type& key() const {
13581 JSON_ASSERT(m_object != nullptr);
13582
13583 if (JSON_HEDLEY_LIKELY(m_object->is_object())) {
13584 return m_it.object_iterator->first;
13585 }
13586
13587 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
13588 }
13589
13594 reference value() const {
13595 return operator*();
13596 }
13597
13598 JSON_PRIVATE_UNLESS_TESTED:
13600 pointer m_object = nullptr;
13603 };
13604
13605} // namespace detail
13606NLOHMANN_JSON_NAMESPACE_END
13607
13608// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
13609
13610// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
13611// __ _____ _____ _____
13612// __| | __| | | | JSON for Modern C++
13613// | | |__ | | | | | | version 3.12.0
13614// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13615//
13616// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
13617// SPDX-License-Identifier: MIT
13618
13619
13620
13621#include <cstddef> // ptrdiff_t
13622#include <iterator> // reverse_iterator
13623#include <utility> // declval
13624
13625// #include <nlohmann/detail/abi_macros.hpp>
13626
13627
13628NLOHMANN_JSON_NAMESPACE_BEGIN
13629namespace detail {
13630
13632 // reverse_iterator //
13634
13653 template<typename Base>
13654 class json_reverse_iterator : public std::reverse_iterator<Base> {
13655 public:
13656 using difference_type = std::ptrdiff_t;
13658 using base_iterator = std::reverse_iterator<Base>;
13660 using reference = typename Base::reference;
13661
13663 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13664 : base_iterator(it) {}
13665
13667 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13668
13670 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
13671 {
13672 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13673 }
13674
13676 json_reverse_iterator& operator++() {
13677 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13678 }
13679
13681 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
13682 {
13683 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13684 }
13685
13687 json_reverse_iterator& operator--() {
13688 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13689 }
13690
13692 json_reverse_iterator& operator+=(difference_type i) {
13693 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13694 }
13695
13697 json_reverse_iterator operator+(difference_type i) const {
13698 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13699 }
13700
13702 json_reverse_iterator operator-(difference_type i) const {
13703 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13704 }
13705
13707 difference_type operator-(const json_reverse_iterator& other) const {
13708 return base_iterator(*this) - base_iterator(other);
13709 }
13710
13712 reference operator[](difference_type n) const {
13713 return *(this->operator+(n));
13714 }
13715
13717 auto key() const -> decltype(std::declval<Base>().key()) {
13718 auto it = --this->base();
13719 return it.key();
13720 }
13721
13723 reference value() const {
13724 auto it = --this->base();
13725 return it.operator * ();
13726 }
13727 };
13728
13729} // namespace detail
13730NLOHMANN_JSON_NAMESPACE_END
13731
13732// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13733
13734// #include <nlohmann/detail/json_custom_base_class.hpp>
13735// __ _____ _____ _____
13736// __| | __| | | | JSON for Modern C++
13737// | | |__ | | | | | | version 3.12.0
13738// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13739//
13740// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
13741// SPDX-License-Identifier: MIT
13742
13743
13744
13745#include <type_traits> // conditional, is_same
13746
13747// #include <nlohmann/detail/abi_macros.hpp>
13748
13749
13750NLOHMANN_JSON_NAMESPACE_BEGIN
13751namespace detail {
13752
13764
13765 template<class T>
13766 using json_base_class = typename std::conditional <
13767 std::is_same<T, void>::value,
13769 T
13770 >::type;
13771
13772} // namespace detail
13773NLOHMANN_JSON_NAMESPACE_END
13774
13775// #include <nlohmann/detail/json_pointer.hpp>
13776// __ _____ _____ _____
13777// __| | __| | | | JSON for Modern C++
13778// | | |__ | | | | | | version 3.12.0
13779// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13780//
13781// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
13782// SPDX-License-Identifier: MIT
13783
13784
13785
13786#include <algorithm> // all_of
13787#include <cctype> // isdigit
13788#include <cerrno> // errno, ERANGE
13789#include <cstdlib> // strtoull
13790#ifndef JSON_NO_IO
13791#include <iosfwd> // ostream
13792#endif // JSON_NO_IO
13793#include <limits> // max
13794#include <numeric> // accumulate
13795#include <string> // string
13796#include <utility> // move
13797#include <vector> // vector
13798
13799// #include <nlohmann/detail/exceptions.hpp>
13800
13801// #include <nlohmann/detail/macro_scope.hpp>
13802
13803// #include <nlohmann/detail/string_concat.hpp>
13804
13805// #include <nlohmann/detail/string_escape.hpp>
13806
13807// #include <nlohmann/detail/value_t.hpp>
13808
13809
13810NLOHMANN_JSON_NAMESPACE_BEGIN
13811
13814template<typename RefStringType>
13815class json_pointer {
13816 // allow basic_json to access private members
13817 NLOHMANN_BASIC_JSON_TPL_DECLARATION
13818 friend class basic_json;
13819
13820 template<typename>
13821 friend class json_pointer;
13822
13823 template<typename T>
13825 using type = T;
13826 };
13827
13828 NLOHMANN_BASIC_JSON_TPL_DECLARATION
13829 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL> {
13830 using type = StringType;
13831 };
13832
13833public:
13834 // for backwards compatibility accept BasicJsonType
13835 using string_t = typename string_t_helper<RefStringType>::type;
13836
13839 explicit json_pointer(const string_t& s = "")
13840 : reference_tokens(split(s)) {}
13841
13844 string_t to_string() const {
13845 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
13846 string_t{},
13847 [](const string_t& a, const string_t& b) {
13848 return detail::concat(a, '/', detail::escape(b));
13849 });
13850 }
13851
13854 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
13855 operator string_t() const {
13856 return to_string();
13857 }
13858
13859#ifndef JSON_NO_IO
13862 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr) {
13863 o << ptr.to_string();
13864 return o;
13865 }
13866#endif
13867
13870 json_pointer& operator/=(const json_pointer& ptr) {
13871 reference_tokens.insert(reference_tokens.end(),
13872 ptr.reference_tokens.begin(),
13873 ptr.reference_tokens.end());
13874 return *this;
13875 }
13876
13879 json_pointer& operator/=(string_t token) {
13880 push_back(std::move(token));
13881 return *this;
13882 }
13883
13886 json_pointer& operator/=(std::size_t array_idx) {
13887 return *this /= std::to_string(array_idx);
13888 }
13889
13892 friend json_pointer operator/(const json_pointer& lhs,
13893 const json_pointer& rhs) {
13894 return json_pointer(lhs) /= rhs;
13895 }
13896
13899 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
13900 {
13901 return json_pointer(lhs) /= std::move(token);
13902 }
13903
13906 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx) {
13907 return json_pointer(lhs) /= array_idx;
13908 }
13909
13912 json_pointer parent_pointer() const {
13913 if (empty()) {
13914 return *this;
13915 }
13916
13917 json_pointer res = *this;
13918 res.pop_back();
13919 return res;
13920 }
13921
13924 void pop_back() {
13925 if (JSON_HEDLEY_UNLIKELY(empty())) {
13926 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13927 }
13928
13929 reference_tokens.pop_back();
13930 }
13931
13934 const string_t& back() const {
13935 if (JSON_HEDLEY_UNLIKELY(empty())) {
13936 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13937 }
13938
13939 return reference_tokens.back();
13940 }
13941
13944 void push_back(const string_t& token) {
13945 reference_tokens.push_back(token);
13946 }
13947
13950 void push_back(string_t&& token) {
13951 reference_tokens.push_back(std::move(token));
13952 }
13953
13956 bool empty() const noexcept {
13957 return reference_tokens.empty();
13958 }
13959
13960private:
13971 template<typename BasicJsonType>
13972 static typename BasicJsonType::size_type array_index(const string_t& s) {
13973 using size_type = typename BasicJsonType::size_type;
13974
13975 // error condition (cf. RFC 6901, Sect. 4)
13976 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) {
13977 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
13978 }
13979
13980 // error condition (cf. RFC 6901, Sect. 4)
13981 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) {
13982 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
13983 }
13984
13985 const char* p = s.c_str();
13986 char* p_end = nullptr; // NOLINT(misc-const-correctness)
13987 errno = 0; // strtoull doesn't reset errno
13988 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
13989 if (p == p_end // invalid input or empty string
13990 || errno == ERANGE // out of range
13991 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
13992 {
13993 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
13994 }
13995
13996 // only triggered on special platforms (like 32bit), see also
13997 // https://github.com/nlohmann/json/pull/2203
13998 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
13999 {
14000 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14001 }
14002
14003 return static_cast<size_type>(res);
14004 }
14005
14006JSON_PRIVATE_UNLESS_TESTED:
14007 json_pointer top() const {
14008 if (JSON_HEDLEY_UNLIKELY(empty())) {
14009 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14010 }
14011
14012 json_pointer result = *this;
14013 result.reference_tokens = { reference_tokens[0] };
14014 return result;
14015 }
14016
14017private:
14026 template<typename BasicJsonType>
14027 BasicJsonType& get_and_create(BasicJsonType& j) const {
14028 auto* result = &j;
14029
14030 // in case no reference tokens exist, return a reference to the JSON value
14031 // j which will be overwritten by a primitive value
14032 for (const auto& reference_token : reference_tokens) {
14033 switch (result->type()) {
14035 {
14036 if (reference_token == "0") {
14037 // start a new array if the reference token is 0
14038 result = &result->operator[](0);
14039 }
14040 else {
14041 // start a new object otherwise
14042 result = &result->operator[](reference_token);
14043 }
14044 break;
14045 }
14046
14048 {
14049 // create an entry in the object
14050 result = &result->operator[](reference_token);
14051 break;
14052 }
14053
14055 {
14056 // create an entry in the array
14057 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14058 break;
14059 }
14060
14061 /*
14062 The following code is only reached if there exists a reference
14063 token _and_ the current value is primitive. In this case, we have
14064 an error situation, because primitive values may only occur as
14065 a single value; that is, with an empty list of reference tokens.
14066 */
14074 default:
14075 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14076 }
14077 }
14078
14079 return *result;
14080 }
14081
14101 template<typename BasicJsonType>
14102 BasicJsonType& get_unchecked(BasicJsonType* ptr) const {
14103 for (const auto& reference_token : reference_tokens) {
14104 // convert null values to arrays or objects before continuing
14105 if (ptr->is_null()) {
14106 // check if the reference token is a number
14107 const bool nums =
14108 std::all_of(reference_token.begin(), reference_token.end(),
14109 [](const unsigned char x) {
14110 return std::isdigit(x);
14111 });
14112
14113 // change value to an array for numbers or "-" or to object otherwise
14114 *ptr = (nums || reference_token == "-")
14116 : detail::value_t::object;
14117 }
14118
14119 switch (ptr->type()) {
14121 {
14122 // use unchecked object access
14123 ptr = &ptr->operator[](reference_token);
14124 break;
14125 }
14126
14128 {
14129 if (reference_token == "-") {
14130 // explicitly treat "-" as index beyond the end
14131 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14132 }
14133 else {
14134 // convert array index to number; unchecked access
14135 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14136 }
14137 break;
14138 }
14139
14148 default:
14149 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14150 }
14151 }
14152
14153 return *ptr;
14154 }
14155
14162 template<typename BasicJsonType>
14163 BasicJsonType& get_checked(BasicJsonType* ptr) const {
14164 for (const auto& reference_token : reference_tokens) {
14165 switch (ptr->type()) {
14167 {
14168 // note: at performs range check
14169 ptr = &ptr->at(reference_token);
14170 break;
14171 }
14172
14174 {
14175 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) {
14176 // "-" always fails the range check
14177 JSON_THROW(detail::out_of_range::create(402, detail::concat(
14178 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14179 ") is out of range"), ptr));
14180 }
14181
14182 // note: at performs range check
14183 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14184 break;
14185 }
14186
14195 default:
14196 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14197 }
14198 }
14199
14200 return *ptr;
14201 }
14202
14216 template<typename BasicJsonType>
14217 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const {
14218 for (const auto& reference_token : reference_tokens) {
14219 switch (ptr->type()) {
14221 {
14222 // use unchecked object access
14223 ptr = &ptr->operator[](reference_token);
14224 break;
14225 }
14226
14228 {
14229 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) {
14230 // "-" cannot be used for const access
14231 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));
14232 }
14233
14234 // use unchecked array access
14235 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14236 break;
14237 }
14238
14247 default:
14248 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14249 }
14250 }
14251
14252 return *ptr;
14253 }
14254
14261 template<typename BasicJsonType>
14262 const BasicJsonType& get_checked(const BasicJsonType* ptr) const {
14263 for (const auto& reference_token : reference_tokens) {
14264 switch (ptr->type()) {
14266 {
14267 // note: at performs range check
14268 ptr = &ptr->at(reference_token);
14269 break;
14270 }
14271
14273 {
14274 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) {
14275 // "-" always fails the range check
14276 JSON_THROW(detail::out_of_range::create(402, detail::concat(
14277 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14278 ") is out of range"), ptr));
14279 }
14280
14281 // note: at performs range check
14282 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14283 break;
14284 }
14285
14294 default:
14295 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14296 }
14297 }
14298
14299 return *ptr;
14300 }
14301
14306 template<typename BasicJsonType>
14307 bool contains(const BasicJsonType* ptr) const {
14308 for (const auto& reference_token : reference_tokens) {
14309 switch (ptr->type()) {
14311 {
14312 if (!ptr->contains(reference_token)) {
14313 // we did not find the key in the object
14314 return false;
14315 }
14316
14317 ptr = &ptr->operator[](reference_token);
14318 break;
14319 }
14320
14322 {
14323 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) {
14324 // "-" always fails the range check
14325 return false;
14326 }
14327 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) {
14328 // invalid char
14329 return false;
14330 }
14331 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) {
14332 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) {
14333 // the first char should be between '1' and '9'
14334 return false;
14335 }
14336 for (std::size_t i = 1; i < reference_token.size(); i++) {
14337 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) {
14338 // other char should be between '0' and '9'
14339 return false;
14340 }
14341 }
14342 }
14343
14344 const auto idx = array_index<BasicJsonType>(reference_token);
14345 if (idx >= ptr->size()) {
14346 // index out of range
14347 return false;
14348 }
14349
14350 ptr = &ptr->operator[](idx);
14351 break;
14352 }
14353
14362 default:
14363 {
14364 // we do not expect primitive values if there is still a
14365 // reference token to process
14366 return false;
14367 }
14368 }
14369 }
14370
14371 // no reference token left means we found a primitive value
14372 return true;
14373 }
14374
14384 static std::vector<string_t> split(const string_t& reference_string) {
14385 std::vector<string_t> result;
14386
14387 // special case: empty reference string -> no reference tokens
14388 if (reference_string.empty()) {
14389 return result;
14390 }
14391
14392 // check if a nonempty reference string begins with slash
14393 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) {
14394 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
14395 }
14396
14397 // extract the reference tokens:
14398 // - slash: position of the last read slash (or end of string)
14399 // - start: position after the previous slash
14400 for (
14401 // search for the first slash after the first character
14402 std::size_t slash = reference_string.find_first_of('/', 1),
14403 // set the beginning of the first reference token
14404 start = 1;
14405 // we can stop if start == 0 (if slash == string_t::npos)
14406 start != 0;
14407 // set the beginning of the next reference token
14408 // (will eventually be 0 if slash == string_t::npos)
14409 start = (slash == string_t::npos) ? 0 : slash + 1,
14410 // find next slash
14411 slash = reference_string.find_first_of('/', start)) {
14412 // use the text between the beginning of the reference token
14413 // (start) and the last slash (slash).
14414 auto reference_token = reference_string.substr(start, slash - start);
14415
14416 // check reference tokens are properly escaped
14417 for (std::size_t pos = reference_token.find_first_of('~');
14418 pos != string_t::npos;
14419 pos = reference_token.find_first_of('~', pos + 1)) {
14420 JSON_ASSERT(reference_token[pos] == '~');
14421
14422 // ~ must be followed by 0 or 1
14423 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
14424 (reference_token[pos + 1] != '0' &&
14425 reference_token[pos + 1] != '1'))) {
14426 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
14427 }
14428 }
14429
14430 // finally, store the reference token
14431 detail::unescape(reference_token);
14432 result.push_back(reference_token);
14433 }
14434
14435 return result;
14436 }
14437
14438private:
14446 template<typename BasicJsonType>
14447 static void flatten(const string_t& reference_string,
14448 const BasicJsonType& value,
14449 BasicJsonType& result) {
14450 switch (value.type()) {
14452 {
14453 if (value.m_data.m_value.array->empty()) {
14454 // flatten empty array as null
14455 result[reference_string] = nullptr;
14456 }
14457 else {
14458 // iterate array and use index as a reference string
14459 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i) {
14460 flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
14461 value.m_data.m_value.array->operator[](i), result);
14462 }
14463 }
14464 break;
14465 }
14466
14468 {
14469 if (value.m_data.m_value.object->empty()) {
14470 // flatten empty object as null
14471 result[reference_string] = nullptr;
14472 }
14473 else {
14474 // iterate object and use keys as reference string
14475 for (const auto& element : *value.m_data.m_value.object) {
14476 flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
14477 }
14478 }
14479 break;
14480 }
14481
14490 default:
14491 {
14492 // add a primitive value with its reference string
14493 result[reference_string] = value;
14494 break;
14495 }
14496 }
14497 }
14498
14509 template<typename BasicJsonType>
14510 static BasicJsonType
14511 unflatten(const BasicJsonType& value) {
14512 if (JSON_HEDLEY_UNLIKELY(!value.is_object())) {
14513 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
14514 }
14515
14516 BasicJsonType result;
14517
14518 // iterate the JSON object values
14519 for (const auto& element : *value.m_data.m_value.object) {
14520 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) {
14521 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
14522 }
14523
14524 // Assign the value to the reference pointed to by JSON pointer. Note
14525 // that if the JSON pointer is "" (i.e., points to the whole value),
14526 // function get_and_create returns a reference to the result itself.
14527 // An assignment will then create a primitive value.
14528 json_pointer(element.first).get_and_create(result) = element.second;
14529 }
14530
14531 return result;
14532 }
14533
14534 // can't use the conversion operator because of ambiguity
14535 json_pointer<string_t> convert() const& {
14536 json_pointer<string_t> result;
14537 result.reference_tokens = reference_tokens;
14538 return result;
14539 }
14540
14541 json_pointer<string_t> convert()&& {
14542 json_pointer<string_t> result;
14543 result.reference_tokens = std::move(reference_tokens);
14544 return result;
14545 }
14546
14547public:
14548#if JSON_HAS_THREE_WAY_COMPARISON
14551 template<typename RefStringTypeRhs>
14552 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept {
14553 return reference_tokens == rhs.reference_tokens;
14554 }
14555
14558 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
14559 bool operator==(const string_t& rhs) const {
14560 return *this == json_pointer(rhs);
14561 }
14562
14564 template<typename RefStringTypeRhs>
14565 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
14566 {
14567 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
14568 }
14569#else
14572 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14573 // NOLINTNEXTLINE(readability-redundant-declaration)
14574 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14575 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14576
14579 template<typename RefStringTypeLhs, typename StringType>
14580 // NOLINTNEXTLINE(readability-redundant-declaration)
14581 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14582 const StringType& rhs);
14583
14586 template<typename RefStringTypeRhs, typename StringType>
14587 // NOLINTNEXTLINE(readability-redundant-declaration)
14588 friend bool operator==(const StringType& lhs,
14589 const json_pointer<RefStringTypeRhs>& rhs);
14590
14593 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14594 // NOLINTNEXTLINE(readability-redundant-declaration)
14595 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14596 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14597
14600 template<typename RefStringTypeLhs, typename StringType>
14601 // NOLINTNEXTLINE(readability-redundant-declaration)
14602 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14603 const StringType& rhs);
14604
14607 template<typename RefStringTypeRhs, typename StringType>
14608 // NOLINTNEXTLINE(readability-redundant-declaration)
14609 friend bool operator!=(const StringType& lhs,
14610 const json_pointer<RefStringTypeRhs>& rhs);
14611
14613 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14614 // NOLINTNEXTLINE(readability-redundant-declaration)
14615 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14616 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14617#endif
14618
14619private:
14621 std::vector<string_t> reference_tokens;
14622};
14623
14624#if !JSON_HAS_THREE_WAY_COMPARISON
14625// functions cannot be defined inside the class due to ODR violations
14626template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14627inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14628 const json_pointer<RefStringTypeRhs>& rhs) noexcept {
14629 return lhs.reference_tokens == rhs.reference_tokens;
14630}
14631
14632template<typename RefStringTypeLhs,
14633 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14634JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
14635inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14636 const StringType& rhs) {
14637 return lhs == json_pointer<RefStringTypeLhs>(rhs);
14638}
14639
14640template<typename RefStringTypeRhs,
14641 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14642JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
14643inline bool operator==(const StringType& lhs,
14644 const json_pointer<RefStringTypeRhs>& rhs) {
14645 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
14646}
14647
14648template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14649inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14650 const json_pointer<RefStringTypeRhs>& rhs) noexcept {
14651 return !(lhs == rhs);
14652}
14653
14654template<typename RefStringTypeLhs,
14655 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14656JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14657inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14658 const StringType& rhs) {
14659 return !(lhs == rhs);
14660}
14661
14662template<typename RefStringTypeRhs,
14663 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14664JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14665inline bool operator!=(const StringType& lhs,
14666 const json_pointer<RefStringTypeRhs>& rhs) {
14667 return !(lhs == rhs);
14668}
14669
14670template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14671inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14672 const json_pointer<RefStringTypeRhs>& rhs) noexcept {
14673 return lhs.reference_tokens < rhs.reference_tokens;
14674}
14675#endif
14676
14677NLOHMANN_JSON_NAMESPACE_END
14678
14679// #include <nlohmann/detail/json_ref.hpp>
14680// __ _____ _____ _____
14681// __| | __| | | | JSON for Modern C++
14682// | | |__ | | | | | | version 3.12.0
14683// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14684//
14685// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
14686// SPDX-License-Identifier: MIT
14687
14688
14689
14690#include <initializer_list>
14691#include <utility>
14692
14693// #include <nlohmann/detail/abi_macros.hpp>
14694
14695// #include <nlohmann/detail/meta/type_traits.hpp>
14696
14697
14698NLOHMANN_JSON_NAMESPACE_BEGIN
14699namespace detail {
14700
14701 template<typename BasicJsonType>
14702 class json_ref {
14703 public:
14704 using value_type = BasicJsonType;
14705
14706 json_ref(value_type&& value)
14707 : owned_value(std::move(value)) {}
14708
14709 json_ref(const value_type& value)
14710 : value_ref(&value) {}
14711
14712 json_ref(std::initializer_list<json_ref> init)
14713 : owned_value(init) {}
14714
14715 template <
14716 class... Args,
14717 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
14718 json_ref(Args && ... args)
14719 : owned_value(std::forward<Args>(args)...) {}
14720
14721 // class should be movable only
14722 json_ref(json_ref&&) noexcept = default;
14723 json_ref(const json_ref&) = delete;
14724 json_ref& operator=(const json_ref&) = delete;
14725 json_ref& operator=(json_ref&&) = delete;
14726 ~json_ref() = default;
14727
14728 value_type moved_or_copied() const {
14729 if (value_ref == nullptr) {
14730 return std::move(owned_value);
14731 }
14732 return *value_ref;
14733 }
14734
14735 value_type const& operator*() const {
14736 return value_ref ? *value_ref : owned_value;
14737 }
14738
14739 value_type const* operator->() const {
14740 return &**this;
14741 }
14742
14743 private:
14744 mutable value_type owned_value = nullptr;
14745 value_type const* value_ref = nullptr;
14746 };
14747
14748} // namespace detail
14749NLOHMANN_JSON_NAMESPACE_END
14750
14751// #include <nlohmann/detail/macro_scope.hpp>
14752
14753// #include <nlohmann/detail/string_concat.hpp>
14754
14755// #include <nlohmann/detail/string_escape.hpp>
14756
14757// #include <nlohmann/detail/string_utils.hpp>
14758
14759// #include <nlohmann/detail/meta/cpp_future.hpp>
14760
14761// #include <nlohmann/detail/meta/type_traits.hpp>
14762
14763// #include <nlohmann/detail/output/binary_writer.hpp>
14764// __ _____ _____ _____
14765// __| | __| | | | JSON for Modern C++
14766// | | |__ | | | | | | version 3.12.0
14767// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14768//
14769// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
14770// SPDX-License-Identifier: MIT
14771
14772
14773
14774#include <algorithm> // reverse
14775#include <array> // array
14776#include <map> // map
14777#include <cmath> // isnan, isinf
14778#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
14779#include <cstring> // memcpy
14780#include <limits> // numeric_limits
14781#include <string> // string
14782#include <utility> // move
14783#include <vector> // vector
14784
14785// #include <nlohmann/detail/input/binary_reader.hpp>
14786
14787// #include <nlohmann/detail/macro_scope.hpp>
14788
14789// #include <nlohmann/detail/output/output_adapters.hpp>
14790// __ _____ _____ _____
14791// __| | __| | | | JSON for Modern C++
14792// | | |__ | | | | | | version 3.12.0
14793// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14794//
14795// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
14796// SPDX-License-Identifier: MIT
14797
14798
14799
14800#include <algorithm> // copy
14801#include <cstddef> // size_t
14802#include <iterator> // back_inserter
14803#include <memory> // shared_ptr, make_shared
14804#include <string> // basic_string
14805#include <vector> // vector
14806
14807#ifndef JSON_NO_IO
14808#include <ios> // streamsize
14809#include <ostream> // basic_ostream
14810#endif // JSON_NO_IO
14811
14812// #include <nlohmann/detail/macro_scope.hpp>
14813
14814
14815NLOHMANN_JSON_NAMESPACE_BEGIN
14816namespace detail {
14817
14819 template<typename CharType> struct output_adapter_protocol {
14820 virtual void write_character(CharType c) = 0;
14821 virtual void write_characters(const CharType* s, std::size_t length) = 0;
14822 virtual ~output_adapter_protocol() = default;
14823
14824 output_adapter_protocol() = default;
14825 output_adapter_protocol(const output_adapter_protocol&) = default;
14826 output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
14827 output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
14828 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
14829 };
14830
14832 template<typename CharType>
14833 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
14834
14836 template<typename CharType, typename AllocatorType = std::allocator<CharType>>
14837 class output_vector_adapter : public output_adapter_protocol<CharType> {
14838 public:
14839 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
14840 : v(vec) {}
14841
14842 void write_character(CharType c) override {
14843 v.push_back(c);
14844 }
14845
14846 JSON_HEDLEY_NON_NULL(2)
14847 void write_characters(const CharType* s, std::size_t length) override {
14848 v.insert(v.end(), s, s + length);
14849 }
14850
14851 private:
14852 std::vector<CharType, AllocatorType>& v;
14853 };
14854
14855#ifndef JSON_NO_IO
14857 template<typename CharType>
14858 class output_stream_adapter : public output_adapter_protocol<CharType> {
14859 public:
14860 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
14861 : stream(s) {}
14862
14863 void write_character(CharType c) override {
14864 stream.put(c);
14865 }
14866
14867 JSON_HEDLEY_NON_NULL(2)
14868 void write_characters(const CharType* s, std::size_t length) override {
14869 stream.write(s, static_cast<std::streamsize>(length));
14870 }
14871
14872 private:
14873 std::basic_ostream<CharType>& stream;
14874 };
14875#endif // JSON_NO_IO
14876
14878 template<typename CharType, typename StringType = std::basic_string<CharType>>
14879 class output_string_adapter : public output_adapter_protocol<CharType> {
14880 public:
14881 explicit output_string_adapter(StringType& s) noexcept
14882 : str(s) {}
14883
14884 void write_character(CharType c) override {
14885 str.push_back(c);
14886 }
14887
14888 JSON_HEDLEY_NON_NULL(2)
14889 void write_characters(const CharType* s, std::size_t length) override {
14890 str.append(s, length);
14891 }
14892
14893 private:
14894 StringType& str;
14895 };
14896
14897 template<typename CharType, typename StringType = std::basic_string<CharType>>
14898 class output_adapter {
14899 public:
14900 template<typename AllocatorType = std::allocator<CharType>>
14901 output_adapter(std::vector<CharType, AllocatorType>& vec)
14902 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
14903
14904#ifndef JSON_NO_IO
14905 output_adapter(std::basic_ostream<CharType>& s)
14906 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
14907#endif // JSON_NO_IO
14908
14909 output_adapter(StringType& s)
14910 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
14911
14912 operator output_adapter_t<CharType>() {
14913 return oa;
14914 }
14915
14916 private:
14917 output_adapter_t<CharType> oa = nullptr;
14918 };
14919
14920} // namespace detail
14921NLOHMANN_JSON_NAMESPACE_END
14922
14923// #include <nlohmann/detail/string_concat.hpp>
14924
14925
14926NLOHMANN_JSON_NAMESPACE_BEGIN
14927namespace detail {
14928
14930 enum class bjdata_version_t {
14931 draft2,
14932 draft3,
14933 };
14934
14936 // binary writer //
14938
14942 template<typename BasicJsonType, typename CharType>
14944 using string_t = typename BasicJsonType::string_t;
14945 using binary_t = typename BasicJsonType::binary_t;
14946 using number_float_t = typename BasicJsonType::number_float_t;
14947
14948 public:
14954 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter)) {
14955 JSON_ASSERT(oa);
14956 }
14957
14962 void write_bson(const BasicJsonType& j) {
14963 switch (j.type()) {
14964 case value_t::object:
14965 {
14966 write_bson_object(*j.m_data.m_value.object);
14967 break;
14968 }
14969
14970 case value_t::null:
14971 case value_t::array:
14972 case value_t::string:
14973 case value_t::boolean:
14977 case value_t::binary:
14978 case value_t::discarded:
14979 default:
14980 {
14981 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
14982 }
14983 }
14984 }
14985
14989 void write_cbor(const BasicJsonType& j) {
14990 switch (j.type()) {
14991 case value_t::null:
14992 {
14993 oa->write_character(to_char_type(0xF6));
14994 break;
14995 }
14996
14997 case value_t::boolean:
14998 {
14999 oa->write_character(j.m_data.m_value.boolean
15000 ? to_char_type(0xF5)
15001 : to_char_type(0xF4));
15002 break;
15003 }
15004
15006 {
15007 if (j.m_data.m_value.number_integer >= 0) {
15008 // CBOR does not differentiate between positive signed
15009 // integers and unsigned integers. Therefore, we used the
15010 // code from the value_t::number_unsigned case here.
15011 if (j.m_data.m_value.number_integer <= 0x17) {
15012 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15013 }
15014 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)()) {
15015 oa->write_character(to_char_type(0x18));
15016 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15017 }
15018 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()) {
15019 oa->write_character(to_char_type(0x19));
15020 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15021 }
15022 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()) {
15023 oa->write_character(to_char_type(0x1A));
15024 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15025 }
15026 else {
15027 oa->write_character(to_char_type(0x1B));
15028 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15029 }
15030 }
15031 else {
15032 // The conversions below encode the sign in the first
15033 // byte, and the value is converted to a positive number.
15034 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15035 if (j.m_data.m_value.number_integer >= -24) {
15036 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15037 }
15038 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)()) {
15039 oa->write_character(to_char_type(0x38));
15040 write_number(static_cast<std::uint8_t>(positive_number));
15041 }
15042 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)()) {
15043 oa->write_character(to_char_type(0x39));
15044 write_number(static_cast<std::uint16_t>(positive_number));
15045 }
15046 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)()) {
15047 oa->write_character(to_char_type(0x3A));
15048 write_number(static_cast<std::uint32_t>(positive_number));
15049 }
15050 else {
15051 oa->write_character(to_char_type(0x3B));
15052 write_number(static_cast<std::uint64_t>(positive_number));
15053 }
15054 }
15055 break;
15056 }
15057
15059 {
15060 if (j.m_data.m_value.number_unsigned <= 0x17) {
15061 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15062 }
15063 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) {
15064 oa->write_character(to_char_type(0x18));
15065 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15066 }
15067 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) {
15068 oa->write_character(to_char_type(0x19));
15069 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15070 }
15071 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) {
15072 oa->write_character(to_char_type(0x1A));
15073 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15074 }
15075 else {
15076 oa->write_character(to_char_type(0x1B));
15077 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15078 }
15079 break;
15080 }
15081
15083 {
15084 if (std::isnan(j.m_data.m_value.number_float)) {
15085 // NaN is 0xf97e00 in CBOR
15086 oa->write_character(to_char_type(0xF9));
15087 oa->write_character(to_char_type(0x7E));
15088 oa->write_character(to_char_type(0x00));
15089 }
15090 else if (std::isinf(j.m_data.m_value.number_float)) {
15091 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
15092 oa->write_character(to_char_type(0xf9));
15093 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15094 oa->write_character(to_char_type(0x00));
15095 }
15096 else {
15097 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15098 }
15099 break;
15100 }
15101
15102 case value_t::string:
15103 {
15104 // step 1: write control byte and the string length
15105 const auto N = j.m_data.m_value.string->size();
15106 if (N <= 0x17) {
15107 write_number(static_cast<std::uint8_t>(0x60 + N));
15108 }
15109 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
15110 oa->write_character(to_char_type(0x78));
15111 write_number(static_cast<std::uint8_t>(N));
15112 }
15113 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
15114 oa->write_character(to_char_type(0x79));
15115 write_number(static_cast<std::uint16_t>(N));
15116 }
15117 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
15118 oa->write_character(to_char_type(0x7A));
15119 write_number(static_cast<std::uint32_t>(N));
15120 }
15121 // LCOV_EXCL_START
15122 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) {
15123 oa->write_character(to_char_type(0x7B));
15124 write_number(static_cast<std::uint64_t>(N));
15125 }
15126 // LCOV_EXCL_STOP
15127
15128 // step 2: write the string
15129 oa->write_characters(
15130 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15131 j.m_data.m_value.string->size());
15132 break;
15133 }
15134
15135 case value_t::array:
15136 {
15137 // step 1: write control byte and the array size
15138 const auto N = j.m_data.m_value.array->size();
15139 if (N <= 0x17) {
15140 write_number(static_cast<std::uint8_t>(0x80 + N));
15141 }
15142 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
15143 oa->write_character(to_char_type(0x98));
15144 write_number(static_cast<std::uint8_t>(N));
15145 }
15146 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
15147 oa->write_character(to_char_type(0x99));
15148 write_number(static_cast<std::uint16_t>(N));
15149 }
15150 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
15151 oa->write_character(to_char_type(0x9A));
15152 write_number(static_cast<std::uint32_t>(N));
15153 }
15154 // LCOV_EXCL_START
15155 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) {
15156 oa->write_character(to_char_type(0x9B));
15157 write_number(static_cast<std::uint64_t>(N));
15158 }
15159 // LCOV_EXCL_STOP
15160
15161 // step 2: write each element
15162 for (const auto& el : *j.m_data.m_value.array) {
15163 write_cbor(el);
15164 }
15165 break;
15166 }
15167
15168 case value_t::binary:
15169 {
15170 if (j.m_data.m_value.binary->has_subtype()) {
15171 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)()) {
15172 write_number(static_cast<std::uint8_t>(0xd8));
15173 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
15174 }
15175 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)()) {
15176 write_number(static_cast<std::uint8_t>(0xd9));
15177 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
15178 }
15179 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)()) {
15180 write_number(static_cast<std::uint8_t>(0xda));
15181 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
15182 }
15183 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)()) {
15184 write_number(static_cast<std::uint8_t>(0xdb));
15185 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
15186 }
15187 }
15188
15189 // step 1: write control byte and the binary array size
15190 const auto N = j.m_data.m_value.binary->size();
15191 if (N <= 0x17) {
15192 write_number(static_cast<std::uint8_t>(0x40 + N));
15193 }
15194 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
15195 oa->write_character(to_char_type(0x58));
15196 write_number(static_cast<std::uint8_t>(N));
15197 }
15198 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
15199 oa->write_character(to_char_type(0x59));
15200 write_number(static_cast<std::uint16_t>(N));
15201 }
15202 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
15203 oa->write_character(to_char_type(0x5A));
15204 write_number(static_cast<std::uint32_t>(N));
15205 }
15206 // LCOV_EXCL_START
15207 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) {
15208 oa->write_character(to_char_type(0x5B));
15209 write_number(static_cast<std::uint64_t>(N));
15210 }
15211 // LCOV_EXCL_STOP
15212
15213 // step 2: write each element
15214 oa->write_characters(
15215 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15216 N);
15217
15218 break;
15219 }
15220
15221 case value_t::object:
15222 {
15223 // step 1: write control byte and the object size
15224 const auto N = j.m_data.m_value.object->size();
15225 if (N <= 0x17) {
15226 write_number(static_cast<std::uint8_t>(0xA0 + N));
15227 }
15228 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
15229 oa->write_character(to_char_type(0xB8));
15230 write_number(static_cast<std::uint8_t>(N));
15231 }
15232 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
15233 oa->write_character(to_char_type(0xB9));
15234 write_number(static_cast<std::uint16_t>(N));
15235 }
15236 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
15237 oa->write_character(to_char_type(0xBA));
15238 write_number(static_cast<std::uint32_t>(N));
15239 }
15240 // LCOV_EXCL_START
15241 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) {
15242 oa->write_character(to_char_type(0xBB));
15243 write_number(static_cast<std::uint64_t>(N));
15244 }
15245 // LCOV_EXCL_STOP
15246
15247 // step 2: write each element
15248 for (const auto& el : *j.m_data.m_value.object) {
15249 write_cbor(el.first);
15250 write_cbor(el.second);
15251 }
15252 break;
15253 }
15254
15255 case value_t::discarded:
15256 default:
15257 break;
15258 }
15259 }
15260
15264 void write_msgpack(const BasicJsonType& j) {
15265 switch (j.type()) {
15266 case value_t::null: // nil
15267 {
15268 oa->write_character(to_char_type(0xC0));
15269 break;
15270 }
15271
15272 case value_t::boolean: // true and false
15273 {
15274 oa->write_character(j.m_data.m_value.boolean
15275 ? to_char_type(0xC3)
15276 : to_char_type(0xC2));
15277 break;
15278 }
15279
15281 {
15282 if (j.m_data.m_value.number_integer >= 0) {
15283 // MessagePack does not differentiate between positive
15284 // signed integers and unsigned integers. Therefore, we used
15285 // the code from the value_t::number_unsigned case here.
15286 if (j.m_data.m_value.number_unsigned < 128) {
15287 // positive fixnum
15288 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15289 }
15290 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) {
15291 // uint 8
15292 oa->write_character(to_char_type(0xCC));
15293 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15294 }
15295 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) {
15296 // uint 16
15297 oa->write_character(to_char_type(0xCD));
15298 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15299 }
15300 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) {
15301 // uint 32
15302 oa->write_character(to_char_type(0xCE));
15303 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15304 }
15305 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) {
15306 // uint 64
15307 oa->write_character(to_char_type(0xCF));
15308 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15309 }
15310 }
15311 else {
15312 if (j.m_data.m_value.number_integer >= -32) {
15313 // negative fixnum
15314 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15315 }
15316 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
15317 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)()) {
15318 // int 8
15319 oa->write_character(to_char_type(0xD0));
15320 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15321 }
15322 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
15323 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)()) {
15324 // int 16
15325 oa->write_character(to_char_type(0xD1));
15326 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
15327 }
15328 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
15329 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)()) {
15330 // int 32
15331 oa->write_character(to_char_type(0xD2));
15332 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
15333 }
15334 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
15335 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)()) {
15336 // int 64
15337 oa->write_character(to_char_type(0xD3));
15338 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
15339 }
15340 }
15341 break;
15342 }
15343
15345 {
15346 if (j.m_data.m_value.number_unsigned < 128) {
15347 // positive fixnum
15348 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15349 }
15350 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) {
15351 // uint 8
15352 oa->write_character(to_char_type(0xCC));
15353 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15354 }
15355 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) {
15356 // uint 16
15357 oa->write_character(to_char_type(0xCD));
15358 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15359 }
15360 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) {
15361 // uint 32
15362 oa->write_character(to_char_type(0xCE));
15363 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15364 }
15365 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) {
15366 // uint 64
15367 oa->write_character(to_char_type(0xCF));
15368 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15369 }
15370 break;
15371 }
15372
15374 {
15375 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
15376 break;
15377 }
15378
15379 case value_t::string:
15380 {
15381 // step 1: write control byte and the string length
15382 const auto N = j.m_data.m_value.string->size();
15383 if (N <= 31) {
15384 // fixstr
15385 write_number(static_cast<std::uint8_t>(0xA0 | N));
15386 }
15387 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
15388 // str 8
15389 oa->write_character(to_char_type(0xD9));
15390 write_number(static_cast<std::uint8_t>(N));
15391 }
15392 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
15393 // str 16
15394 oa->write_character(to_char_type(0xDA));
15395 write_number(static_cast<std::uint16_t>(N));
15396 }
15397 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
15398 // str 32
15399 oa->write_character(to_char_type(0xDB));
15400 write_number(static_cast<std::uint32_t>(N));
15401 }
15402
15403 // step 2: write the string
15404 oa->write_characters(
15405 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15406 j.m_data.m_value.string->size());
15407 break;
15408 }
15409
15410 case value_t::array:
15411 {
15412 // step 1: write control byte and the array size
15413 const auto N = j.m_data.m_value.array->size();
15414 if (N <= 15) {
15415 // fixarray
15416 write_number(static_cast<std::uint8_t>(0x90 | N));
15417 }
15418 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
15419 // array 16
15420 oa->write_character(to_char_type(0xDC));
15421 write_number(static_cast<std::uint16_t>(N));
15422 }
15423 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
15424 // array 32
15425 oa->write_character(to_char_type(0xDD));
15426 write_number(static_cast<std::uint32_t>(N));
15427 }
15428
15429 // step 2: write each element
15430 for (const auto& el : *j.m_data.m_value.array) {
15431 write_msgpack(el);
15432 }
15433 break;
15434 }
15435
15436 case value_t::binary:
15437 {
15438 // step 0: determine if the binary type has a set subtype to
15439 // determine whether to use the ext or fixext types
15440 const bool use_ext = j.m_data.m_value.binary->has_subtype();
15441
15442 // step 1: write control byte and the byte string length
15443 const auto N = j.m_data.m_value.binary->size();
15444 if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
15445 std::uint8_t output_type{};
15446 bool fixed = true;
15447 if (use_ext) {
15448 switch (N) {
15449 case 1:
15450 output_type = 0xD4; // fixext 1
15451 break;
15452 case 2:
15453 output_type = 0xD5; // fixext 2
15454 break;
15455 case 4:
15456 output_type = 0xD6; // fixext 4
15457 break;
15458 case 8:
15459 output_type = 0xD7; // fixext 8
15460 break;
15461 case 16:
15462 output_type = 0xD8; // fixext 16
15463 break;
15464 default:
15465 output_type = 0xC7; // ext 8
15466 fixed = false;
15467 break;
15468 }
15469
15470 }
15471 else {
15472 output_type = 0xC4; // bin 8
15473 fixed = false;
15474 }
15475
15476 oa->write_character(to_char_type(output_type));
15477 if (!fixed) {
15478 write_number(static_cast<std::uint8_t>(N));
15479 }
15480 }
15481 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
15482 const std::uint8_t output_type = use_ext
15483 ? 0xC8 // ext 16
15484 : 0xC5; // bin 16
15485
15486 oa->write_character(to_char_type(output_type));
15487 write_number(static_cast<std::uint16_t>(N));
15488 }
15489 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
15490 const std::uint8_t output_type = use_ext
15491 ? 0xC9 // ext 32
15492 : 0xC6; // bin 32
15493
15494 oa->write_character(to_char_type(output_type));
15495 write_number(static_cast<std::uint32_t>(N));
15496 }
15497
15498 // step 1.5: if this is an ext type, write the subtype
15499 if (use_ext) {
15500 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
15501 }
15502
15503 // step 2: write the byte string
15504 oa->write_characters(
15505 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15506 N);
15507
15508 break;
15509 }
15510
15511 case value_t::object:
15512 {
15513 // step 1: write control byte and the object size
15514 const auto N = j.m_data.m_value.object->size();
15515 if (N <= 15) {
15516 // fixmap
15517 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
15518 }
15519 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
15520 // map 16
15521 oa->write_character(to_char_type(0xDE));
15522 write_number(static_cast<std::uint16_t>(N));
15523 }
15524 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
15525 // map 32
15526 oa->write_character(to_char_type(0xDF));
15527 write_number(static_cast<std::uint32_t>(N));
15528 }
15529
15530 // step 2: write each element
15531 for (const auto& el : *j.m_data.m_value.object) {
15532 write_msgpack(el.first);
15533 write_msgpack(el.second);
15534 }
15535 break;
15536 }
15537
15538 case value_t::discarded:
15539 default:
15540 break;
15541 }
15542 }
15543
15552 void write_ubjson(const BasicJsonType& j, const bool use_count,
15553 const bool use_type, const bool add_prefix = true,
15554 const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2) {
15555 const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3;
15556
15557 switch (j.type()) {
15558 case value_t::null:
15559 {
15560 if (add_prefix) {
15561 oa->write_character(to_char_type('Z'));
15562 }
15563 break;
15564 }
15565
15566 case value_t::boolean:
15567 {
15568 if (add_prefix) {
15569 oa->write_character(j.m_data.m_value.boolean
15570 ? to_char_type('T')
15571 : to_char_type('F'));
15572 }
15573 break;
15574 }
15575
15577 {
15578 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
15579 break;
15580 }
15581
15583 {
15584 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
15585 break;
15586 }
15587
15589 {
15590 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
15591 break;
15592 }
15593
15594 case value_t::string:
15595 {
15596 if (add_prefix) {
15597 oa->write_character(to_char_type('S'));
15598 }
15599 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
15600 oa->write_characters(
15601 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15602 j.m_data.m_value.string->size());
15603 break;
15604 }
15605
15606 case value_t::array:
15607 {
15608 if (add_prefix) {
15609 oa->write_character(to_char_type('['));
15610 }
15611
15612 bool prefix_required = true;
15613 if (use_type && !j.m_data.m_value.array->empty()) {
15614 JSON_ASSERT(use_count);
15615 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15616 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
15617 [this, first_prefix, use_bjdata](const BasicJsonType& v) {
15618 return ubjson_prefix(v, use_bjdata) == first_prefix;
15619 });
15620
15621 std::vector<CharType> bjdx = { '[', '{', 'S', 'H', 'T', 'F', 'N', 'Z' }; // excluded markers in bjdata optimized type
15622
15623 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end())) {
15624 prefix_required = false;
15625 oa->write_character(to_char_type('$'));
15626 oa->write_character(first_prefix);
15627 }
15628 }
15629
15630 if (use_count) {
15631 oa->write_character(to_char_type('#'));
15632 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
15633 }
15634
15635 for (const auto& el : *j.m_data.m_value.array) {
15636 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
15637 }
15638
15639 if (!use_count) {
15640 oa->write_character(to_char_type(']'));
15641 }
15642
15643 break;
15644 }
15645
15646 case value_t::binary:
15647 {
15648 if (add_prefix) {
15649 oa->write_character(to_char_type('['));
15650 }
15651
15652 if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty())) {
15653 JSON_ASSERT(use_count);
15654 oa->write_character(to_char_type('$'));
15655 oa->write_character(bjdata_draft3 ? 'B' : 'U');
15656 }
15657
15658 if (use_count) {
15659 oa->write_character(to_char_type('#'));
15660 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
15661 }
15662
15663 if (use_type) {
15664 oa->write_characters(
15665 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15666 j.m_data.m_value.binary->size());
15667 }
15668 else {
15669 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i) {
15670 oa->write_character(to_char_type(bjdata_draft3 ? 'B' : 'U'));
15671 oa->write_character(j.m_data.m_value.binary->data()[i]);
15672 }
15673 }
15674
15675 if (!use_count) {
15676 oa->write_character(to_char_type(']'));
15677 }
15678
15679 break;
15680 }
15681
15682 case value_t::object:
15683 {
15684 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()) {
15685 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)
15686 {
15687 break;
15688 }
15689 }
15690
15691 if (add_prefix) {
15692 oa->write_character(to_char_type('{'));
15693 }
15694
15695 bool prefix_required = true;
15696 if (use_type && !j.m_data.m_value.object->empty()) {
15697 JSON_ASSERT(use_count);
15698 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15699 const bool same_prefix = std::all_of(j.begin(), j.end(),
15700 [this, first_prefix, use_bjdata](const BasicJsonType& v) {
15701 return ubjson_prefix(v, use_bjdata) == first_prefix;
15702 });
15703
15704 std::vector<CharType> bjdx = { '[', '{', 'S', 'H', 'T', 'F', 'N', 'Z' }; // excluded markers in bjdata optimized type
15705
15706 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end())) {
15707 prefix_required = false;
15708 oa->write_character(to_char_type('$'));
15709 oa->write_character(first_prefix);
15710 }
15711 }
15712
15713 if (use_count) {
15714 oa->write_character(to_char_type('#'));
15715 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
15716 }
15717
15718 for (const auto& el : *j.m_data.m_value.object) {
15719 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
15720 oa->write_characters(
15721 reinterpret_cast<const CharType*>(el.first.c_str()),
15722 el.first.size());
15723 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
15724 }
15725
15726 if (!use_count) {
15727 oa->write_character(to_char_type('}'));
15728 }
15729
15730 break;
15731 }
15732
15733 case value_t::discarded:
15734 default:
15735 break;
15736 }
15737 }
15738
15739 private:
15741 // BSON //
15743
15748 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j) {
15749 const auto it = name.find(static_cast<typename string_t::value_type>(0));
15750 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) {
15751 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
15752 }
15753
15754 static_cast<void>(j);
15755 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
15756 }
15757
15761 void write_bson_entry_header(const string_t& name,
15762 const std::uint8_t element_type) {
15763 oa->write_character(to_char_type(element_type)); // boolean
15764 oa->write_characters(
15765 reinterpret_cast<const CharType*>(name.c_str()),
15766 name.size() + 1u);
15767 }
15768
15772 void write_bson_boolean(const string_t& name,
15773 const bool value) {
15774 write_bson_entry_header(name, 0x08);
15775 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
15776 }
15777
15781 void write_bson_double(const string_t& name,
15782 const double value) {
15783 write_bson_entry_header(name, 0x01);
15784 write_number<double>(value, true);
15785 }
15786
15790 static std::size_t calc_bson_string_size(const string_t& value) {
15791 return sizeof(std::int32_t) + value.size() + 1ul;
15792 }
15793
15797 void write_bson_string(const string_t& name,
15798 const string_t& value) {
15799 write_bson_entry_header(name, 0x02);
15800
15801 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
15802 oa->write_characters(
15803 reinterpret_cast<const CharType*>(value.c_str()),
15804 value.size() + 1);
15805 }
15806
15810 void write_bson_null(const string_t& name) {
15811 write_bson_entry_header(name, 0x0A);
15812 }
15813
15817 static std::size_t calc_bson_integer_size(const std::int64_t value) {
15818 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
15819 ? sizeof(std::int32_t)
15820 : sizeof(std::int64_t);
15821 }
15822
15826 void write_bson_integer(const string_t& name,
15827 const std::int64_t value) {
15828 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()) {
15829 write_bson_entry_header(name, 0x10); // int32
15830 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
15831 }
15832 else {
15833 write_bson_entry_header(name, 0x12); // int64
15834 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
15835 }
15836 }
15837
15841 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept {
15842 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
15843 ? sizeof(std::int32_t)
15844 : sizeof(std::int64_t);
15845 }
15846
15850 void write_bson_unsigned(const string_t& name,
15851 const BasicJsonType& j) {
15852 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) {
15853 write_bson_entry_header(name, 0x10 /* int32 */);
15854 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
15855 }
15856 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) {
15857 write_bson_entry_header(name, 0x12 /* int64 */);
15858 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
15859 }
15860 else {
15861 write_bson_entry_header(name, 0x11 /* uint64 */);
15862 write_number<std::uint64_t>(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned), true);
15863 }
15864 }
15865
15869 void write_bson_object_entry(const string_t& name,
15870 const typename BasicJsonType::object_t& value) {
15871 write_bson_entry_header(name, 0x03); // object
15872 write_bson_object(value);
15873 }
15874
15878 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) {
15879 std::size_t array_index = 0ul;
15880
15881 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) {
15882 return result + calc_bson_element_size(std::to_string(array_index++), el);
15883 });
15884
15885 return sizeof(std::int32_t) + embedded_document_size + 1ul;
15886 }
15887
15891 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value) {
15892 return sizeof(std::int32_t) + value.size() + 1ul;
15893 }
15894
15898 void write_bson_array(const string_t& name,
15899 const typename BasicJsonType::array_t& value) {
15900 write_bson_entry_header(name, 0x04); // array
15901 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
15902
15903 std::size_t array_index = 0ul;
15904
15905 for (const auto& el : value) {
15906 write_bson_element(std::to_string(array_index++), el);
15907 }
15908
15909 oa->write_character(to_char_type(0x00));
15910 }
15911
15915 void write_bson_binary(const string_t& name,
15916 const binary_t& value) {
15917 write_bson_entry_header(name, 0x05);
15918
15919 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
15920 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
15921
15922 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
15923 }
15924
15929 static std::size_t calc_bson_element_size(const string_t& name,
15930 const BasicJsonType& j) {
15931 const auto header_size = calc_bson_entry_header_size(name, j);
15932 switch (j.type()) {
15933 case value_t::object:
15934 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
15935
15936 case value_t::array:
15937 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
15938
15939 case value_t::binary:
15940 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
15941
15942 case value_t::boolean:
15943 return header_size + 1ul;
15944
15945 case value_t::number_float:
15946 return header_size + 8ul;
15947
15948 case value_t::number_integer:
15949 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
15950
15951 case value_t::number_unsigned:
15952 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
15953
15954 case value_t::string:
15955 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
15956
15957 case value_t::null:
15958 return header_size + 0ul;
15959
15960 // LCOV_EXCL_START
15961 case value_t::discarded:
15962 default:
15963 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
15964 return 0ul;
15965 // LCOV_EXCL_STOP
15966 }
15967 }
15968
15975 void write_bson_element(const string_t& name,
15976 const BasicJsonType& j) {
15977 switch (j.type()) {
15978 case value_t::object:
15979 return write_bson_object_entry(name, *j.m_data.m_value.object);
15980
15981 case value_t::array:
15982 return write_bson_array(name, *j.m_data.m_value.array);
15983
15984 case value_t::binary:
15985 return write_bson_binary(name, *j.m_data.m_value.binary);
15986
15987 case value_t::boolean:
15988 return write_bson_boolean(name, j.m_data.m_value.boolean);
15989
15990 case value_t::number_float:
15991 return write_bson_double(name, j.m_data.m_value.number_float);
15992
15993 case value_t::number_integer:
15994 return write_bson_integer(name, j.m_data.m_value.number_integer);
15995
15996 case value_t::number_unsigned:
15997 return write_bson_unsigned(name, j);
15998
15999 case value_t::string:
16000 return write_bson_string(name, *j.m_data.m_value.string);
16001
16002 case value_t::null:
16003 return write_bson_null(name);
16004
16005 // LCOV_EXCL_START
16006 case value_t::discarded:
16007 default:
16008 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16009 return;
16010 // LCOV_EXCL_STOP
16011 }
16012 }
16013
16020 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) {
16021 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
16022 [](size_t result, const typename BasicJsonType::object_t::value_type& el) {
16023 return result += calc_bson_element_size(el.first, el.second);
16024 });
16025
16026 return sizeof(std::int32_t) + document_size + 1ul;
16027 }
16028
16033 void write_bson_object(const typename BasicJsonType::object_t& value) {
16034 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
16035
16036 for (const auto& el : value) {
16037 write_bson_element(el.first, el.second);
16038 }
16039
16040 oa->write_character(to_char_type(0x00));
16041 }
16042
16044 // CBOR //
16046
16047 static constexpr CharType get_cbor_float_prefix(float /*unused*/) {
16048 return to_char_type(0xFA); // Single-Precision Float
16049 }
16050
16051 static constexpr CharType get_cbor_float_prefix(double /*unused*/) {
16052 return to_char_type(0xFB); // Double-Precision Float
16053 }
16054
16056 // MsgPack //
16058
16059 static constexpr CharType get_msgpack_float_prefix(float /*unused*/) {
16060 return to_char_type(0xCA); // float 32
16061 }
16062
16063 static constexpr CharType get_msgpack_float_prefix(double /*unused*/) {
16064 return to_char_type(0xCB); // float 64
16065 }
16066
16068 // UBJSON //
16070
16071 // UBJSON: write number (floating point)
16072 template<typename NumberType, typename std::enable_if<
16073 std::is_floating_point<NumberType>::value, int>::type = 0>
16074 void write_number_with_ubjson_prefix(const NumberType n,
16075 const bool add_prefix,
16076 const bool use_bjdata) {
16077 if (add_prefix) {
16078 oa->write_character(get_ubjson_float_prefix(n));
16079 }
16080 write_number(n, use_bjdata);
16081 }
16082
16083 // UBJSON: write number (unsigned integer)
16084 template<typename NumberType, typename std::enable_if<
16085 std::is_unsigned<NumberType>::value, int>::type = 0>
16086 void write_number_with_ubjson_prefix(const NumberType n,
16087 const bool add_prefix,
16088 const bool use_bjdata) {
16089 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) {
16090 if (add_prefix) {
16091 oa->write_character(to_char_type('i')); // int8
16092 }
16093 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16094 }
16095 else if (n <= (std::numeric_limits<std::uint8_t>::max)()) {
16096 if (add_prefix) {
16097 oa->write_character(to_char_type('U')); // uint8
16098 }
16099 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16100 }
16101 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) {
16102 if (add_prefix) {
16103 oa->write_character(to_char_type('I')); // int16
16104 }
16105 write_number(static_cast<std::int16_t>(n), use_bjdata);
16106 }
16107 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)())) {
16108 if (add_prefix) {
16109 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16110 }
16111 write_number(static_cast<std::uint16_t>(n), use_bjdata);
16112 }
16113 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) {
16114 if (add_prefix) {
16115 oa->write_character(to_char_type('l')); // int32
16116 }
16117 write_number(static_cast<std::int32_t>(n), use_bjdata);
16118 }
16119 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)())) {
16120 if (add_prefix) {
16121 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16122 }
16123 write_number(static_cast<std::uint32_t>(n), use_bjdata);
16124 }
16125 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) {
16126 if (add_prefix) {
16127 oa->write_character(to_char_type('L')); // int64
16128 }
16129 write_number(static_cast<std::int64_t>(n), use_bjdata);
16130 }
16131 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)()) {
16132 if (add_prefix) {
16133 oa->write_character(to_char_type('M')); // uint64 - bjdata only
16134 }
16135 write_number(static_cast<std::uint64_t>(n), use_bjdata);
16136 }
16137 else {
16138 if (add_prefix) {
16139 oa->write_character(to_char_type('H')); // high-precision number
16140 }
16141
16142 const auto number = BasicJsonType(n).dump();
16143 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16144 for (std::size_t i = 0; i < number.size(); ++i) {
16145 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16146 }
16147 }
16148 }
16149
16150 // UBJSON: write number (signed integer)
16151 template < typename NumberType, typename std::enable_if <
16152 std::is_signed<NumberType>::value &&
16153 !std::is_floating_point<NumberType>::value, int >::type = 0 >
16154 void write_number_with_ubjson_prefix(const NumberType n,
16155 const bool add_prefix,
16156 const bool use_bjdata) {
16157 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)()) {
16158 if (add_prefix) {
16159 oa->write_character(to_char_type('i')); // int8
16160 }
16161 write_number(static_cast<std::int8_t>(n), use_bjdata);
16162 }
16163 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)())) {
16164 if (add_prefix) {
16165 oa->write_character(to_char_type('U')); // uint8
16166 }
16167 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16168 }
16169 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)()) {
16170 if (add_prefix) {
16171 oa->write_character(to_char_type('I')); // int16
16172 }
16173 write_number(static_cast<std::int16_t>(n), use_bjdata);
16174 }
16175 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)()))) {
16176 if (add_prefix) {
16177 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16178 }
16179 write_number(static_cast<uint16_t>(n), use_bjdata);
16180 }
16181 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)()) {
16182 if (add_prefix) {
16183 oa->write_character(to_char_type('l')); // int32
16184 }
16185 write_number(static_cast<std::int32_t>(n), use_bjdata);
16186 }
16187 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)()))) {
16188 if (add_prefix) {
16189 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16190 }
16191 write_number(static_cast<uint32_t>(n), use_bjdata);
16192 }
16193 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)()) {
16194 if (add_prefix) {
16195 oa->write_character(to_char_type('L')); // int64
16196 }
16197 write_number(static_cast<std::int64_t>(n), use_bjdata);
16198 }
16199 // LCOV_EXCL_START
16200 else {
16201 if (add_prefix) {
16202 oa->write_character(to_char_type('H')); // high-precision number
16203 }
16204
16205 const auto number = BasicJsonType(n).dump();
16206 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16207 for (std::size_t i = 0; i < number.size(); ++i) {
16208 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16209 }
16210 }
16211 // LCOV_EXCL_STOP
16212 }
16213
16217 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept {
16218 switch (j.type()) {
16219 case value_t::null:
16220 return 'Z';
16221
16222 case value_t::boolean:
16223 return j.m_data.m_value.boolean ? 'T' : 'F';
16224
16225 case value_t::number_integer:
16226 {
16227 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)()) {
16228 return 'i';
16229 }
16230 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)()) {
16231 return 'U';
16232 }
16233 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)()) {
16234 return 'I';
16235 }
16236 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)())) {
16237 return 'u';
16238 }
16239 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)()) {
16240 return 'l';
16241 }
16242 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)())) {
16243 return 'm';
16244 }
16245 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)()) {
16246 return 'L';
16247 }
16248 // anything else is treated as a high-precision number
16249 return 'H'; // LCOV_EXCL_LINE
16250 }
16251
16252 case value_t::number_unsigned:
16253 {
16254 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) {
16255 return 'i';
16256 }
16257 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)())) {
16258 return 'U';
16259 }
16260 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) {
16261 return 'I';
16262 }
16263 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)())) {
16264 return 'u';
16265 }
16266 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) {
16267 return 'l';
16268 }
16269 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)())) {
16270 return 'm';
16271 }
16272 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) {
16273 return 'L';
16274 }
16275 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) {
16276 return 'M';
16277 }
16278 // anything else is treated as a high-precision number
16279 return 'H'; // LCOV_EXCL_LINE
16280 }
16281
16282 case value_t::number_float:
16283 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
16284
16285 case value_t::string:
16286 return 'S';
16287
16288 case value_t::array: // fallthrough
16289 case value_t::binary:
16290 return '[';
16291
16292 case value_t::object:
16293 return '{';
16294
16295 case value_t::discarded:
16296 default: // discarded values
16297 return 'N';
16298 }
16299 }
16300
16301 static constexpr CharType get_ubjson_float_prefix(float /*unused*/) {
16302 return 'd'; // float 32
16303 }
16304
16305 static constexpr CharType get_ubjson_float_prefix(double /*unused*/) {
16306 return 'D'; // float 64
16307 }
16308
16312 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version) {
16313 std::map<string_t, CharType> bjdtype = { {"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
16314 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'},
16315 {"char", 'C'}, {"byte", 'B'}
16316 };
16317
16318 string_t key = "_ArrayType_";
16319 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
16320 if (it == bjdtype.end()) {
16321 return true;
16322 }
16323 CharType dtype = it->second;
16324
16325 key = "_ArraySize_";
16326 std::size_t len = (value.at(key).empty() ? 0 : 1);
16327 for (const auto& el : value.at(key)) {
16328 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
16329 }
16330
16331 key = "_ArrayData_";
16332 if (value.at(key).size() != len) {
16333 return true;
16334 }
16335
16336 oa->write_character('[');
16337 oa->write_character('$');
16338 oa->write_character(dtype);
16339 oa->write_character('#');
16340
16341 key = "_ArraySize_";
16342 write_ubjson(value.at(key), use_count, use_type, true, true, bjdata_version);
16343
16344 key = "_ArrayData_";
16345 if (dtype == 'U' || dtype == 'C' || dtype == 'B') {
16346 for (const auto& el : value.at(key)) {
16347 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
16348 }
16349 }
16350 else if (dtype == 'i') {
16351 for (const auto& el : value.at(key)) {
16352 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
16353 }
16354 }
16355 else if (dtype == 'u') {
16356 for (const auto& el : value.at(key)) {
16357 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
16358 }
16359 }
16360 else if (dtype == 'I') {
16361 for (const auto& el : value.at(key)) {
16362 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
16363 }
16364 }
16365 else if (dtype == 'm') {
16366 for (const auto& el : value.at(key)) {
16367 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
16368 }
16369 }
16370 else if (dtype == 'l') {
16371 for (const auto& el : value.at(key)) {
16372 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
16373 }
16374 }
16375 else if (dtype == 'M') {
16376 for (const auto& el : value.at(key)) {
16377 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
16378 }
16379 }
16380 else if (dtype == 'L') {
16381 for (const auto& el : value.at(key)) {
16382 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
16383 }
16384 }
16385 else if (dtype == 'd') {
16386 for (const auto& el : value.at(key)) {
16387 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
16388 }
16389 }
16390 else if (dtype == 'D') {
16391 for (const auto& el : value.at(key)) {
16392 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
16393 }
16394 }
16395 return false;
16396 }
16397
16399 // Utility functions //
16401
16402 /*
16403 @brief write a number to output input
16404 @param[in] n number of type @a NumberType
16405 @param[in] OutputIsLittleEndian Set to true if output data is
16406 required to be little endian
16407 @tparam NumberType the type of the number
16408
16409 @note This function needs to respect the system's endianness, because bytes
16410 in CBOR, MessagePack, and UBJSON are stored in network order (big
16411 endian) and therefore need reordering on little endian systems.
16412 On the other hand, BSON and BJData use little endian and should reorder
16413 on big endian systems.
16414 */
16415 template<typename NumberType>
16416 void write_number(const NumberType n, const bool OutputIsLittleEndian = false) {
16417 // step 1: write the number to an array of length NumberType
16418 std::array<CharType, sizeof(NumberType)> vec{};
16419 std::memcpy(vec.data(), &n, sizeof(NumberType));
16420
16421 // step 2: write the array to output (with possible reordering)
16422 if (is_little_endian != OutputIsLittleEndian) {
16423 // reverse byte order prior to conversion if necessary
16424 std::reverse(vec.begin(), vec.end());
16425 }
16426
16427 oa->write_characters(vec.data(), sizeof(NumberType));
16428 }
16429
16430 void write_compact_float(const number_float_t n, detail::input_format_t format) {
16431#ifdef __GNUC__
16432#pragma GCC diagnostic push
16433#pragma GCC diagnostic ignored "-Wfloat-equal"
16434#endif
16435 if (!std::isfinite(n) || ((static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
16436 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
16437 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n)))) {
16438 oa->write_character(format == detail::input_format_t::cbor
16439 ? get_cbor_float_prefix(static_cast<float>(n))
16440 : get_msgpack_float_prefix(static_cast<float>(n)));
16441 write_number(static_cast<float>(n));
16442 }
16443 else {
16444 oa->write_character(format == detail::input_format_t::cbor
16445 ? get_cbor_float_prefix(n)
16446 : get_msgpack_float_prefix(n));
16447 write_number(n);
16448 }
16449#ifdef __GNUC__
16450#pragma GCC diagnostic pop
16451#endif
16452 }
16453
16454 public:
16455 // The following to_char_type functions are implement the conversion
16456 // between uint8_t and CharType. In case CharType is not unsigned,
16457 // such a conversion is required to allow values greater than 128.
16458 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
16459 template < typename C = CharType,
16460 enable_if_t < std::is_signed<C>::value&& std::is_signed<char>::value >* = nullptr >
16461 static constexpr CharType to_char_type(std::uint8_t x) noexcept {
16462 return *reinterpret_cast<char*>(&x);
16463 }
16464
16465 template < typename C = CharType,
16466 enable_if_t < std::is_signed<C>::value&& std::is_unsigned<char>::value >* = nullptr >
16467 static CharType to_char_type(std::uint8_t x) noexcept {
16468 // The std::is_trivial trait is deprecated in C++26. The replacement is to use
16469 // std::is_trivially_copyable and std::is_trivially_default_constructible.
16470 // However, some older library implementations support std::is_trivial
16471 // but not all the std::is_trivially_* traits.
16472 // Since detecting full support across all libraries is difficult,
16473 // we use std::is_trivial unless we are using a standard where it has been deprecated.
16474 // For more details, see: https://github.com/nlohmann/json/pull/4775#issuecomment-2884361627
16475#ifdef JSON_HAS_CPP_26
16476 static_assert(std::is_trivially_copyable<CharType>::value, "CharType must be trivially copyable");
16477 static_assert(std::is_trivially_default_constructible<CharType>::value, "CharType must be trivially default constructible");
16478#else
16479 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
16480#endif
16481
16482 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
16483 CharType result;
16484 std::memcpy(&result, &x, sizeof(x));
16485 return result;
16486 }
16487
16488 template<typename C = CharType,
16489 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
16490 static constexpr CharType to_char_type(std::uint8_t x) noexcept {
16491 return x;
16492 }
16493
16494 template < typename InputCharType, typename C = CharType,
16495 enable_if_t <
16496 std::is_signed<C>::value&&
16497 std::is_signed<char>::value&&
16498 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
16499 >* = nullptr >
16500 static constexpr CharType to_char_type(InputCharType x) noexcept {
16501 return x;
16502 }
16503
16504 private:
16506 const bool is_little_endian = little_endianness();
16507
16509 output_adapter_t<CharType> oa = nullptr;
16510 };
16511
16512} // namespace detail
16513NLOHMANN_JSON_NAMESPACE_END
16514
16515// #include <nlohmann/detail/output/output_adapters.hpp>
16516
16517// #include <nlohmann/detail/output/serializer.hpp>
16518// __ _____ _____ _____
16519// __| | __| | | | JSON for Modern C++
16520// | | |__ | | | | | | version 3.12.0
16521// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16522//
16523// SPDX-FileCopyrightText: 2008, 2009 Björn Hoehrmann <bjoern@hoehrmann.de>
16524// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
16525// SPDX-License-Identifier: MIT
16526
16527
16528
16529#include <algorithm> // reverse, remove, fill, find, none_of
16530#include <array> // array
16531#include <clocale> // localeconv, lconv
16532#include <cmath> // labs, isfinite, isnan, signbit
16533#include <cstddef> // size_t, ptrdiff_t
16534#include <cstdint> // uint8_t
16535#include <cstdio> // snprintf
16536#include <limits> // numeric_limits
16537#include <string> // string, char_traits
16538#include <iomanip> // setfill, setw
16539#include <type_traits> // is_same
16540#include <utility> // move
16541
16542// #include <nlohmann/detail/conversions/to_chars.hpp>
16543// __ _____ _____ _____
16544// __| | __| | | | JSON for Modern C++
16545// | | |__ | | | | | | version 3.12.0
16546// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16547//
16548// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
16549// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
16550// SPDX-License-Identifier: MIT
16551
16552
16553
16554#include <array> // array
16555#include <cmath> // signbit, isfinite
16556#include <cstdint> // intN_t, uintN_t
16557#include <cstring> // memcpy, memmove
16558#include <limits> // numeric_limits
16559#include <type_traits> // conditional
16560
16561// #include <nlohmann/detail/macro_scope.hpp>
16562
16563
16564NLOHMANN_JSON_NAMESPACE_BEGIN
16565namespace detail {
16566
16586 namespace dtoa_impl {
16587
16588 template<typename Target, typename Source>
16589 Target reinterpret_bits(const Source source) {
16590 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
16591
16592 Target target;
16593 std::memcpy(&target, &source, sizeof(Source));
16594 return target;
16595 }
16596
16597 struct diyfp // f * 2^e
16598 {
16599 static constexpr int kPrecision = 64; // = q
16600
16601 std::uint64_t f = 0;
16602 int e = 0;
16603
16604 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
16605
16610 static diyfp sub(const diyfp& x, const diyfp& y) noexcept {
16611 JSON_ASSERT(x.e == y.e);
16612 JSON_ASSERT(x.f >= y.f);
16613
16614 return { x.f - y.f, x.e };
16615 }
16616
16621 static diyfp mul(const diyfp& x, const diyfp& y) noexcept {
16622 static_assert(kPrecision == 64, "internal error");
16623
16624 // Computes:
16625 // f = round((x.f * y.f) / 2^q)
16626 // e = x.e + y.e + q
16627
16628 // Emulate the 64-bit * 64-bit multiplication:
16629 //
16630 // p = u * v
16631 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
16632 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
16633 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
16634 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
16635 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
16636 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
16637 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
16638 //
16639 // (Since Q might be larger than 2^32 - 1)
16640 //
16641 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
16642 //
16643 // (Q_hi + H does not overflow a 64-bit int)
16644 //
16645 // = p_lo + 2^64 p_hi
16646
16647 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
16648 const std::uint64_t u_hi = x.f >> 32u;
16649 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
16650 const std::uint64_t v_hi = y.f >> 32u;
16651
16652 const std::uint64_t p0 = u_lo * v_lo;
16653 const std::uint64_t p1 = u_lo * v_hi;
16654 const std::uint64_t p2 = u_hi * v_lo;
16655 const std::uint64_t p3 = u_hi * v_hi;
16656
16657 const std::uint64_t p0_hi = p0 >> 32u;
16658 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
16659 const std::uint64_t p1_hi = p1 >> 32u;
16660 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
16661 const std::uint64_t p2_hi = p2 >> 32u;
16662
16663 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
16664
16665 // The full product might now be computed as
16666 //
16667 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
16668 // p_lo = p0_lo + (Q << 32)
16669 //
16670 // But in this particular case here, the full p_lo is not required.
16671 // Effectively, we only need to add the highest bit in p_lo to p_hi (and
16672 // Q_hi + 1 does not overflow).
16673
16674 Q += std::uint64_t{ 1 } << (64u - 32u - 1u); // round, ties up
16675
16676 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
16677
16678 return { h, x.e + y.e + 64 };
16679 }
16680
16685 static diyfp normalize(diyfp x) noexcept {
16686 JSON_ASSERT(x.f != 0);
16687
16688 while ((x.f >> 63u) == 0) {
16689 x.f <<= 1u;
16690 x.e--;
16691 }
16692
16693 return x;
16694 }
16695
16700 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept {
16701 const int delta = x.e - target_exponent;
16702
16703 JSON_ASSERT(delta >= 0);
16704 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
16705
16706 return { x.f << delta, target_exponent };
16707 }
16708 };
16709
16710 struct boundaries {
16711 diyfp w;
16712 diyfp minus;
16713 diyfp plus;
16714 };
16715
16722 template<typename FloatType>
16724 JSON_ASSERT(std::isfinite(value));
16725 JSON_ASSERT(value > 0);
16726
16727 // Convert the IEEE representation into a diyfp.
16728 //
16729 // If v is denormal:
16730 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
16731 // If v is normalized:
16732 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
16733
16734 static_assert(std::numeric_limits<FloatType>::is_iec559,
16735 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
16736
16737 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
16738 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
16739 constexpr int kMinExp = 1 - kBias;
16740 constexpr std::uint64_t kHiddenBit = std::uint64_t{ 1 } << (kPrecision - 1); // = 2^(p-1)
16741
16742 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
16743
16744 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
16745 const std::uint64_t E = bits >> (kPrecision - 1);
16746 const std::uint64_t F = bits & (kHiddenBit - 1);
16747
16748 const bool is_denormal = E == 0;
16749 const diyfp v = is_denormal
16750 ? diyfp(F, kMinExp)
16751 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
16752
16753 // Compute the boundaries m- and m+ of the floating-point value
16754 // v = f * 2^e.
16755 //
16756 // Determine v- and v+, the floating-point predecessor and successor of v,
16757 // respectively.
16758 //
16759 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
16760 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
16761 //
16762 // v+ = v + 2^e
16763 //
16764 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
16765 // between m- and m+ round to v, regardless of how the input rounding
16766 // algorithm breaks ties.
16767 //
16768 // ---+-------------+-------------+-------------+-------------+--- (A)
16769 // v- m- v m+ v+
16770 //
16771 // -----------------+------+------+-------------+-------------+--- (B)
16772 // v- m- v m+ v+
16773
16774 const bool lower_boundary_is_closer = F == 0 && E > 1;
16775 const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
16776 const diyfp m_minus = lower_boundary_is_closer
16777 ? diyfp((4 * v.f) - 1, v.e - 2) // (B)
16778 : diyfp((2 * v.f) - 1, v.e - 1); // (A)
16779
16780 // Determine the normalized w+ = m+.
16781 const diyfp w_plus = diyfp::normalize(m_plus);
16782
16783 // Determine w- = m- such that e_(w-) = e_(w+).
16784 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
16785
16786 return { diyfp::normalize(v), w_minus, w_plus };
16787 }
16788
16789 // Given normalized diyfp w, Grisu needs to find a (normalized) cached
16790 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
16791 // within a certain range [alpha, gamma] (Definition 3.2 from [1])
16792 //
16793 // alpha <= e = e_c + e_w + q <= gamma
16794 //
16795 // or
16796 //
16797 // f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
16798 // <= f_c * f_w * 2^gamma
16799 //
16800 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
16801 //
16802 // 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
16803 //
16804 // or
16805 //
16806 // 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
16807 //
16808 // The choice of (alpha,gamma) determines the size of the table and the form of
16809 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
16810 // in practice:
16811 //
16812 // The idea is to cut the number c * w = f * 2^e into two parts, which can be
16813 // processed independently: An integral part p1, and a fractional part p2:
16814 //
16815 // f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
16816 // = (f div 2^-e) + (f mod 2^-e) * 2^e
16817 // = p1 + p2 * 2^e
16818 //
16819 // The conversion of p1 into decimal form requires a series of divisions and
16820 // modulos by (a power of) 10. These operations are faster for 32-bit than for
16821 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
16822 // achieved by choosing
16823 //
16824 // -e >= 32 or e <= -32 := gamma
16825 //
16826 // In order to convert the fractional part
16827 //
16828 // p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
16829 //
16830 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits
16831 // d[-i] are extracted in order:
16832 //
16833 // (10 * p2) div 2^-e = d[-1]
16834 // (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
16835 //
16836 // The multiplication by 10 must not overflow. It is sufficient to choose
16837 //
16838 // 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
16839 //
16840 // Since p2 = f mod 2^-e < 2^-e,
16841 //
16842 // -e <= 60 or e >= -60 := alpha
16843
16844 constexpr int kAlpha = -60;
16845 constexpr int kGamma = -32;
16846
16847 struct cached_power // c = f * 2^e ~= 10^k
16848 {
16849 std::uint64_t f;
16850 int e;
16851 int k;
16852 };
16853
16862 // Now
16863 //
16864 // alpha <= e_c + e + q <= gamma (1)
16865 // ==> f_c * 2^alpha <= c * 2^e * 2^q
16866 //
16867 // and since the c's are normalized, 2^(q-1) <= f_c,
16868 //
16869 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
16870 // ==> 2^(alpha - e - 1) <= c
16871 //
16872 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
16873 //
16874 // k = ceil( log_10( 2^(alpha - e - 1) ) )
16875 // = ceil( (alpha - e - 1) * log_10(2) )
16876 //
16877 // From the paper:
16878 // "In theory the result of the procedure could be wrong since c is rounded,
16879 // and the computation itself is approximated [...]. In practice, however,
16880 // this simple function is sufficient."
16881 //
16882 // For IEEE double precision floating-point numbers converted into
16883 // normalized diyfp's w = f * 2^e, with q = 64,
16884 //
16885 // e >= -1022 (min IEEE exponent)
16886 // -52 (p - 1)
16887 // -52 (p - 1, possibly normalize denormal IEEE numbers)
16888 // -11 (normalize the diyfp)
16889 // = -1137
16890 //
16891 // and
16892 //
16893 // e <= +1023 (max IEEE exponent)
16894 // -52 (p - 1)
16895 // -11 (normalize the diyfp)
16896 // = 960
16897 //
16898 // This binary exponent range [-1137,960] results in a decimal exponent
16899 // range [-307,324]. One does not need to store a cached power for each
16900 // k in this range. For each such k it suffices to find a cached power
16901 // such that the exponent of the product lies in [alpha,gamma].
16902 // This implies that the difference of the decimal exponents of adjacent
16903 // table entries must be less than or equal to
16904 //
16905 // floor( (gamma - alpha) * log_10(2) ) = 8.
16906 //
16907 // (A smaller distance gamma-alpha would require a larger table.)
16908
16909 // NB:
16910 // Actually, this function returns c, such that -60 <= e_c + e + 64 <= -34.
16911
16912 constexpr int kCachedPowersMinDecExp = -300;
16913 constexpr int kCachedPowersDecStep = 8;
16914
16915 static constexpr std::array<cached_power, 79> kCachedPowers =
16916 {
16917 {
16918 { 0xAB70FE17C79AC6CA, -1060, -300 },
16919 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
16920 { 0xBE5691EF416BD60C, -1007, -284 },
16921 { 0x8DD01FAD907FFC3C, -980, -276 },
16922 { 0xD3515C2831559A83, -954, -268 },
16923 { 0x9D71AC8FADA6C9B5, -927, -260 },
16924 { 0xEA9C227723EE8BCB, -901, -252 },
16925 { 0xAECC49914078536D, -874, -244 },
16926 { 0x823C12795DB6CE57, -847, -236 },
16927 { 0xC21094364DFB5637, -821, -228 },
16928 { 0x9096EA6F3848984F, -794, -220 },
16929 { 0xD77485CB25823AC7, -768, -212 },
16930 { 0xA086CFCD97BF97F4, -741, -204 },
16931 { 0xEF340A98172AACE5, -715, -196 },
16932 { 0xB23867FB2A35B28E, -688, -188 },
16933 { 0x84C8D4DFD2C63F3B, -661, -180 },
16934 { 0xC5DD44271AD3CDBA, -635, -172 },
16935 { 0x936B9FCEBB25C996, -608, -164 },
16936 { 0xDBAC6C247D62A584, -582, -156 },
16937 { 0xA3AB66580D5FDAF6, -555, -148 },
16938 { 0xF3E2F893DEC3F126, -529, -140 },
16939 { 0xB5B5ADA8AAFF80B8, -502, -132 },
16940 { 0x87625F056C7C4A8B, -475, -124 },
16941 { 0xC9BCFF6034C13053, -449, -116 },
16942 { 0x964E858C91BA2655, -422, -108 },
16943 { 0xDFF9772470297EBD, -396, -100 },
16944 { 0xA6DFBD9FB8E5B88F, -369, -92 },
16945 { 0xF8A95FCF88747D94, -343, -84 },
16946 { 0xB94470938FA89BCF, -316, -76 },
16947 { 0x8A08F0F8BF0F156B, -289, -68 },
16948 { 0xCDB02555653131B6, -263, -60 },
16949 { 0x993FE2C6D07B7FAC, -236, -52 },
16950 { 0xE45C10C42A2B3B06, -210, -44 },
16951 { 0xAA242499697392D3, -183, -36 },
16952 { 0xFD87B5F28300CA0E, -157, -28 },
16953 { 0xBCE5086492111AEB, -130, -20 },
16954 { 0x8CBCCC096F5088CC, -103, -12 },
16955 { 0xD1B71758E219652C, -77, -4 },
16956 { 0x9C40000000000000, -50, 4 },
16957 { 0xE8D4A51000000000, -24, 12 },
16958 { 0xAD78EBC5AC620000, 3, 20 },
16959 { 0x813F3978F8940984, 30, 28 },
16960 { 0xC097CE7BC90715B3, 56, 36 },
16961 { 0x8F7E32CE7BEA5C70, 83, 44 },
16962 { 0xD5D238A4ABE98068, 109, 52 },
16963 { 0x9F4F2726179A2245, 136, 60 },
16964 { 0xED63A231D4C4FB27, 162, 68 },
16965 { 0xB0DE65388CC8ADA8, 189, 76 },
16966 { 0x83C7088E1AAB65DB, 216, 84 },
16967 { 0xC45D1DF942711D9A, 242, 92 },
16968 { 0x924D692CA61BE758, 269, 100 },
16969 { 0xDA01EE641A708DEA, 295, 108 },
16970 { 0xA26DA3999AEF774A, 322, 116 },
16971 { 0xF209787BB47D6B85, 348, 124 },
16972 { 0xB454E4A179DD1877, 375, 132 },
16973 { 0x865B86925B9BC5C2, 402, 140 },
16974 { 0xC83553C5C8965D3D, 428, 148 },
16975 { 0x952AB45CFA97A0B3, 455, 156 },
16976 { 0xDE469FBD99A05FE3, 481, 164 },
16977 { 0xA59BC234DB398C25, 508, 172 },
16978 { 0xF6C69A72A3989F5C, 534, 180 },
16979 { 0xB7DCBF5354E9BECE, 561, 188 },
16980 { 0x88FCF317F22241E2, 588, 196 },
16981 { 0xCC20CE9BD35C78A5, 614, 204 },
16982 { 0x98165AF37B2153DF, 641, 212 },
16983 { 0xE2A0B5DC971F303A, 667, 220 },
16984 { 0xA8D9D1535CE3B396, 694, 228 },
16985 { 0xFB9B7CD9A4A7443C, 720, 236 },
16986 { 0xBB764C4CA7A44410, 747, 244 },
16987 { 0x8BAB8EEFB6409C1A, 774, 252 },
16988 { 0xD01FEF10A657842C, 800, 260 },
16989 { 0x9B10A4E5E9913129, 827, 268 },
16990 { 0xE7109BFBA19C0C9D, 853, 276 },
16991 { 0xAC2820D9623BF429, 880, 284 },
16992 { 0x80444B5E7AA7CF85, 907, 292 },
16993 { 0xBF21E44003ACDD2D, 933, 300 },
16994 { 0x8E679C2F5E44FF8F, 960, 308 },
16995 { 0xD433179D9C8CB841, 986, 316 },
16996 { 0x9E19DB92B4E31BA9, 1013, 324 },
16997 }
16998 };
16999
17000 // This computation gives exactly the same results for k as
17001 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
17002 // for |e| <= 1500, but doesn't require floating-point operations.
17003 // NB: log_10(2) ~= 78913 / 2^18
17004 JSON_ASSERT(e >= -1500);
17005 JSON_ASSERT(e <= 1500);
17006 const int f = kAlpha - e - 1;
17007 const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
17008
17009 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
17010 JSON_ASSERT(index >= 0);
17011 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
17012
17013 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
17014 JSON_ASSERT(kAlpha <= cached.e + e + 64);
17015 JSON_ASSERT(kGamma >= cached.e + e + 64);
17016
17017 return cached;
17018 }
17019
17024 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) {
17025 // LCOV_EXCL_START
17026 if (n >= 1000000000) {
17027 pow10 = 1000000000;
17028 return 10;
17029 }
17030 // LCOV_EXCL_STOP
17031 if (n >= 100000000) {
17032 pow10 = 100000000;
17033 return 9;
17034 }
17035 if (n >= 10000000) {
17036 pow10 = 10000000;
17037 return 8;
17038 }
17039 if (n >= 1000000) {
17040 pow10 = 1000000;
17041 return 7;
17042 }
17043 if (n >= 100000) {
17044 pow10 = 100000;
17045 return 6;
17046 }
17047 if (n >= 10000) {
17048 pow10 = 10000;
17049 return 5;
17050 }
17051 if (n >= 1000) {
17052 pow10 = 1000;
17053 return 4;
17054 }
17055 if (n >= 100) {
17056 pow10 = 100;
17057 return 3;
17058 }
17059 if (n >= 10) {
17060 pow10 = 10;
17061 return 2;
17062 }
17063
17064 pow10 = 1;
17065 return 1;
17066 }
17067
17068 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
17069 std::uint64_t rest, std::uint64_t ten_k) {
17070 JSON_ASSERT(len >= 1);
17071 JSON_ASSERT(dist <= delta);
17072 JSON_ASSERT(rest <= delta);
17073 JSON_ASSERT(ten_k > 0);
17074
17075 // <--------------------------- delta ---->
17076 // <---- dist --------->
17077 // --------------[------------------+-------------------]--------------
17078 // M- w M+
17079 //
17080 // ten_k
17081 // <------>
17082 // <---- rest ---->
17083 // --------------[------------------+----+--------------]--------------
17084 // w V
17085 // = buf * 10^k
17086 //
17087 // ten_k represents a unit-in-the-last-place in the decimal representation
17088 // stored in buf.
17089 // Decrement buf by ten_k while this takes buf closer to w.
17090
17091 // The tests are written in this order to avoid overflow in unsigned
17092 // integer arithmetic.
17093
17094 while (rest < dist
17095 && delta - rest >= ten_k
17096 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) {
17097 JSON_ASSERT(buf[len - 1] != '0');
17098 buf[len - 1]--;
17099 rest += ten_k;
17100 }
17101 }
17102
17107 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
17108 diyfp M_minus, diyfp w, diyfp M_plus) {
17109 static_assert(kAlpha >= -60, "internal error");
17110 static_assert(kGamma <= -32, "internal error");
17111
17112 // Generates the digits (and the exponent) of a decimal floating-point
17113 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
17114 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
17115 //
17116 // <--------------------------- delta ---->
17117 // <---- dist --------->
17118 // --------------[------------------+-------------------]--------------
17119 // M- w M+
17120 //
17121 // Grisu2 generates the digits of M+ from left to right and stops as soon as
17122 // V is in [M-,M+].
17123
17124 JSON_ASSERT(M_plus.e >= kAlpha);
17125 JSON_ASSERT(M_plus.e <= kGamma);
17126
17127 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
17128 std::uint64_t dist = diyfp::sub(M_plus, w).f; // (significand of (M+ - w ), implicit exponent is e)
17129
17130 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
17131 //
17132 // M+ = f * 2^e
17133 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
17134 // = ((p1 ) * 2^-e + (p2 )) * 2^e
17135 // = p1 + p2 * 2^e
17136
17137 const diyfp one(std::uint64_t{ 1 } << -M_plus.e, M_plus.e);
17138
17139 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.)
17140 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
17141
17142 // 1)
17143 //
17144 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
17145
17146 JSON_ASSERT(p1 > 0);
17147
17148 std::uint32_t pow10{};
17149 const int k = find_largest_pow10(p1, pow10);
17150
17151 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
17152 //
17153 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
17154 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
17155 //
17156 // M+ = p1 + p2 * 2^e
17157 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
17158 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
17159 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
17160 //
17161 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
17162 //
17163 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
17164 //
17165 // but stop as soon as
17166 //
17167 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
17168
17169 int n = k;
17170 while (n > 0) {
17171 // Invariants:
17172 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
17173 // pow10 = 10^(n-1) <= p1 < 10^n
17174 //
17175 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
17176 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
17177 //
17178 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
17179 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
17180 //
17181 JSON_ASSERT(d <= 9);
17182 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17183 //
17184 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
17185 //
17186 p1 = r;
17187 n--;
17188 //
17189 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
17190 // pow10 = 10^n
17191 //
17192
17193 // Now check if enough digits have been generated.
17194 // Compute
17195 //
17196 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
17197 //
17198 // Note:
17199 // Since rest and delta share the same exponent e, it suffices to
17200 // compare the significands.
17201 const std::uint64_t rest = (std::uint64_t{ p1 } << -one.e) + p2;
17202 if (rest <= delta) {
17203 // V = buffer * 10^n, with M- <= V <= M+.
17204
17205 decimal_exponent += n;
17206
17207 // We may now just stop. But instead, it looks as if the buffer
17208 // could be decremented to bring V closer to w.
17209 //
17210 // pow10 = 10^n is now 1 ulp in the decimal representation V.
17211 // The rounding procedure works with diyfp's with an implicit
17212 // exponent of e.
17213 //
17214 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
17215 //
17216 const std::uint64_t ten_n = std::uint64_t{ pow10 } << -one.e;
17217 grisu2_round(buffer, length, dist, delta, rest, ten_n);
17218
17219 return;
17220 }
17221
17222 pow10 /= 10;
17223 //
17224 // pow10 = 10^(n-1) <= p1 < 10^n
17225 // Invariants restored.
17226 }
17227
17228 // 2)
17229 //
17230 // The digits of the integral part have been generated:
17231 //
17232 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
17233 // = buffer + p2 * 2^e
17234 //
17235 // Now generate the digits of the fractional part p2 * 2^e.
17236 //
17237 // Note:
17238 // No decimal point is generated: the exponent is adjusted instead.
17239 //
17240 // p2 actually represents the fraction
17241 //
17242 // p2 * 2^e
17243 // = p2 / 2^-e
17244 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
17245 //
17246 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
17247 //
17248 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
17249 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
17250 //
17251 // using
17252 //
17253 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
17254 // = ( d) * 2^-e + ( r)
17255 //
17256 // or
17257 // 10^m * p2 * 2^e = d + r * 2^e
17258 //
17259 // i.e.
17260 //
17261 // M+ = buffer + p2 * 2^e
17262 // = buffer + 10^-m * (d + r * 2^e)
17263 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
17264 //
17265 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
17266
17267 JSON_ASSERT(p2 > delta);
17268
17269 int m = 0;
17270 for (;;) {
17271 // Invariant:
17272 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
17273 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
17274 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
17275 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
17276 //
17277 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
17278 p2 *= 10;
17279 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
17280 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
17281 //
17282 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
17283 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
17284 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
17285 //
17286 JSON_ASSERT(d <= 9);
17287 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17288 //
17289 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
17290 //
17291 p2 = r;
17292 m++;
17293 //
17294 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
17295 // Invariant restored.
17296
17297 // Check if enough digits have been generated.
17298 //
17299 // 10^-m * p2 * 2^e <= delta * 2^e
17300 // p2 * 2^e <= 10^m * delta * 2^e
17301 // p2 <= 10^m * delta
17302 delta *= 10;
17303 dist *= 10;
17304 if (p2 <= delta) {
17305 break;
17306 }
17307 }
17308
17309 // V = buffer * 10^-m, with M- <= V <= M+.
17310
17311 decimal_exponent -= m;
17312
17313 // 1 ulp in the decimal representation is now 10^-m.
17314 // Since delta and dist are now scaled by 10^m, we need to do the
17315 // same with ulp in order to keep the units in sync.
17316 //
17317 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
17318 //
17319 const std::uint64_t ten_m = one.f;
17320 grisu2_round(buffer, length, dist, delta, p2, ten_m);
17321
17322 // By construction this algorithm generates the shortest possible decimal
17323 // number (Loitsch, Theorem 6.2) which rounds back to w.
17324 // For an input number of precision p, at least
17325 //
17326 // N = 1 + ceil(p * log_10(2))
17327 //
17328 // decimal digits are sufficient to identify all binary floating-point
17329 // numbers (Matula, "In-and-Out conversions").
17330 // This implies that the algorithm does not produce more than N decimal
17331 // digits.
17332 //
17333 // N = 17 for p = 53 (IEEE double precision)
17334 // N = 9 for p = 24 (IEEE single precision)
17335 }
17336
17342 JSON_HEDLEY_NON_NULL(1)
17343 inline void grisu2(char* buf, int& len, int& decimal_exponent,
17344 diyfp m_minus, diyfp v, diyfp m_plus) {
17345 JSON_ASSERT(m_plus.e == m_minus.e);
17346 JSON_ASSERT(m_plus.e == v.e);
17347
17348 // --------(-----------------------+-----------------------)-------- (A)
17349 // m- v m+
17350 //
17351 // --------------------(-----------+-----------------------)-------- (B)
17352 // m- v m+
17353 //
17354 // First scale v (and m- and m+) such that the exponent is in the range
17355 // [alpha, gamma].
17356
17357 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
17358
17359 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
17360
17361 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
17362 const diyfp w = diyfp::mul(v, c_minus_k);
17363 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17364 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
17365
17366 // ----(---+---)---------------(---+---)---------------(---+---)----
17367 // w- w w+
17368 // = c*m- = c*v = c*m+
17369 //
17370 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
17371 // w+ are now off by a small amount.
17372 // In fact:
17373 //
17374 // w - v * 10^k < 1 ulp
17375 //
17376 // To account for this inaccuracy, add resp. subtract 1 ulp.
17377 //
17378 // --------+---[---------------(---+---)---------------]---+--------
17379 // w- M- w M+ w+
17380 //
17381 // Now any number in [M-, M+] (bounds included) will round to w when input,
17382 // regardless of how the input rounding algorithm breaks ties.
17383 //
17384 // And digit_gen generates the shortest possible such number in [M-, M+].
17385 // Note that this does not mean that Grisu2 always generates the shortest
17386 // possible number in the interval (m-, m+).
17387 const diyfp M_minus(w_minus.f + 1, w_minus.e);
17388 const diyfp M_plus(w_plus.f - 1, w_plus.e);
17389
17390 decimal_exponent = -cached.k; // = -(-k) = k
17391
17392 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
17393 }
17394
17400 template<typename FloatType>
17401 JSON_HEDLEY_NON_NULL(1)
17402 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) {
17403 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17404 "internal error: not enough precision");
17405
17406 JSON_ASSERT(std::isfinite(value));
17407 JSON_ASSERT(value > 0);
17408
17409 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
17410 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
17411 // decimal representations are not exactly "short".
17412 //
17413 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
17414 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
17415 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
17416 // does.
17417 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
17418 // representation using the corresponding std::from_chars function recovers value exactly". That
17419 // indicates that single precision floating-point numbers should be recovered using
17420 // 'std::strtof'.
17421 //
17422 // NB: If the neighbors are computed for single-precision numbers, there is a single float
17423 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
17424 // value is off by 1 ulp.
17425#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
17426 const boundaries w = compute_boundaries(static_cast<double>(value));
17427#else
17428 const boundaries w = compute_boundaries(value);
17429#endif
17430
17431 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
17432 }
17433
17439 JSON_HEDLEY_NON_NULL(1)
17440 JSON_HEDLEY_RETURNS_NON_NULL
17441 inline char* append_exponent(char* buf, int e) {
17442 JSON_ASSERT(e > -1000);
17443 JSON_ASSERT(e < 1000);
17444
17445 if (e < 0) {
17446 e = -e;
17447 *buf++ = '-';
17448 }
17449 else {
17450 *buf++ = '+';
17451 }
17452
17453 auto k = static_cast<std::uint32_t>(e);
17454 if (k < 10) {
17455 // Always print at least two digits in the exponent.
17456 // This is for compatibility with printf("%g").
17457 *buf++ = '0';
17458 *buf++ = static_cast<char>('0' + k);
17459 }
17460 else if (k < 100) {
17461 *buf++ = static_cast<char>('0' + (k / 10));
17462 k %= 10;
17463 *buf++ = static_cast<char>('0' + k);
17464 }
17465 else {
17466 *buf++ = static_cast<char>('0' + (k / 100));
17467 k %= 100;
17468 *buf++ = static_cast<char>('0' + (k / 10));
17469 k %= 10;
17470 *buf++ = static_cast<char>('0' + k);
17471 }
17472
17473 return buf;
17474 }
17475
17485 JSON_HEDLEY_NON_NULL(1)
17486 JSON_HEDLEY_RETURNS_NON_NULL
17487 inline char* format_buffer(char* buf, int len, int decimal_exponent,
17488 int min_exp, int max_exp) {
17489 JSON_ASSERT(min_exp < 0);
17490 JSON_ASSERT(max_exp > 0);
17491
17492 const int k = len;
17493 const int n = len + decimal_exponent;
17494
17495 // v = buf * 10^(n-k)
17496 // k is the length of the buffer (number of decimal digits)
17497 // n is the position of the decimal point relative to the start of the buffer.
17498
17499 if (k <= n && n <= max_exp) {
17500 // digits[000]
17501 // len <= max_exp + 2
17502
17503 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
17504 // Make it look like a floating-point number (#362, #378)
17505 buf[n + 0] = '.';
17506 buf[n + 1] = '0';
17507 return buf + (static_cast<size_t>(n) + 2);
17508 }
17509
17510 if (0 < n && n <= max_exp) {
17511 // dig.its
17512 // len <= max_digits10 + 1
17513
17514 JSON_ASSERT(k > n);
17515
17516 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
17517 buf[n] = '.';
17518 return buf + (static_cast<size_t>(k) + 1U);
17519 }
17520
17521 if (min_exp < n && n <= 0) {
17522 // 0.[000]digits
17523 // len <= 2 + (-min_exp - 1) + max_digits10
17524
17525 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
17526 buf[0] = '0';
17527 buf[1] = '.';
17528 std::memset(buf + 2, '0', static_cast<size_t>(-n));
17529 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
17530 }
17531
17532 if (k == 1) {
17533 // dE+123
17534 // len <= 1 + 5
17535
17536 buf += 1;
17537 }
17538 else {
17539 // d.igitsE+123
17540 // len <= max_digits10 + 1 + 5
17541
17542 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
17543 buf[1] = '.';
17544 buf += 1 + static_cast<size_t>(k);
17545 }
17546
17547 *buf++ = 'e';
17548 return append_exponent(buf, n - 1);
17549 }
17550
17551 } // namespace dtoa_impl
17552
17563 template<typename FloatType>
17564 JSON_HEDLEY_NON_NULL(1, 2)
17565 JSON_HEDLEY_RETURNS_NON_NULL
17566 char* to_chars(char* first, const char* last, FloatType value) {
17567 static_cast<void>(last); // maybe unused - fix warning
17568 JSON_ASSERT(std::isfinite(value));
17569
17570 // Use signbit(value) instead of (value < 0) since signbit works for -0.
17571 if (std::signbit(value)) {
17572 value = -value;
17573 *first++ = '-';
17574 }
17575
17576#ifdef __GNUC__
17577#pragma GCC diagnostic push
17578#pragma GCC diagnostic ignored "-Wfloat-equal"
17579#endif
17580 if (value == 0) // +-0
17581 {
17582 *first++ = '0';
17583 // Make it look like a floating-point number (#362, #378)
17584 *first++ = '.';
17585 *first++ = '0';
17586 return first;
17587 }
17588#ifdef __GNUC__
17589#pragma GCC diagnostic pop
17590#endif
17591
17592 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
17593
17594 // Compute v = buffer * 10^decimal_exponent.
17595 // The decimal digits are stored in the buffer, which needs to be interpreted
17596 // as an unsigned decimal integer.
17597 // len is the length of the buffer, i.e., the number of decimal digits.
17598 int len = 0;
17599 int decimal_exponent = 0;
17600 dtoa_impl::grisu2(first, len, decimal_exponent, value);
17601
17602 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
17603
17604 // Format the buffer like printf("%.*g", prec, value)
17605 constexpr int kMinExp = -4;
17606 // Use digits10 here to increase compatibility with version 2.
17607 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
17608
17609 JSON_ASSERT(last - first >= kMaxExp + 2);
17610 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
17611 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
17612
17613 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
17614 }
17615
17616} // namespace detail
17617NLOHMANN_JSON_NAMESPACE_END
17618
17619// #include <nlohmann/detail/exceptions.hpp>
17620
17621// #include <nlohmann/detail/macro_scope.hpp>
17622
17623// #include <nlohmann/detail/meta/cpp_future.hpp>
17624
17625// #include <nlohmann/detail/output/binary_writer.hpp>
17626
17627// #include <nlohmann/detail/output/output_adapters.hpp>
17628
17629// #include <nlohmann/detail/string_concat.hpp>
17630
17631// #include <nlohmann/detail/value_t.hpp>
17632
17633
17634NLOHMANN_JSON_NAMESPACE_BEGIN
17635namespace detail {
17636
17638 // serialization //
17640
17647
17648 template<typename BasicJsonType>
17650 using string_t = typename BasicJsonType::string_t;
17651 using number_float_t = typename BasicJsonType::number_float_t;
17652 using number_integer_t = typename BasicJsonType::number_integer_t;
17653 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
17654 using binary_char_t = typename BasicJsonType::binary_t::value_type;
17655 static constexpr std::uint8_t UTF8_ACCEPT = 0;
17656 static constexpr std::uint8_t UTF8_REJECT = 1;
17657
17658 public:
17664 serializer(output_adapter_t<char> s, const char ichar,
17666 : o(std::move(s))
17667 , loc(std::localeconv())
17668 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(*(loc->thousands_sep)))
17669 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(*(loc->decimal_point)))
17670 , indent_char(ichar)
17671 , indent_string(512, indent_char)
17672 , error_handler(error_handler_) {}
17673
17674 // deleted because of pointer members
17675 serializer(const serializer&) = delete;
17676 serializer& operator=(const serializer&) = delete;
17677 serializer(serializer&&) = delete;
17678 serializer& operator=(serializer&&) = delete;
17679 ~serializer() = default;
17680
17703 void dump(const BasicJsonType& val,
17704 const bool pretty_print,
17705 const bool ensure_ascii,
17706 const unsigned int indent_step,
17707 const unsigned int current_indent = 0) {
17708 switch (val.m_data.m_type) {
17709 case value_t::object:
17710 {
17711 if (val.m_data.m_value.object->empty()) {
17712 o->write_characters("{}", 2);
17713 return;
17714 }
17715
17716 if (pretty_print) {
17717 o->write_characters("{\n", 2);
17718
17719 // variable to hold indentation for recursive calls
17720 const auto new_indent = current_indent + indent_step;
17721 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) {
17722 indent_string.resize(indent_string.size() * 2, ' ');
17723 }
17724
17725 // first n-1 elements
17726 auto i = val.m_data.m_value.object->cbegin();
17727 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) {
17728 o->write_characters(indent_string.c_str(), new_indent);
17729 o->write_character('\"');
17730 dump_escaped(i->first, ensure_ascii);
17731 o->write_characters("\": ", 3);
17732 dump(i->second, true, ensure_ascii, indent_step, new_indent);
17733 o->write_characters(",\n", 2);
17734 }
17735
17736 // last element
17737 JSON_ASSERT(i != val.m_data.m_value.object->cend());
17738 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
17739 o->write_characters(indent_string.c_str(), new_indent);
17740 o->write_character('\"');
17741 dump_escaped(i->first, ensure_ascii);
17742 o->write_characters("\": ", 3);
17743 dump(i->second, true, ensure_ascii, indent_step, new_indent);
17744
17745 o->write_character('\n');
17746 o->write_characters(indent_string.c_str(), current_indent);
17747 o->write_character('}');
17748 }
17749 else {
17750 o->write_character('{');
17751
17752 // first n-1 elements
17753 auto i = val.m_data.m_value.object->cbegin();
17754 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) {
17755 o->write_character('\"');
17756 dump_escaped(i->first, ensure_ascii);
17757 o->write_characters("\":", 2);
17758 dump(i->second, false, ensure_ascii, indent_step, current_indent);
17759 o->write_character(',');
17760 }
17761
17762 // last element
17763 JSON_ASSERT(i != val.m_data.m_value.object->cend());
17764 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
17765 o->write_character('\"');
17766 dump_escaped(i->first, ensure_ascii);
17767 o->write_characters("\":", 2);
17768 dump(i->second, false, ensure_ascii, indent_step, current_indent);
17769
17770 o->write_character('}');
17771 }
17772
17773 return;
17774 }
17775
17776 case value_t::array:
17777 {
17778 if (val.m_data.m_value.array->empty()) {
17779 o->write_characters("[]", 2);
17780 return;
17781 }
17782
17783 if (pretty_print) {
17784 o->write_characters("[\n", 2);
17785
17786 // variable to hold indentation for recursive calls
17787 const auto new_indent = current_indent + indent_step;
17788 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) {
17789 indent_string.resize(indent_string.size() * 2, ' ');
17790 }
17791
17792 // first n-1 elements
17793 for (auto i = val.m_data.m_value.array->cbegin();
17794 i != val.m_data.m_value.array->cend() - 1; ++i) {
17795 o->write_characters(indent_string.c_str(), new_indent);
17796 dump(*i, true, ensure_ascii, indent_step, new_indent);
17797 o->write_characters(",\n", 2);
17798 }
17799
17800 // last element
17801 JSON_ASSERT(!val.m_data.m_value.array->empty());
17802 o->write_characters(indent_string.c_str(), new_indent);
17803 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
17804
17805 o->write_character('\n');
17806 o->write_characters(indent_string.c_str(), current_indent);
17807 o->write_character(']');
17808 }
17809 else {
17810 o->write_character('[');
17811
17812 // first n-1 elements
17813 for (auto i = val.m_data.m_value.array->cbegin();
17814 i != val.m_data.m_value.array->cend() - 1; ++i) {
17815 dump(*i, false, ensure_ascii, indent_step, current_indent);
17816 o->write_character(',');
17817 }
17818
17819 // last element
17820 JSON_ASSERT(!val.m_data.m_value.array->empty());
17821 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
17822
17823 o->write_character(']');
17824 }
17825
17826 return;
17827 }
17828
17829 case value_t::string:
17830 {
17831 o->write_character('\"');
17832 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
17833 o->write_character('\"');
17834 return;
17835 }
17836
17837 case value_t::binary:
17838 {
17839 if (pretty_print) {
17840 o->write_characters("{\n", 2);
17841
17842 // variable to hold indentation for recursive calls
17843 const auto new_indent = current_indent + indent_step;
17844 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) {
17845 indent_string.resize(indent_string.size() * 2, ' ');
17846 }
17847
17848 o->write_characters(indent_string.c_str(), new_indent);
17849
17850 o->write_characters("\"bytes\": [", 10);
17851
17852 if (!val.m_data.m_value.binary->empty()) {
17853 for (auto i = val.m_data.m_value.binary->cbegin();
17854 i != val.m_data.m_value.binary->cend() - 1; ++i) {
17855 dump_integer(*i);
17856 o->write_characters(", ", 2);
17857 }
17858 dump_integer(val.m_data.m_value.binary->back());
17859 }
17860
17861 o->write_characters("],\n", 3);
17862 o->write_characters(indent_string.c_str(), new_indent);
17863
17864 o->write_characters("\"subtype\": ", 11);
17865 if (val.m_data.m_value.binary->has_subtype()) {
17866 dump_integer(val.m_data.m_value.binary->subtype());
17867 }
17868 else {
17869 o->write_characters("null", 4);
17870 }
17871 o->write_character('\n');
17872 o->write_characters(indent_string.c_str(), current_indent);
17873 o->write_character('}');
17874 }
17875 else {
17876 o->write_characters("{\"bytes\":[", 10);
17877
17878 if (!val.m_data.m_value.binary->empty()) {
17879 for (auto i = val.m_data.m_value.binary->cbegin();
17880 i != val.m_data.m_value.binary->cend() - 1; ++i) {
17881 dump_integer(*i);
17882 o->write_character(',');
17883 }
17884 dump_integer(val.m_data.m_value.binary->back());
17885 }
17886
17887 o->write_characters("],\"subtype\":", 12);
17888 if (val.m_data.m_value.binary->has_subtype()) {
17889 dump_integer(val.m_data.m_value.binary->subtype());
17890 o->write_character('}');
17891 }
17892 else {
17893 o->write_characters("null}", 5);
17894 }
17895 }
17896 return;
17897 }
17898
17899 case value_t::boolean:
17900 {
17901 if (val.m_data.m_value.boolean) {
17902 o->write_characters("true", 4);
17903 }
17904 else {
17905 o->write_characters("false", 5);
17906 }
17907 return;
17908 }
17909
17911 {
17912 dump_integer(val.m_data.m_value.number_integer);
17913 return;
17914 }
17915
17917 {
17918 dump_integer(val.m_data.m_value.number_unsigned);
17919 return;
17920 }
17921
17923 {
17924 dump_float(val.m_data.m_value.number_float);
17925 return;
17926 }
17927
17928 case value_t::discarded:
17929 {
17930 o->write_characters("<discarded>", 11);
17931 return;
17932 }
17933
17934 case value_t::null:
17935 {
17936 o->write_characters("null", 4);
17937 return;
17938 }
17939
17940 default: // LCOV_EXCL_LINE
17941 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
17942 }
17943 }
17944
17945 JSON_PRIVATE_UNLESS_TESTED:
17960 void dump_escaped(const string_t& s, const bool ensure_ascii) {
17961 std::uint32_t codepoint{};
17962 std::uint8_t state = UTF8_ACCEPT;
17963 std::size_t bytes = 0; // number of bytes written to string_buffer
17964
17965 // number of bytes written at the point of the last valid byte
17966 std::size_t bytes_after_last_accept = 0;
17967 std::size_t undumped_chars = 0;
17968
17969 for (std::size_t i = 0; i < s.size(); ++i) {
17970 const auto byte = static_cast<std::uint8_t>(s[i]);
17971
17972 switch (decode(state, codepoint, byte)) {
17973 case UTF8_ACCEPT: // decode found a new code point
17974 {
17975 switch (codepoint) {
17976 case 0x08: // backspace
17977 {
17978 string_buffer[bytes++] = '\\';
17979 string_buffer[bytes++] = 'b';
17980 break;
17981 }
17982
17983 case 0x09: // horizontal tab
17984 {
17985 string_buffer[bytes++] = '\\';
17986 string_buffer[bytes++] = 't';
17987 break;
17988 }
17989
17990 case 0x0A: // newline
17991 {
17992 string_buffer[bytes++] = '\\';
17993 string_buffer[bytes++] = 'n';
17994 break;
17995 }
17996
17997 case 0x0C: // formfeed
17998 {
17999 string_buffer[bytes++] = '\\';
18000 string_buffer[bytes++] = 'f';
18001 break;
18002 }
18003
18004 case 0x0D: // carriage return
18005 {
18006 string_buffer[bytes++] = '\\';
18007 string_buffer[bytes++] = 'r';
18008 break;
18009 }
18010
18011 case 0x22: // quotation mark
18012 {
18013 string_buffer[bytes++] = '\\';
18014 string_buffer[bytes++] = '\"';
18015 break;
18016 }
18017
18018 case 0x5C: // reverse solidus
18019 {
18020 string_buffer[bytes++] = '\\';
18021 string_buffer[bytes++] = '\\';
18022 break;
18023 }
18024
18025 default:
18026 {
18027 // escape control characters (0x00..0x1F) or, if
18028 // ensure_ascii parameter is used, non-ASCII characters
18029 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) {
18030 if (codepoint <= 0xFFFF) {
18031 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18032 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
18033 static_cast<std::uint16_t>(codepoint)));
18034 bytes += 6;
18035 }
18036 else {
18037 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18038 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
18039 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
18040 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
18041 bytes += 12;
18042 }
18043 }
18044 else {
18045 // copy byte to buffer (all previous bytes
18046 // been copied have in default case above)
18047 string_buffer[bytes++] = s[i];
18048 }
18049 break;
18050 }
18051 }
18052
18053 // write buffer and reset index; there must be 13 bytes
18054 // left, as this is the maximal number of bytes to be
18055 // written ("\uxxxx\uxxxx\0") for one code point
18056 if (string_buffer.size() - bytes < 13) {
18057 o->write_characters(string_buffer.data(), bytes);
18058 bytes = 0;
18059 }
18060
18061 // remember the byte position of this accept
18062 bytes_after_last_accept = bytes;
18063 undumped_chars = 0;
18064 break;
18065 }
18066
18067 case UTF8_REJECT: // decode found invalid UTF-8 byte
18068 {
18069 switch (error_handler) {
18070 case error_handler_t::strict:
18071 {
18072 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
18073 }
18074
18075 case error_handler_t::ignore:
18076 case error_handler_t::replace:
18077 {
18078 // in case we saw this character the first time, we
18079 // would like to read it again, because the byte
18080 // may be OK for itself, but just not OK for the
18081 // previous sequence
18082 if (undumped_chars > 0) {
18083 --i;
18084 }
18085
18086 // reset length buffer to the last accepted index;
18087 // thus removing/ignoring the invalid characters
18088 bytes = bytes_after_last_accept;
18089
18090 if (error_handler == error_handler_t::replace) {
18091 // add a replacement character
18092 if (ensure_ascii) {
18093 string_buffer[bytes++] = '\\';
18094 string_buffer[bytes++] = 'u';
18095 string_buffer[bytes++] = 'f';
18096 string_buffer[bytes++] = 'f';
18097 string_buffer[bytes++] = 'f';
18098 string_buffer[bytes++] = 'd';
18099 }
18100 else {
18101 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
18102 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
18103 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
18104 }
18105
18106 // write buffer and reset index; there must be 13 bytes
18107 // left, as this is the maximal number of bytes to be
18108 // written ("\uxxxx\uxxxx\0") for one code point
18109 if (string_buffer.size() - bytes < 13) {
18110 o->write_characters(string_buffer.data(), bytes);
18111 bytes = 0;
18112 }
18113
18114 bytes_after_last_accept = bytes;
18115 }
18116
18117 undumped_chars = 0;
18118
18119 // continue processing the string
18120 state = UTF8_ACCEPT;
18121 break;
18122 }
18123
18124 default: // LCOV_EXCL_LINE
18125 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18126 }
18127 break;
18128 }
18129
18130 default: // decode found yet incomplete multibyte code point
18131 {
18132 if (!ensure_ascii) {
18133 // code point will not be escaped - copy byte to buffer
18134 string_buffer[bytes++] = s[i];
18135 }
18136 ++undumped_chars;
18137 break;
18138 }
18139 }
18140 }
18141
18142 // we finished processing the string
18143 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) {
18144 // write buffer
18145 if (bytes > 0) {
18146 o->write_characters(string_buffer.data(), bytes);
18147 }
18148 }
18149 else {
18150 // we finish reading, but do not accept: string was incomplete
18151 switch (error_handler) {
18152 case error_handler_t::strict:
18153 {
18154 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));
18155 }
18156
18157 case error_handler_t::ignore:
18158 {
18159 // write all accepted bytes
18160 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18161 break;
18162 }
18163
18164 case error_handler_t::replace:
18165 {
18166 // write all accepted bytes
18167 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18168 // add a replacement character
18169 if (ensure_ascii) {
18170 o->write_characters("\\ufffd", 6);
18171 }
18172 else {
18173 o->write_characters("\xEF\xBF\xBD", 3);
18174 }
18175 break;
18176 }
18177
18178 default: // LCOV_EXCL_LINE
18179 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18180 }
18181 }
18182 }
18183
18184 private:
18193 unsigned int count_digits(number_unsigned_t x) noexcept {
18194 unsigned int n_digits = 1;
18195 for (;;) {
18196 if (x < 10) {
18197 return n_digits;
18198 }
18199 if (x < 100) {
18200 return n_digits + 1;
18201 }
18202 if (x < 1000) {
18203 return n_digits + 2;
18204 }
18205 if (x < 10000) {
18206 return n_digits + 3;
18207 }
18208 x = x / 10000u;
18209 n_digits += 4;
18210 }
18211 }
18212
18218 static std::string hex_bytes(std::uint8_t byte) {
18219 std::string result = "FF";
18220 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
18221 result[0] = nibble_to_hex[byte / 16];
18222 result[1] = nibble_to_hex[byte % 16];
18223 return result;
18224 }
18225
18226 // templates to avoid warnings about useless casts
18227 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
18228 bool is_negative_number(NumberType x) {
18229 return x < 0;
18230 }
18231
18232 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
18233 bool is_negative_number(NumberType /*unused*/) {
18234 return false;
18235 }
18236
18246 template < typename NumberType, detail::enable_if_t <
18247 std::is_integral<NumberType>::value ||
18248 std::is_same<NumberType, number_unsigned_t>::value ||
18249 std::is_same<NumberType, number_integer_t>::value ||
18250 std::is_same<NumberType, binary_char_t>::value,
18251 int > = 0 >
18252 void dump_integer(NumberType x) {
18253 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18254 {
18255 {
18256 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
18257 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
18258 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
18259 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
18260 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
18261 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
18262 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
18263 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
18264 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
18265 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
18266 }
18267 };
18268
18269 // special case for "0"
18270 if (x == 0) {
18271 o->write_character('0');
18272 return;
18273 }
18274
18275 // use a pointer to fill the buffer
18276 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18277
18278 number_unsigned_t abs_value;
18279
18280 unsigned int n_chars{};
18281
18282 if (is_negative_number(x)) {
18283 *buffer_ptr = '-';
18284 abs_value = remove_sign(static_cast<number_integer_t>(x));
18285
18286 // account one more byte for the minus sign
18287 n_chars = 1 + count_digits(abs_value);
18288 }
18289 else {
18290 abs_value = static_cast<number_unsigned_t>(x);
18291 n_chars = count_digits(abs_value);
18292 }
18293
18294 // spare 1 byte for '\0'
18295 JSON_ASSERT(n_chars < number_buffer.size() - 1);
18296
18297 // jump to the end to generate the string from backward,
18298 // so we later avoid reversing the result
18299 buffer_ptr += static_cast<typename decltype(number_buffer)::difference_type>(n_chars);
18300
18301 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
18302 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
18303 while (abs_value >= 100) {
18304 const auto digits_index = static_cast<unsigned>((abs_value % 100));
18305 abs_value /= 100;
18306 *(--buffer_ptr) = digits_to_99[digits_index][1];
18307 *(--buffer_ptr) = digits_to_99[digits_index][0];
18308 }
18309
18310 if (abs_value >= 10) {
18311 const auto digits_index = static_cast<unsigned>(abs_value);
18312 *(--buffer_ptr) = digits_to_99[digits_index][1];
18313 *(--buffer_ptr) = digits_to_99[digits_index][0];
18314 }
18315 else {
18316 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
18317 }
18318
18319 o->write_characters(number_buffer.data(), n_chars);
18320 }
18321
18330 void dump_float(number_float_t x) {
18331 // NaN / inf
18332 if (!std::isfinite(x)) {
18333 o->write_characters("null", 4);
18334 return;
18335 }
18336
18337 // If number_float_t is an IEEE-754 single or double precision number,
18338 // use the Grisu2 algorithm to produce short numbers which are
18339 // guaranteed to round-trip, using strtof and strtod, resp.
18340 //
18341 // NB: The test below works if <long double> == <double>.
18342 static constexpr bool is_ieee_single_or_double
18343 = (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) ||
18344 (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);
18345
18346 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
18347 }
18348
18349 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) {
18350 auto* begin = number_buffer.data();
18351 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
18352
18353 o->write_characters(begin, static_cast<size_t>(end - begin));
18354 }
18355
18356 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) {
18357 // get the number of digits for a float -> text -> float round-trip
18358 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
18359
18360 // the actual conversion
18361 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18362 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
18363
18364 // negative value indicates an error
18365 JSON_ASSERT(len > 0);
18366 // check if the buffer was large enough
18367 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
18368
18369 // erase thousands separators
18370 if (thousands_sep != '\0') {
18371 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
18372 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
18373 std::fill(end, number_buffer.end(), '\0');
18374 JSON_ASSERT((end - number_buffer.begin()) <= len);
18375 len = (end - number_buffer.begin());
18376 }
18377
18378 // convert decimal point to '.'
18379 if (decimal_point != '\0' && decimal_point != '.') {
18380 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
18381 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
18382 if (dec_pos != number_buffer.end()) {
18383 *dec_pos = '.';
18384 }
18385 }
18386
18387 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
18388
18389 // determine if we need to append ".0"
18390 const bool value_is_int_like =
18391 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
18392 [](char c) {
18393 return c == '.' || c == 'e';
18394 });
18395
18396 if (value_is_int_like) {
18397 o->write_characters(".0", 2);
18398 }
18399 }
18400
18422 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept {
18423 static const std::array<std::uint8_t, 400> utf8d =
18424 {
18425 {
18426 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
18427 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
18428 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
18429 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
18430 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
18431 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
18432 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
18433 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
18434 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
18435 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
18436 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
18437 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
18438 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
18439 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
18440 }
18441 };
18442
18443 JSON_ASSERT(static_cast<std::size_t>(byte) < utf8d.size());
18444 const std::uint8_t type = utf8d[byte];
18445
18446 codep = (state != UTF8_ACCEPT)
18447 ? (byte & 0x3fu) | (codep << 6u)
18448 : (0xFFu >> type) & (byte);
18449
18450 const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
18451 JSON_ASSERT(index < utf8d.size());
18452 state = utf8d[index];
18453 return state;
18454 }
18455
18456 /*
18457 * Overload to make the compiler happy while it is instantiating
18458 * dump_integer for number_unsigned_t.
18459 * Must never be called.
18460 */
18461 number_unsigned_t remove_sign(number_unsigned_t x) {
18462 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18463 return x; // LCOV_EXCL_LINE
18464 }
18465
18466 /*
18467 * Helper function for dump_integer
18468 *
18469 * This function takes a negative signed integer and returns its absolute
18470 * value as an unsigned integer. The plus/minus shuffling is necessary as we
18471 * cannot directly remove the sign of an arbitrary signed integer as the
18472 * absolute values of INT_MIN and INT_MAX are usually not the same. See
18473 * #1708 for details.
18474 */
18475 number_unsigned_t remove_sign(number_integer_t x) noexcept {
18476 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
18477 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
18478 }
18479
18480 private:
18482 output_adapter_t<char> o = nullptr;
18483
18485 std::array<char, 64> number_buffer{ {} };
18486
18488 const std::lconv* loc = nullptr;
18490 const char thousands_sep = '\0';
18492 const char decimal_point = '\0';
18493
18495 std::array<char, 512> string_buffer{ {} };
18496
18498 const char indent_char;
18500 string_t indent_string;
18501
18503 const error_handler_t error_handler;
18504 };
18505
18506} // namespace detail
18507NLOHMANN_JSON_NAMESPACE_END
18508
18509// #include <nlohmann/detail/value_t.hpp>
18510
18511// #include <nlohmann/json_fwd.hpp>
18512
18513// #include <nlohmann/ordered_map.hpp>
18514// __ _____ _____ _____
18515// __| | __| | | | JSON for Modern C++
18516// | | |__ | | | | | | version 3.12.0
18517// |_____|_____|_____|_|___| https://github.com/nlohmann/json
18518//
18519// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
18520// SPDX-License-Identifier: MIT
18521
18522
18523
18524#include <functional> // equal_to, less
18525#include <initializer_list> // initializer_list
18526#include <iterator> // input_iterator_tag, iterator_traits
18527#include <memory> // allocator
18528#include <stdexcept> // for out_of_range
18529#include <type_traits> // enable_if, is_convertible
18530#include <utility> // pair
18531#include <vector> // vector
18532
18533// #include <nlohmann/detail/macro_scope.hpp>
18534
18535// #include <nlohmann/detail/meta/type_traits.hpp>
18536
18537
18538NLOHMANN_JSON_NAMESPACE_BEGIN
18539
18542template <class Key, class T, class IgnoredLess = std::less<Key>,
18543 class Allocator = std::allocator<std::pair<const Key, T>>>
18544struct ordered_map : std::vector<std::pair<const Key, T>, Allocator> {
18545 using key_type = Key;
18546 using mapped_type = T;
18547 using Container = std::vector<std::pair<const Key, T>, Allocator>;
18548 using iterator = typename Container::iterator;
18549 using const_iterator = typename Container::const_iterator;
18550 using size_type = typename Container::size_type;
18551 using value_type = typename Container::value_type;
18552#ifdef JSON_HAS_CPP_14
18553 using key_compare = std::equal_to<>;
18554#else
18555 using key_compare = std::equal_to<Key>;
18556#endif
18557
18558 // Explicit constructors instead of `using Container::Container`
18559 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
18560 ordered_map() noexcept(noexcept(Container())) : Container{} {}
18561 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{ alloc } {}
18562 template <class It>
18563 ordered_map(It first, It last, const Allocator& alloc = Allocator())
18564 : Container{ first, last, alloc } {}
18565 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator())
18566 : Container{ init, alloc } {}
18567
18568 std::pair<iterator, bool> emplace(const key_type& key, T&& t) {
18569 for (auto it = this->begin(); it != this->end(); ++it) {
18570 if (m_compare(it->first, key)) {
18571 return { it, false };
18572 }
18573 }
18574 Container::emplace_back(key, std::forward<T>(t));
18575 return { std::prev(this->end()), true };
18576 }
18577
18578 template<class KeyType, detail::enable_if_t<
18579 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
18580 std::pair<iterator, bool> emplace(KeyType&& key, T&& t) {
18581 for (auto it = this->begin(); it != this->end(); ++it) {
18582 if (m_compare(it->first, key)) {
18583 return { it, false };
18584 }
18585 }
18586 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
18587 return { std::prev(this->end()), true };
18588 }
18589
18590 T& operator[](const key_type& key) {
18591 return emplace(key, T{}).first->second;
18592 }
18593
18594 template<class KeyType, detail::enable_if_t<
18595 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
18596 T& operator[](KeyType&& key) {
18597 return emplace(std::forward<KeyType>(key), T{}).first->second;
18598 }
18599
18600 const T& operator[](const key_type& key) const {
18601 return at(key);
18602 }
18603
18604 template<class KeyType, detail::enable_if_t<
18605 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
18606 const T& operator[](KeyType&& key) const {
18607 return at(std::forward<KeyType>(key));
18608 }
18609
18610 T& at(const key_type& key) {
18611 for (auto it = this->begin(); it != this->end(); ++it) {
18612 if (m_compare(it->first, key)) {
18613 return it->second;
18614 }
18615 }
18616
18617 JSON_THROW(std::out_of_range("key not found"));
18618 }
18619
18620 template<class KeyType, detail::enable_if_t<
18621 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
18622 T& at(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
18623 {
18624 for (auto it = this->begin(); it != this->end(); ++it) {
18625 if (m_compare(it->first, key)) {
18626 return it->second;
18627 }
18628 }
18629
18630 JSON_THROW(std::out_of_range("key not found"));
18631 }
18632
18633 const T& at(const key_type& key) const {
18634 for (auto it = this->begin(); it != this->end(); ++it) {
18635 if (m_compare(it->first, key)) {
18636 return it->second;
18637 }
18638 }
18639
18640 JSON_THROW(std::out_of_range("key not found"));
18641 }
18642
18643 template<class KeyType, detail::enable_if_t<
18644 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
18645 const T& at(KeyType&& key) const // NOLINT(cppcoreguidelines-missing-std-forward)
18646 {
18647 for (auto it = this->begin(); it != this->end(); ++it) {
18648 if (m_compare(it->first, key)) {
18649 return it->second;
18650 }
18651 }
18652
18653 JSON_THROW(std::out_of_range("key not found"));
18654 }
18655
18656 size_type erase(const key_type& key) {
18657 for (auto it = this->begin(); it != this->end(); ++it) {
18658 if (m_compare(it->first, key)) {
18659 // Since we cannot move const Keys, re-construct them in place
18660 for (auto next = it; ++next != this->end(); ++it) {
18661 it->~value_type(); // Destroy but keep allocation
18662 new (&*it) value_type{ std::move(*next) };
18663 }
18664 Container::pop_back();
18665 return 1;
18666 }
18667 }
18668 return 0;
18669 }
18670
18671 template<class KeyType, detail::enable_if_t<
18672 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
18673 size_type erase(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
18674 {
18675 for (auto it = this->begin(); it != this->end(); ++it) {
18676 if (m_compare(it->first, key)) {
18677 // Since we cannot move const Keys, re-construct them in place
18678 for (auto next = it; ++next != this->end(); ++it) {
18679 it->~value_type(); // Destroy but keep allocation
18680 new (&*it) value_type{ std::move(*next) };
18681 }
18682 Container::pop_back();
18683 return 1;
18684 }
18685 }
18686 return 0;
18687 }
18688
18689 iterator erase(iterator pos) {
18690 return erase(pos, std::next(pos));
18691 }
18692
18693 iterator erase(iterator first, iterator last) {
18694 if (first == last) {
18695 return first;
18696 }
18697
18698 const auto elements_affected = std::distance(first, last);
18699 const auto offset = std::distance(Container::begin(), first);
18700
18701 // This is the start situation. We need to delete elements_affected
18702 // elements (3 in this example: e, f, g), and need to return an
18703 // iterator past the last deleted element (h in this example).
18704 // Note that offset is the distance from the start of the vector
18705 // to first. We will need this later.
18706
18707 // [ a, b, c, d, e, f, g, h, i, j ]
18708 // ^ ^
18709 // first last
18710
18711 // Since we cannot move const Keys, we re-construct them in place.
18712 // We start at first and re-construct (viz. copy) the elements from
18713 // the back of the vector. Example for the first iteration:
18714
18715 // ,--------.
18716 // v | destroy e and re-construct with h
18717 // [ a, b, c, d, e, f, g, h, i, j ]
18718 // ^ ^
18719 // it it + elements_affected
18720
18721 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it) {
18722 it->~value_type(); // destroy but keep allocation
18723 new (&*it) value_type{ std::move(*std::next(it, elements_affected)) }; // "move" next element to it
18724 }
18725
18726 // [ a, b, c, d, h, i, j, h, i, j ]
18727 // ^ ^
18728 // first last
18729
18730 // remove the unneeded elements at the end of the vector
18731 Container::resize(this->size() - static_cast<size_type>(elements_affected));
18732
18733 // [ a, b, c, d, h, i, j ]
18734 // ^ ^
18735 // first last
18736
18737 // first is now pointing past the last deleted element, but we cannot
18738 // use this iterator, because it may have been invalidated by the
18739 // resize call. Instead, we can return begin() + offset.
18740 return Container::begin() + offset;
18741 }
18742
18743 size_type count(const key_type& key) const {
18744 for (auto it = this->begin(); it != this->end(); ++it) {
18745 if (m_compare(it->first, key)) {
18746 return 1;
18747 }
18748 }
18749 return 0;
18750 }
18751
18752 template<class KeyType, detail::enable_if_t<
18753 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
18754 size_type count(KeyType&& key) const // NOLINT(cppcoreguidelines-missing-std-forward)
18755 {
18756 for (auto it = this->begin(); it != this->end(); ++it) {
18757 if (m_compare(it->first, key)) {
18758 return 1;
18759 }
18760 }
18761 return 0;
18762 }
18763
18764 iterator find(const key_type& key) {
18765 for (auto it = this->begin(); it != this->end(); ++it) {
18766 if (m_compare(it->first, key)) {
18767 return it;
18768 }
18769 }
18770 return Container::end();
18771 }
18772
18773 template<class KeyType, detail::enable_if_t<
18774 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
18775 iterator find(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
18776 {
18777 for (auto it = this->begin(); it != this->end(); ++it) {
18778 if (m_compare(it->first, key)) {
18779 return it;
18780 }
18781 }
18782 return Container::end();
18783 }
18784
18785 const_iterator find(const key_type& key) const {
18786 for (auto it = this->begin(); it != this->end(); ++it) {
18787 if (m_compare(it->first, key)) {
18788 return it;
18789 }
18790 }
18791 return Container::end();
18792 }
18793
18794 std::pair<iterator, bool> insert(value_type&& value) {
18795 return emplace(value.first, std::move(value.second));
18796 }
18797
18798 std::pair<iterator, bool> insert(const value_type& value) {
18799 for (auto it = this->begin(); it != this->end(); ++it) {
18800 if (m_compare(it->first, value.first)) {
18801 return { it, false };
18802 }
18803 }
18804 Container::push_back(value);
18805 return { --this->end(), true };
18806 }
18807
18808 template<typename InputIt>
18809 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
18810 std::input_iterator_tag>::value>::type;
18811
18812 template<typename InputIt, typename = require_input_iter<InputIt>>
18813 void insert(InputIt first, InputIt last) {
18814 for (auto it = first; it != last; ++it) {
18815 insert(*it);
18816 }
18817 }
18818
18819private:
18820 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
18821};
18822
18823NLOHMANN_JSON_NAMESPACE_END
18824
18825
18826#if defined(JSON_HAS_CPP_17)
18827#if JSON_HAS_STATIC_RTTI
18828#include <any>
18829#endif
18830#include <string_view>
18831#endif
18832
18838NLOHMANN_JSON_NAMESPACE_BEGIN
18839
18858NLOHMANN_BASIC_JSON_TPL_DECLARATION
18859class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
18860 : public ::nlohmann::detail::json_base_class<CustomBaseClass> {
18861private:
18862 template<detail::value_t> friend struct detail::external_constructor;
18863
18864 template<typename>
18865 friend class ::nlohmann::json_pointer;
18866 // can be restored when json_pointer backwards compatibility is removed
18867 // friend ::nlohmann::json_pointer<StringType>;
18868
18869 template<typename BasicJsonType, typename InputType>
18870 friend class ::nlohmann::detail::parser;
18871 friend ::nlohmann::detail::serializer<basic_json>;
18872 template<typename BasicJsonType>
18873 friend class ::nlohmann::detail::iter_impl;
18874 template<typename BasicJsonType, typename CharType>
18875 friend class ::nlohmann::detail::binary_writer;
18876 template<typename BasicJsonType, typename InputType, typename SAX>
18877 friend class ::nlohmann::detail::binary_reader;
18878 template<typename BasicJsonType, typename InputAdapterType>
18879 friend class ::nlohmann::detail::json_sax_dom_parser;
18880 template<typename BasicJsonType, typename InputAdapterType>
18881 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
18882 friend class ::nlohmann::detail::exception;
18883
18885 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
18886 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
18887
18888JSON_PRIVATE_UNLESS_TESTED:
18889 // convenience aliases for types residing in namespace detail;
18890 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
18891
18892 template<typename InputAdapterType>
18893 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
18894 InputAdapterType adapter,
18895 detail::parser_callback_t<basic_json>cb = nullptr,
18896 const bool allow_exceptions = true,
18897 const bool ignore_comments = false,
18898 const bool ignore_trailing_commas = false
18899 ) {
18900 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
18901 std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
18902 }
18903
18904private:
18905 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
18906 template<typename BasicJsonType>
18907 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
18908 template<typename BasicJsonType>
18909 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
18910 template<typename Iterator>
18911 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
18912 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
18913
18914 template<typename CharType>
18915 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
18916
18917 template<typename InputType>
18918 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
18919 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
18920
18921JSON_PRIVATE_UNLESS_TESTED:
18922 using serializer = ::nlohmann::detail::serializer<basic_json>;
18923
18924public:
18925 using value_t = detail::value_t;
18927 using json_pointer = ::nlohmann::json_pointer<StringType>;
18928 template<typename T, typename SFINAE>
18929 using json_serializer = JSONSerializer<T, SFINAE>;
18931 using error_handler_t = detail::error_handler_t;
18933 using cbor_tag_handler_t = detail::cbor_tag_handler_t;
18935 using bjdata_version_t = detail::bjdata_version_t;
18937 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
18938
18939 using input_format_t = detail::input_format_t;
18941 using json_sax_t = json_sax<basic_json>;
18942
18944 // exceptions //
18946
18950
18951 using exception = detail::exception;
18952 using parse_error = detail::parse_error;
18953 using invalid_iterator = detail::invalid_iterator;
18954 using type_error = detail::type_error;
18955 using out_of_range = detail::out_of_range;
18956 using other_error = detail::other_error;
18957
18959
18961 // container types //
18963
18968
18970 using value_type = basic_json;
18971
18973 using reference = value_type&;
18975 using const_reference = const value_type&;
18976
18978 using difference_type = std::ptrdiff_t;
18980 using size_type = std::size_t;
18981
18983 using allocator_type = AllocatorType<basic_json>;
18984
18986 using pointer = typename std::allocator_traits<allocator_type>::pointer;
18988 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
18989
18991 using iterator = iter_impl<basic_json>;
18993 using const_iterator = iter_impl<const basic_json>;
18995 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
18997 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
18998
19000
19003 static allocator_type get_allocator() {
19004 return allocator_type();
19005 }
19006
19009 JSON_HEDLEY_WARN_UNUSED_RESULT
19010 static basic_json meta() {
19011 basic_json result;
19012
19013 result["copyright"] = "(C) 2013-2026 Niels Lohmann";
19014 result["name"] = "JSON for Modern C++";
19015 result["url"] = "https://github.com/nlohmann/json";
19016 result["version"]["string"] =
19017 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
19018 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
19019 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19020 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
19021 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
19022 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
19023
19024#ifdef _WIN32
19025 result["platform"] = "win32";
19026#elif defined __linux__
19027 result["platform"] = "linux";
19028#elif defined __APPLE__
19029 result["platform"] = "apple";
19030#elif defined __unix__
19031 result["platform"] = "unix";
19032#else
19033 result["platform"] = "unknown";
19034#endif
19035
19036#if defined(__ICC) || defined(__INTEL_COMPILER)
19037 result["compiler"] = { {"family", "icc"}, {"version", __INTEL_COMPILER} };
19038#elif defined(__clang__)
19039 result["compiler"] = { {"family", "clang"}, {"version", __clang_version__} };
19040#elif defined(__GNUC__) || defined(__GNUG__)
19041 result["compiler"] = { {"family", "gcc"}, {"version", detail::concat(
19042 std::to_string(__GNUC__), '.',
19043 std::to_string(__GNUC_MINOR__), '.',
19044 std::to_string(__GNUC_PATCHLEVEL__))
19045 }
19046 };
19047#elif defined(__HP_cc) || defined(__HP_aCC)
19048 result["compiler"] = "hp"
19049#elif defined(__IBMCPP__)
19050 result["compiler"] = { {"family", "ilecpp"}, {"version", __IBMCPP__} };
19051#elif defined(_MSC_VER)
19052 result["compiler"] = { {"family", "msvc"}, {"version", _MSC_VER} };
19053#elif defined(__PGI)
19054 result["compiler"] = { {"family", "pgcpp"}, {"version", __PGI} };
19055#elif defined(__SUNPRO_CC)
19056 result["compiler"] = { {"family", "sunpro"}, {"version", __SUNPRO_CC} };
19057#else
19058 result["compiler"] = { {"family", "unknown"}, {"version", "unknown"} };
19059#endif
19060
19061#if defined(_MSVC_LANG)
19062 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
19063#elif defined(__cplusplus)
19064 result["compiler"]["c++"] = std::to_string(__cplusplus);
19065#else
19066 result["compiler"]["c++"] = "unknown";
19067#endif
19068 return result;
19069 }
19070
19072 // JSON value data types //
19074
19079
19084#if defined(JSON_HAS_CPP_14)
19085 // use of transparent comparator avoids unnecessary repeated construction of temporaries
19086 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
19087 using default_object_comparator_t = std::less<>;
19088#else
19089 using default_object_comparator_t = std::less<StringType>;
19090#endif
19091
19094 using object_t = ObjectType<StringType,
19095 basic_json,
19096 default_object_comparator_t,
19097 AllocatorType<std::pair<const StringType,
19098 basic_json>>>;
19099
19102 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19103
19106 using string_t = StringType;
19107
19110 using boolean_t = BooleanType;
19111
19114 using number_integer_t = NumberIntegerType;
19115
19118 using number_unsigned_t = NumberUnsignedType;
19119
19122 using number_float_t = NumberFloatType;
19123
19126 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19127
19130 using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
19131
19133
19134private:
19135
19137 template<typename T, typename... Args>
19138 JSON_HEDLEY_RETURNS_NON_NULL
19139 static T* create(Args&& ... args) {
19140 AllocatorType<T> alloc;
19141 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19142
19143 auto deleter = [&](T* obj) {
19144 AllocatorTraits::deallocate(alloc, obj, 1);
19145 };
19146 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19147 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19148 JSON_ASSERT(obj != nullptr);
19149 return obj.release();
19150 }
19151
19153 // JSON value storage //
19155
19156JSON_PRIVATE_UNLESS_TESTED:
19182 union json_value {
19184 object_t* object;
19186 array_t* array;
19188 string_t* string;
19190 binary_t* binary;
19192 boolean_t boolean;
19194 number_integer_t number_integer;
19196 number_unsigned_t number_unsigned;
19198 number_float_t number_float;
19199
19201 json_value() = default;
19203 json_value(boolean_t v) noexcept : boolean(v) {}
19205 json_value(number_integer_t v) noexcept : number_integer(v) {}
19207 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19209 json_value(number_float_t v) noexcept : number_float(v) {}
19211 json_value(value_t t) {
19212 switch (t) {
19213 case value_t::object:
19214 {
19215 object = create<object_t>();
19216 break;
19217 }
19218
19219 case value_t::array:
19220 {
19221 array = create<array_t>();
19222 break;
19223 }
19224
19225 case value_t::string:
19226 {
19227 string = create<string_t>("");
19228 break;
19229 }
19230
19231 case value_t::binary:
19232 {
19233 binary = create<binary_t>();
19234 break;
19235 }
19236
19237 case value_t::boolean:
19238 {
19239 boolean = static_cast<boolean_t>(false);
19240 break;
19241 }
19242
19243 case value_t::number_integer:
19244 {
19245 number_integer = static_cast<number_integer_t>(0);
19246 break;
19247 }
19248
19249 case value_t::number_unsigned:
19250 {
19251 number_unsigned = static_cast<number_unsigned_t>(0);
19252 break;
19253 }
19254
19255 case value_t::number_float:
19256 {
19257 number_float = static_cast<number_float_t>(0.0);
19258 break;
19259 }
19260
19261 case value_t::null:
19262 {
19263 object = nullptr; // silence warning, see #821
19264 break;
19265 }
19266
19267 case value_t::discarded:
19268 default:
19269 {
19270 object = nullptr; // silence warning, see #821
19271 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) {
19272 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.12.0", nullptr)); // LCOV_EXCL_LINE
19273 }
19274 break;
19275 }
19276 }
19277 }
19278
19280 json_value(const string_t& value) : string(create<string_t>(value)) {}
19281
19283 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
19284
19286 json_value(const object_t& value) : object(create<object_t>(value)) {}
19287
19289 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
19290
19292 json_value(const array_t& value) : array(create<array_t>(value)) {}
19293
19295 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
19296
19298 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
19299
19301 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
19302
19304 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
19305
19307 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
19308
19309 void destroy(value_t t) {
19310 if (
19311 (t == value_t::object && object == nullptr) ||
19312 (t == value_t::array && array == nullptr) ||
19313 (t == value_t::string && string == nullptr) ||
19314 (t == value_t::binary && binary == nullptr)
19315 ) {
19316 // not initialized (e.g., due to exception in the ctor)
19317 return;
19318 }
19319 if (t == value_t::array || t == value_t::object) {
19320 // flatten the current json_value to a heap-allocated stack
19321 std::vector<basic_json> stack;
19322
19323 // move the top-level items to stack
19324 if (t == value_t::array) {
19325 stack.reserve(array->size());
19326 std::move(array->begin(), array->end(), std::back_inserter(stack));
19327 }
19328 else {
19329 stack.reserve(object->size());
19330 for (auto&& it : *object) {
19331 stack.push_back(std::move(it.second));
19332 }
19333 }
19334
19335 while (!stack.empty()) {
19336 // move the last item to a local variable to be processed
19337 basic_json current_item(std::move(stack.back()));
19338 stack.pop_back();
19339
19340 // if current_item is array/object, move
19341 // its children to the stack to be processed later
19342 if (current_item.is_array()) {
19343 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
19344
19345 current_item.m_data.m_value.array->clear();
19346 }
19347 else if (current_item.is_object()) {
19348 for (auto&& it : *current_item.m_data.m_value.object) {
19349 stack.push_back(std::move(it.second));
19350 }
19351
19352 current_item.m_data.m_value.object->clear();
19353 }
19354
19355 // it's now safe that current_item gets destructed
19356 // since it doesn't have any children
19357 }
19358 }
19359
19360 switch (t) {
19361 case value_t::object:
19362 {
19363 AllocatorType<object_t> alloc;
19364 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
19365 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
19366 break;
19367 }
19368
19369 case value_t::array:
19370 {
19371 AllocatorType<array_t> alloc;
19372 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
19373 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
19374 break;
19375 }
19376
19377 case value_t::string:
19378 {
19379 AllocatorType<string_t> alloc;
19380 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
19381 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
19382 break;
19383 }
19384
19385 case value_t::binary:
19386 {
19387 AllocatorType<binary_t> alloc;
19388 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
19389 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
19390 break;
19391 }
19392
19393 case value_t::null:
19394 case value_t::boolean:
19395 case value_t::number_integer:
19396 case value_t::number_unsigned:
19397 case value_t::number_float:
19398 case value_t::discarded:
19399 default:
19400 {
19401 break;
19402 }
19403 }
19404 }
19405 };
19406
19407private:
19426 void assert_invariant(bool check_parents = true) const noexcept {
19427 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
19428 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
19429 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
19430 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
19431
19432#if JSON_DIAGNOSTICS
19433 JSON_TRY
19434 {
19435 // cppcheck-suppress assertWithSideEffect
19436 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json& j) {
19437 return j.m_parent == this;
19438 }));
19439 }
19440 JSON_CATCH(...) {} // LCOV_EXCL_LINE
19441#endif
19442 static_cast<void>(check_parents);
19443 }
19444
19445 void set_parents() {
19446#if JSON_DIAGNOSTICS
19447 switch (m_data.m_type) {
19448 case value_t::array:
19449 {
19450 for (auto& element : *m_data.m_value.array) {
19451 element.m_parent = this;
19452 }
19453 break;
19454 }
19455
19456 case value_t::object:
19457 {
19458 for (auto& element : *m_data.m_value.object) {
19459 element.second.m_parent = this;
19460 }
19461 break;
19462 }
19463
19464 case value_t::null:
19465 case value_t::string:
19466 case value_t::boolean:
19467 case value_t::number_integer:
19468 case value_t::number_unsigned:
19469 case value_t::number_float:
19470 case value_t::binary:
19471 case value_t::discarded:
19472 default:
19473 break;
19474 }
19475#endif
19476 }
19477
19478 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents) {
19479#if JSON_DIAGNOSTICS
19480 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i) {
19481 (it + i)->m_parent = this;
19482 }
19483#else
19484 static_cast<void>(count_set_parents);
19485#endif
19486 return it;
19487 }
19488
19489 reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size()) {
19490#if JSON_DIAGNOSTICS
19491 if (old_capacity != detail::unknown_size()) {
19492 // see https://github.com/nlohmann/json/issues/2838
19493 JSON_ASSERT(type() == value_t::array);
19494 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) {
19495 // capacity has changed: update all parents
19496 set_parents();
19497 return j;
19498 }
19499 }
19500
19501 // ordered_json uses a vector internally, so pointers could have
19502 // been invalidated; see https://github.com/nlohmann/json/issues/2962
19503#ifdef JSON_HEDLEY_MSVC_VERSION
19504#pragma warning(push )
19505#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
19506#endif
19507 if (detail::is_ordered_map<object_t>::value) {
19508 set_parents();
19509 return j;
19510 }
19511#ifdef JSON_HEDLEY_MSVC_VERSION
19512#pragma warning( pop )
19513#endif
19514
19515 j.m_parent = this;
19516#else
19517 static_cast<void>(j);
19518 static_cast<void>(old_capacity);
19519#endif
19520 return j;
19521 }
19522
19523public:
19525 // JSON parser callback //
19527
19530 using parse_event_t = detail::parse_event_t;
19531
19534 using parser_callback_t = detail::parser_callback_t<basic_json>;
19535
19537 // constructors //
19539
19544
19547 basic_json(const value_t v)
19548 : m_data(v) {
19549 assert_invariant();
19550 }
19551
19554 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
19555 : basic_json(value_t::null) {
19556 assert_invariant();
19557 }
19558
19561 template < typename CompatibleType,
19562 typename U = detail::uncvref_t<CompatibleType>,
19563 detail::enable_if_t <
19565 basic_json(CompatibleType&& val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
19566 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
19567 std::forward<CompatibleType>(val)))) {
19568 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
19569 set_parents();
19570 assert_invariant();
19571 }
19572
19575 template < typename BasicJsonType,
19576 detail::enable_if_t <
19577 detail::is_basic_json<BasicJsonType>::value && !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
19578 basic_json(const BasicJsonType& val)
19579#if JSON_DIAGNOSTIC_POSITIONS
19580 : start_position(val.start_pos()),
19581 end_position(val.end_pos())
19582#endif
19583 {
19584 using other_boolean_t = typename BasicJsonType::boolean_t;
19585 using other_number_float_t = typename BasicJsonType::number_float_t;
19586 using other_number_integer_t = typename BasicJsonType::number_integer_t;
19587 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
19588 using other_string_t = typename BasicJsonType::string_t;
19589 using other_object_t = typename BasicJsonType::object_t;
19590 using other_array_t = typename BasicJsonType::array_t;
19591 using other_binary_t = typename BasicJsonType::binary_t;
19592
19593 switch (val.type()) {
19594 case value_t::boolean:
19595 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
19596 break;
19597 case value_t::number_float:
19598 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
19599 break;
19600 case value_t::number_integer:
19601 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
19602 break;
19603 case value_t::number_unsigned:
19604 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
19605 break;
19606 case value_t::string:
19607 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
19608 break;
19609 case value_t::object:
19610 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
19611 break;
19612 case value_t::array:
19613 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
19614 break;
19615 case value_t::binary:
19616 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
19617 break;
19618 case value_t::null:
19619 *this = nullptr;
19620 break;
19621 case value_t::discarded:
19622 m_data.m_type = value_t::discarded;
19623 break;
19624 default: // LCOV_EXCL_LINE
19625 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19626 }
19627 JSON_ASSERT(m_data.m_type == val.type());
19628
19629 set_parents();
19630 assert_invariant();
19631 }
19632
19635 basic_json(initializer_list_t init,
19636 bool type_deduction = true,
19637 value_t manual_type = value_t::array) {
19638 // check if each element is an array with two elements whose first
19639 // element is a string
19640 bool is_an_object = std::all_of(init.begin(), init.end(),
19641 [](const detail::json_ref<basic_json>& element_ref) {
19642 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
19643 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
19644 // broken call to op[key_type], the wrong semantics, and a 4804 warning on Windows)
19645 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
19646 });
19647
19648 // adjust type if type deduction is not wanted
19649 if (!type_deduction) {
19650 // if an array is wanted, do not create an object though possible
19651 if (manual_type == value_t::array) {
19652 is_an_object = false;
19653 }
19654
19655 // if an object is wanted but impossible, throw an exception
19656 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) {
19657 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
19658 }
19659 }
19660
19661 if (is_an_object) {
19662 // the initializer list is a list of pairs -> create an object
19663 m_data.m_type = value_t::object;
19664 m_data.m_value = value_t::object;
19665
19666 for (auto& element_ref : init) {
19667 auto element = element_ref.moved_or_copied();
19668 m_data.m_value.object->emplace(
19669 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
19670 std::move((*element.m_data.m_value.array)[1]));
19671 }
19672 }
19673 else {
19674 // the initializer list describes an array -> create an array
19675 m_data.m_type = value_t::array;
19676 m_data.m_value.array = create<array_t>(init.begin(), init.end());
19677 }
19678
19679 set_parents();
19680 assert_invariant();
19681 }
19682
19685 JSON_HEDLEY_WARN_UNUSED_RESULT
19686 static basic_json binary(const typename binary_t::container_type& init) {
19687 auto res = basic_json();
19688 res.m_data.m_type = value_t::binary;
19689 res.m_data.m_value = init;
19690 return res;
19691 }
19692
19695 JSON_HEDLEY_WARN_UNUSED_RESULT
19696 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype) {
19697 auto res = basic_json();
19698 res.m_data.m_type = value_t::binary;
19699 res.m_data.m_value = binary_t(init, subtype);
19700 return res;
19701 }
19702
19705 JSON_HEDLEY_WARN_UNUSED_RESULT
19706 static basic_json binary(typename binary_t::container_type&& init) {
19707 auto res = basic_json();
19708 res.m_data.m_type = value_t::binary;
19709 res.m_data.m_value = std::move(init);
19710 return res;
19711 }
19712
19715 JSON_HEDLEY_WARN_UNUSED_RESULT
19716 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype) {
19717 auto res = basic_json();
19718 res.m_data.m_type = value_t::binary;
19719 res.m_data.m_value = binary_t(std::move(init), subtype);
19720 return res;
19721 }
19722
19725 JSON_HEDLEY_WARN_UNUSED_RESULT
19726 static basic_json array(initializer_list_t init = {}) {
19727 return basic_json(init, false, value_t::array);
19728 }
19729
19732 JSON_HEDLEY_WARN_UNUSED_RESULT
19733 static basic_json object(initializer_list_t init = {}) {
19734 return basic_json(init, false, value_t::object);
19735 }
19736
19739 basic_json(size_type cnt, const basic_json& val) :
19740 m_data{ cnt, val } {
19741 set_parents();
19742 assert_invariant();
19743 }
19744
19747 template < class InputIT, typename std::enable_if <
19748 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
19749 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
19750 basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
19751 {
19752 JSON_ASSERT(first.m_object != nullptr);
19753 JSON_ASSERT(last.m_object != nullptr);
19754
19755 // make sure the iterator fits the current value
19756 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
19757 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
19758 }
19759
19760 // copy type from the first iterator
19761 m_data.m_type = first.m_object->m_data.m_type;
19762
19763 // check if the iterator range is complete for primitive values
19764 switch (m_data.m_type) {
19765 case value_t::boolean:
19766 case value_t::number_float:
19767 case value_t::number_integer:
19768 case value_t::number_unsigned:
19769 case value_t::string:
19770 {
19771 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
19772 || !last.m_it.primitive_iterator.is_end())) {
19773 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
19774 }
19775 break;
19776 }
19777
19778 case value_t::null:
19779 case value_t::object:
19780 case value_t::array:
19781 case value_t::binary:
19782 case value_t::discarded:
19783 default:
19784 break;
19785 }
19786
19787 switch (m_data.m_type) {
19788 case value_t::number_integer:
19789 {
19790 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
19791 break;
19792 }
19793
19794 case value_t::number_unsigned:
19795 {
19796 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
19797 break;
19798 }
19799
19800 case value_t::number_float:
19801 {
19802 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
19803 break;
19804 }
19805
19806 case value_t::boolean:
19807 {
19808 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
19809 break;
19810 }
19811
19812 case value_t::string:
19813 {
19814 m_data.m_value = *first.m_object->m_data.m_value.string;
19815 break;
19816 }
19817
19818 case value_t::object:
19819 {
19820 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
19821 last.m_it.object_iterator);
19822 break;
19823 }
19824
19825 case value_t::array:
19826 {
19827 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
19828 last.m_it.array_iterator);
19829 break;
19830 }
19831
19832 case value_t::binary:
19833 {
19834 m_data.m_value = *first.m_object->m_data.m_value.binary;
19835 break;
19836 }
19837
19838 case value_t::null:
19839 case value_t::discarded:
19840 default:
19841 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
19842 }
19843
19844 set_parents();
19845 assert_invariant();
19846 }
19847
19849 // other constructors and destructor //
19851
19852 template<typename JsonRef,
19853 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
19854 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
19855 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
19856
19859 basic_json(const basic_json& other)
19860 : json_base_class_t(other)
19861#if JSON_DIAGNOSTIC_POSITIONS
19862 , start_position(other.start_position)
19863 , end_position(other.end_position)
19864#endif
19865 {
19866 m_data.m_type = other.m_data.m_type;
19867 // check of passed value is valid
19868 other.assert_invariant();
19869
19870 switch (m_data.m_type) {
19871 case value_t::object:
19872 {
19873 m_data.m_value = *other.m_data.m_value.object;
19874 break;
19875 }
19876
19877 case value_t::array:
19878 {
19879 m_data.m_value = *other.m_data.m_value.array;
19880 break;
19881 }
19882
19883 case value_t::string:
19884 {
19885 m_data.m_value = *other.m_data.m_value.string;
19886 break;
19887 }
19888
19889 case value_t::boolean:
19890 {
19891 m_data.m_value = other.m_data.m_value.boolean;
19892 break;
19893 }
19894
19895 case value_t::number_integer:
19896 {
19897 m_data.m_value = other.m_data.m_value.number_integer;
19898 break;
19899 }
19900
19901 case value_t::number_unsigned:
19902 {
19903 m_data.m_value = other.m_data.m_value.number_unsigned;
19904 break;
19905 }
19906
19907 case value_t::number_float:
19908 {
19909 m_data.m_value = other.m_data.m_value.number_float;
19910 break;
19911 }
19912
19913 case value_t::binary:
19914 {
19915 m_data.m_value = *other.m_data.m_value.binary;
19916 break;
19917 }
19918
19919 case value_t::null:
19920 case value_t::discarded:
19921 default:
19922 break;
19923 }
19924
19925 set_parents();
19926 assert_invariant();
19927 }
19928
19931 basic_json(basic_json&& other) noexcept
19932 : json_base_class_t(std::forward<json_base_class_t>(other)),
19933 m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
19934#if JSON_DIAGNOSTIC_POSITIONS
19935 , start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
19936 , end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
19937#endif
19938 {
19939 // check that the passed value is valid
19940 other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
19941
19942 // invalidate payload
19943 other.m_data.m_type = value_t::null;
19944 other.m_data.m_value = {};
19945
19946#if JSON_DIAGNOSTIC_POSITIONS
19947 other.start_position = std::string::npos;
19948 other.end_position = std::string::npos;
19949#endif
19950
19951 set_parents();
19952 assert_invariant();
19953 }
19954
19957 basic_json& operator=(basic_json other) noexcept ( // NOLINT(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator)
19958 std::is_nothrow_move_constructible<value_t>::value&&
19959 std::is_nothrow_move_assignable<value_t>::value&&
19960 std::is_nothrow_move_constructible<json_value>::value&&
19961 std::is_nothrow_move_assignable<json_value>::value&&
19962 std::is_nothrow_move_assignable<json_base_class_t>::value
19963 ) {
19964 // check that the passed value is valid
19965 other.assert_invariant();
19966
19967 using std::swap;
19968 swap(m_data.m_type, other.m_data.m_type);
19969 swap(m_data.m_value, other.m_data.m_value);
19970
19971#if JSON_DIAGNOSTIC_POSITIONS
19972 swap(start_position, other.start_position);
19973 swap(end_position, other.end_position);
19974#endif
19975
19976 json_base_class_t::operator=(std::move(other));
19977
19978 set_parents();
19979 assert_invariant();
19980 return *this;
19981 }
19982
19985 ~basic_json() noexcept {
19986 assert_invariant(false);
19987 }
19988
19990
19991public:
19993 // object inspection //
19995
19999
20002 string_t dump(const int indent = -1,
20003 const char indent_char = ' ',
20004 const bool ensure_ascii = false,
20005 const error_handler_t error_handler = error_handler_t::strict) const {
20006 string_t result;
20007 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
20008
20009 if (indent >= 0) {
20010 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
20011 }
20012 else {
20013 s.dump(*this, false, ensure_ascii, 0);
20014 }
20015
20016 return result;
20017 }
20018
20021 constexpr value_t type() const noexcept {
20022 return m_data.m_type;
20023 }
20024
20027 constexpr bool is_primitive() const noexcept {
20028 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20029 }
20030
20033 constexpr bool is_structured() const noexcept {
20034 return is_array() || is_object();
20035 }
20036
20039 constexpr bool is_null() const noexcept {
20040 return m_data.m_type == value_t::null;
20041 }
20042
20045 constexpr bool is_boolean() const noexcept {
20046 return m_data.m_type == value_t::boolean;
20047 }
20048
20051 constexpr bool is_number() const noexcept {
20052 return is_number_integer() || is_number_float();
20053 }
20054
20057 constexpr bool is_number_integer() const noexcept {
20058 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
20059 }
20060
20063 constexpr bool is_number_unsigned() const noexcept {
20064 return m_data.m_type == value_t::number_unsigned;
20065 }
20066
20069 constexpr bool is_number_float() const noexcept {
20070 return m_data.m_type == value_t::number_float;
20071 }
20072
20075 constexpr bool is_object() const noexcept {
20076 return m_data.m_type == value_t::object;
20077 }
20078
20081 constexpr bool is_array() const noexcept {
20082 return m_data.m_type == value_t::array;
20083 }
20084
20087 constexpr bool is_string() const noexcept {
20088 return m_data.m_type == value_t::string;
20089 }
20090
20093 constexpr bool is_binary() const noexcept {
20094 return m_data.m_type == value_t::binary;
20095 }
20096
20099 constexpr bool is_discarded() const noexcept {
20100 return m_data.m_type == value_t::discarded;
20101 }
20102
20105 constexpr operator value_t() const noexcept {
20106 return m_data.m_type;
20107 }
20108
20110
20111private:
20113 // value access //
20115
20117 boolean_t get_impl(boolean_t* /*unused*/) const {
20118 if (JSON_HEDLEY_LIKELY(is_boolean())) {
20119 return m_data.m_value.boolean;
20120 }
20121
20122 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
20123 }
20124
20126 object_t* get_impl_ptr(object_t* /*unused*/) noexcept {
20127 return is_object() ? m_data.m_value.object : nullptr;
20128 }
20129
20131 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept {
20132 return is_object() ? m_data.m_value.object : nullptr;
20133 }
20134
20136 array_t* get_impl_ptr(array_t* /*unused*/) noexcept {
20137 return is_array() ? m_data.m_value.array : nullptr;
20138 }
20139
20141 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept {
20142 return is_array() ? m_data.m_value.array : nullptr;
20143 }
20144
20146 string_t* get_impl_ptr(string_t* /*unused*/) noexcept {
20147 return is_string() ? m_data.m_value.string : nullptr;
20148 }
20149
20151 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept {
20152 return is_string() ? m_data.m_value.string : nullptr;
20153 }
20154
20156 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept {
20157 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20158 }
20159
20161 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept {
20162 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20163 }
20164
20166 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept {
20167 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
20168 }
20169
20171 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept {
20172 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
20173 }
20174
20176 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept {
20177 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20178 }
20179
20181 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept {
20182 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20183 }
20184
20186 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept {
20187 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20188 }
20189
20191 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept {
20192 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20193 }
20194
20196 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept {
20197 return is_binary() ? m_data.m_value.binary : nullptr;
20198 }
20199
20201 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept {
20202 return is_binary() ? m_data.m_value.binary : nullptr;
20203 }
20204
20216 template<typename ReferenceType, typename ThisType>
20217 static ReferenceType get_ref_impl(ThisType& obj) {
20218 // delegate the call to get_ptr<>()
20219 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
20220
20221 if (JSON_HEDLEY_LIKELY(ptr != nullptr)) {
20222 return *ptr;
20223 }
20224
20225 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
20226 }
20227
20228public:
20232
20235 template<typename PointerType, typename std::enable_if<
20236 std::is_pointer<PointerType>::value, int>::type = 0>
20237 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) {
20238 // delegate the call to get_impl_ptr<>()
20239 return get_impl_ptr(static_cast<PointerType>(nullptr));
20240 }
20241
20244 template < typename PointerType, typename std::enable_if <
20245 std::is_pointer<PointerType>::value&&
20246 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
20247 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) {
20248 // delegate the call to get_impl_ptr<>() const
20249 return get_impl_ptr(static_cast<PointerType>(nullptr));
20250 }
20251
20252private:
20291 template < typename ValueType,
20292 detail::enable_if_t <
20295 int > = 0 >
20296 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
20297 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>()))) {
20298 auto ret = ValueType();
20299 JSONSerializer<ValueType>::from_json(*this, ret);
20300 return ret;
20301 }
20302
20333 template < typename ValueType,
20334 detail::enable_if_t <
20336 int > = 0 >
20337 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
20338 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>()))) {
20339 return JSONSerializer<ValueType>::from_json(*this);
20340 }
20341
20357 template < typename BasicJsonType,
20358 detail::enable_if_t <
20360 int > = 0 >
20361 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const {
20362 return *this;
20363 }
20364
20379 template<typename BasicJsonType,
20380 detail::enable_if_t<
20381 std::is_same<BasicJsonType, basic_json_t>::value,
20382 int> = 0>
20383 basic_json get_impl(detail::priority_tag<3> /*unused*/) const {
20384 return *this;
20385 }
20386
20391 template<typename PointerType,
20392 detail::enable_if_t<
20393 std::is_pointer<PointerType>::value,
20394 int> = 0>
20395 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
20396 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>()) {
20397 // delegate the call to get_ptr
20398 return get_ptr<PointerType>();
20399 }
20400
20401public:
20425 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
20426#if defined(JSON_HAS_CPP_14)
20427 constexpr
20428#endif
20429 auto get() const noexcept(
20430 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
20431 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})) {
20432 // we cannot static_assert on ValueTypeCV being non-const, because
20433 // there is support for get<const basic_json_t>(), which is why we
20434 // still need the uncvref
20435 static_assert(!std::is_reference<ValueTypeCV>::value,
20436 "get() cannot be used with reference types, you might want to use get_ref()");
20437 return get_impl<ValueType>(detail::priority_tag<4> {});
20438 }
20439
20467 template<typename PointerType, typename std::enable_if<
20468 std::is_pointer<PointerType>::value, int>::type = 0>
20469 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>()) {
20470 // delegate the call to get_ptr
20471 return get_ptr<PointerType>();
20472 }
20473
20476 template < typename ValueType,
20477 detail::enable_if_t <
20480 int > = 0 >
20481 ValueType& get_to(ValueType& v) const noexcept(noexcept(
20482 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v))) {
20483 JSONSerializer<ValueType>::from_json(*this, v);
20484 return v;
20485 }
20486
20487 // specialization to allow calling get_to with a basic_json value
20488 // see https://github.com/nlohmann/json/issues/2175
20489 template<typename ValueType,
20490 detail::enable_if_t <
20492 int> = 0>
20493 ValueType& get_to(ValueType& v) const {
20494 v = *this;
20495 return v;
20496 }
20497
20498 template <
20499 typename T, std::size_t N,
20500 typename Array = T(&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
20501 detail::enable_if_t <
20503 Array get_to(T(&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
20504 noexcept(noexcept(JSONSerializer<Array>::from_json(
20505 std::declval<const basic_json_t&>(), v))) {
20506 JSONSerializer<Array>::from_json(*this, v);
20507 return v;
20508 }
20509
20512 template<typename ReferenceType, typename std::enable_if<
20513 std::is_reference<ReferenceType>::value, int>::type = 0>
20514 ReferenceType get_ref() {
20515 // delegate call to get_ref_impl
20516 return get_ref_impl<ReferenceType>(*this);
20517 }
20518
20521 template < typename ReferenceType, typename std::enable_if <
20522 std::is_reference<ReferenceType>::value&&
20523 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
20524 ReferenceType get_ref() const {
20525 // delegate call to get_ref_impl
20526 return get_ref_impl<ReferenceType>(*this);
20527 }
20528
20558 template < typename ValueType, typename std::enable_if <
20566#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
20568#endif
20569#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
20571#endif
20573 >::value, int >::type = 0 >
20574 JSON_EXPLICIT operator ValueType() const {
20575 // delegate the call to get<>() const
20576 return get<ValueType>();
20577 }
20578
20581 binary_t& get_binary() {
20582 if (!is_binary()) {
20583 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
20584 }
20585
20586 return *get_ptr<binary_t*>();
20587 }
20588
20591 const binary_t& get_binary() const {
20592 if (!is_binary()) {
20593 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
20594 }
20595
20596 return *get_ptr<const binary_t*>();
20597 }
20598
20600
20602 // element access //
20604
20608
20611 reference at(size_type idx) {
20612 // at only works for arrays
20613 if (JSON_HEDLEY_LIKELY(is_array())) {
20614 JSON_TRY
20615 {
20616 return set_parent(m_data.m_value.array->at(idx));
20617 }
20618 JSON_CATCH(std::out_of_range&) {
20619 // create a better exception explanation
20620 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
20621 } // cppcheck-suppress[missingReturn]
20622 }
20623 else {
20624 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20625 }
20626 }
20627
20630 const_reference at(size_type idx) const {
20631 // at only works for arrays
20632 if (JSON_HEDLEY_LIKELY(is_array())) {
20633 JSON_TRY
20634 {
20635 return m_data.m_value.array->at(idx);
20636 }
20637 JSON_CATCH(std::out_of_range&) {
20638 // create a better exception explanation
20639 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
20640 } // cppcheck-suppress[missingReturn]
20641 }
20642 else {
20643 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20644 }
20645 }
20646
20649 reference at(const typename object_t::key_type& key) {
20650 // at only works for objects
20651 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
20652 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20653 }
20654
20655 auto it = m_data.m_value.object->find(key);
20656 if (it == m_data.m_value.object->end()) {
20657 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
20658 }
20659 return set_parent(it->second);
20660 }
20661
20664 template<class KeyType, detail::enable_if_t<
20665 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
20666 reference at(KeyType&& key) {
20667 // at only works for objects
20668 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
20669 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20670 }
20671
20672 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
20673 if (it == m_data.m_value.object->end()) {
20674 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
20675 }
20676 return set_parent(it->second);
20677 }
20678
20681 const_reference at(const typename object_t::key_type& key) const {
20682 // at only works for objects
20683 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
20684 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20685 }
20686
20687 auto it = m_data.m_value.object->find(key);
20688 if (it == m_data.m_value.object->end()) {
20689 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
20690 }
20691 return it->second;
20692 }
20693
20696 template<class KeyType, detail::enable_if_t<
20697 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
20698 const_reference at(KeyType&& key) const {
20699 // at only works for objects
20700 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
20701 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
20702 }
20703
20704 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
20705 if (it == m_data.m_value.object->end()) {
20706 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
20707 }
20708 return it->second;
20709 }
20710
20713 reference operator[](size_type idx) {
20714 // implicitly convert a null value to an empty array
20715 if (is_null()) {
20716 m_data.m_type = value_t::array;
20717 m_data.m_value.array = create<array_t>();
20718 assert_invariant();
20719 }
20720
20721 // operator[] only works for arrays
20722 if (JSON_HEDLEY_LIKELY(is_array())) {
20723 // fill up the array with null values if given idx is outside the range
20724 if (idx >= m_data.m_value.array->size()) {
20725#if JSON_DIAGNOSTICS
20726 // remember array size & capacity before resizing
20727 const auto old_size = m_data.m_value.array->size();
20728 const auto old_capacity = m_data.m_value.array->capacity();
20729#endif
20730 m_data.m_value.array->resize(idx + 1);
20731
20732#if JSON_DIAGNOSTICS
20733 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) {
20734 // capacity has changed: update all parents
20735 set_parents();
20736 }
20737 else {
20738 // set parent for values added above
20739 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
20740 }
20741#endif
20742 assert_invariant();
20743 }
20744
20745 return m_data.m_value.array->operator[](idx);
20746 }
20747
20748 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
20749 }
20750
20753 const_reference operator[](size_type idx) const {
20754 // const operator[] only works for arrays
20755 if (JSON_HEDLEY_LIKELY(is_array())) {
20756 return m_data.m_value.array->operator[](idx);
20757 }
20758
20759 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
20760 }
20761
20764 reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
20765 {
20766 // implicitly convert a null value to an empty object
20767 if (is_null()) {
20768 m_data.m_type = value_t::object;
20769 m_data.m_value.object = create<object_t>();
20770 assert_invariant();
20771 }
20772
20773 // operator[] only works for objects
20774 if (JSON_HEDLEY_LIKELY(is_object())) {
20775 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
20776 return set_parent(result.first->second);
20777 }
20778
20779 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
20780 }
20781
20784 const_reference operator[](const typename object_t::key_type& key) const {
20785 // const operator[] only works for objects
20786 if (JSON_HEDLEY_LIKELY(is_object())) {
20787 auto it = m_data.m_value.object->find(key);
20788 JSON_ASSERT(it != m_data.m_value.object->end());
20789 return it->second;
20790 }
20791
20792 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
20793 }
20794
20795 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
20796 // (they seemingly cannot be constrained to resolve the ambiguity)
20797 template<typename T>
20798 reference operator[](T* key) {
20799 return operator[](typename object_t::key_type(key));
20800 }
20801
20802 template<typename T>
20803 const_reference operator[](T* key) const {
20804 return operator[](typename object_t::key_type(key));
20805 }
20806
20809 template<class KeyType, detail::enable_if_t<
20810 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
20811 reference operator[](KeyType&& key) {
20812 // implicitly convert a null value to an empty object
20813 if (is_null()) {
20814 m_data.m_type = value_t::object;
20815 m_data.m_value.object = create<object_t>();
20816 assert_invariant();
20817 }
20818
20819 // operator[] only works for objects
20820 if (JSON_HEDLEY_LIKELY(is_object())) {
20821 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
20822 return set_parent(result.first->second);
20823 }
20824
20825 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
20826 }
20827
20830 template<class KeyType, detail::enable_if_t<
20831 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
20832 const_reference operator[](KeyType&& key) const {
20833 // const operator[] only works for objects
20834 if (JSON_HEDLEY_LIKELY(is_object())) {
20835 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
20836 JSON_ASSERT(it != m_data.m_value.object->end());
20837 return it->second;
20838 }
20839
20840 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
20841 }
20842
20843private:
20844 template<typename KeyType>
20845 using is_comparable_with_object_key = detail::is_comparable <
20846 object_comparator_t, const typename object_t::key_type&, KeyType >;
20847
20848 template<typename ValueType>
20849 using value_return_type = std::conditional <
20850 detail::is_c_string_uncvref<ValueType>::value,
20851 string_t, typename std::decay<ValueType>::type >;
20852
20853public:
20856 template < class ValueType, detail::enable_if_t <
20858 && detail::is_getable<basic_json_t, ValueType>::value
20859 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
20860 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const {
20861 // value only works for objects
20862 if (JSON_HEDLEY_LIKELY(is_object())) {
20863 // If 'key' is found, return its value. Otherwise, return `default_value'.
20864 const auto it = find(key);
20865 if (it != end()) {
20866 return it->template get<ValueType>();
20867 }
20868
20869 return default_value;
20870 }
20871
20872 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20873 }
20874
20877 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
20878 detail::enable_if_t <
20880 && detail::is_getable<basic_json_t, ReturnType>::value
20881 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
20882 ReturnType value(const typename object_t::key_type& key, ValueType&& default_value) const {
20883 // value only works for objects
20884 if (JSON_HEDLEY_LIKELY(is_object())) {
20885 // If 'key' is found, return its value. Otherwise, return `default_value'.
20886 const auto it = find(key);
20887 if (it != end()) {
20888 return it->template get<ReturnType>();
20889 }
20890
20891 return std::forward<ValueType>(default_value);
20892 }
20893
20894 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20895 }
20896
20899 template < class ValueType, class KeyType, detail::enable_if_t <
20901 && !detail::is_json_pointer<KeyType>::value
20902 && is_comparable_with_object_key<KeyType>::value
20903 && detail::is_getable<basic_json_t, ValueType>::value
20904 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
20905 ValueType value(KeyType&& key, const ValueType& default_value) const {
20906 // value only works for objects
20907 if (JSON_HEDLEY_LIKELY(is_object())) {
20908 // If 'key' is found, return its value. Otherwise, return `default_value'.
20909 const auto it = find(std::forward<KeyType>(key));
20910 if (it != end()) {
20911 return it->template get<ValueType>();
20912 }
20913
20914 return default_value;
20915 }
20916
20917 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20918 }
20919
20922 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
20923 detail::enable_if_t <
20925 && !detail::is_json_pointer<KeyType>::value
20926 && is_comparable_with_object_key<KeyType>::value
20927 && detail::is_getable<basic_json_t, ReturnType>::value
20928 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
20929 ReturnType value(KeyType&& key, ValueType&& default_value) const {
20930 // value only works for objects
20931 if (JSON_HEDLEY_LIKELY(is_object())) {
20932 // If 'key' is found, return its value. Otherwise, return `default_value'.
20933 const auto it = find(std::forward<KeyType>(key));
20934 if (it != end()) {
20935 return it->template get<ReturnType>();
20936 }
20937
20938 return std::forward<ValueType>(default_value);
20939 }
20940
20941 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20942 }
20943
20946 template < class ValueType, detail::enable_if_t <
20947 detail::is_getable<basic_json_t, ValueType>::value
20948 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
20949 ValueType value(const json_pointer& ptr, const ValueType& default_value) const {
20950 // value only works for objects
20951 if (JSON_HEDLEY_LIKELY(is_object())) {
20952 // If the pointer resolves to a value, return it. Otherwise, return
20953 // 'default_value'.
20954 JSON_TRY
20955 {
20956 return ptr.get_checked(this).template get<ValueType>();
20957 }
20958 JSON_INTERNAL_CATCH(out_of_range&) {
20959 return default_value;
20960 }
20961 }
20962
20963 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20964 }
20965
20968 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
20969 detail::enable_if_t <
20970 detail::is_getable<basic_json_t, ReturnType>::value
20971 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
20972 ReturnType value(const json_pointer& ptr, ValueType&& default_value) const {
20973 // value only works for objects
20974 if (JSON_HEDLEY_LIKELY(is_object())) {
20975 // If the pointer resolves to a value, return it. Otherwise, return
20976 // 'default_value'.
20977 JSON_TRY
20978 {
20979 return ptr.get_checked(this).template get<ReturnType>();
20980 }
20981 JSON_INTERNAL_CATCH(out_of_range&) {
20982 return std::forward<ValueType>(default_value);
20983 }
20984 }
20985
20986 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20987 }
20988
20989 template < class ValueType, class BasicJsonType, detail::enable_if_t <
20991 && detail::is_getable<basic_json_t, ValueType>::value
20992 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
20993 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
20994 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const {
20995 return value(ptr.convert(), default_value);
20996 }
20997
20998 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
20999 detail::enable_if_t <
21001 && detail::is_getable<basic_json_t, ReturnType>::value
21002 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21003 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21004 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType&& default_value) const {
21005 return value(ptr.convert(), std::forward<ValueType>(default_value));
21006 }
21007
21010 reference front() {
21011 return *begin();
21012 }
21013
21016 const_reference front() const {
21017 return *cbegin();
21018 }
21019
21022 reference back() {
21023 auto tmp = end();
21024 --tmp;
21025 return *tmp;
21026 }
21027
21030 const_reference back() const {
21031 auto tmp = cend();
21032 --tmp;
21033 return *tmp;
21034 }
21035
21038 template < class IteratorType, detail::enable_if_t <
21039 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21040 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21041 IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
21042 {
21043 // make sure the iterator fits the current value
21044 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) {
21045 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21046 }
21047
21048 IteratorType result = end();
21049
21050 switch (m_data.m_type) {
21051 case value_t::boolean:
21052 case value_t::number_float:
21053 case value_t::number_integer:
21054 case value_t::number_unsigned:
21055 case value_t::string:
21056 case value_t::binary:
21057 {
21058 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) {
21059 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
21060 }
21061
21062 if (is_string()) {
21063 AllocatorType<string_t> alloc;
21064 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21065 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21066 m_data.m_value.string = nullptr;
21067 }
21068 else if (is_binary()) {
21069 AllocatorType<binary_t> alloc;
21070 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21071 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21072 m_data.m_value.binary = nullptr;
21073 }
21074
21075 m_data.m_type = value_t::null;
21076 assert_invariant();
21077 break;
21078 }
21079
21080 case value_t::object:
21081 {
21082 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
21083 break;
21084 }
21085
21086 case value_t::array:
21087 {
21088 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
21089 break;
21090 }
21091
21092 case value_t::null:
21093 case value_t::discarded:
21094 default:
21095 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21096 }
21097
21098 return result;
21099 }
21100
21103 template < class IteratorType, detail::enable_if_t <
21104 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21105 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21106 IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
21107 {
21108 // make sure the iterator fits the current value
21109 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) {
21110 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
21111 }
21112
21113 IteratorType result = end();
21114
21115 switch (m_data.m_type) {
21116 case value_t::boolean:
21117 case value_t::number_float:
21118 case value_t::number_integer:
21119 case value_t::number_unsigned:
21120 case value_t::string:
21121 case value_t::binary:
21122 {
21123 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
21124 || !last.m_it.primitive_iterator.is_end())) {
21125 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
21126 }
21127
21128 if (is_string()) {
21129 AllocatorType<string_t> alloc;
21130 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21131 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21132 m_data.m_value.string = nullptr;
21133 }
21134 else if (is_binary()) {
21135 AllocatorType<binary_t> alloc;
21136 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21137 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21138 m_data.m_value.binary = nullptr;
21139 }
21140
21141 m_data.m_type = value_t::null;
21142 assert_invariant();
21143 break;
21144 }
21145
21146 case value_t::object:
21147 {
21148 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
21149 last.m_it.object_iterator);
21150 break;
21151 }
21152
21153 case value_t::array:
21154 {
21155 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
21156 last.m_it.array_iterator);
21157 break;
21158 }
21159
21160 case value_t::null:
21161 case value_t::discarded:
21162 default:
21163 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21164 }
21165
21166 return result;
21167 }
21168
21169private:
21170 template < typename KeyType, detail::enable_if_t <
21171 detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
21172 size_type erase_internal(KeyType&& key) {
21173 // this erase only works for objects
21174 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
21175 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21176 }
21177
21178 return m_data.m_value.object->erase(std::forward<KeyType>(key));
21179 }
21180
21181 template < typename KeyType, detail::enable_if_t <
21182 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
21183 size_type erase_internal(KeyType&& key) {
21184 // this erase only works for objects
21185 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
21186 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21187 }
21188
21189 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21190 if (it != m_data.m_value.object->end()) {
21191 m_data.m_value.object->erase(it);
21192 return 1;
21193 }
21194 return 0;
21195 }
21196
21197public:
21198
21201 size_type erase(const typename object_t::key_type& key) {
21202 // the indirection via erase_internal() is added to avoid making this
21203 // function a template and thus de-rank it during overload resolution
21204 return erase_internal(key);
21205 }
21206
21209 template<class KeyType, detail::enable_if_t<
21210 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21211 size_type erase(KeyType&& key) {
21212 return erase_internal(std::forward<KeyType>(key));
21213 }
21214
21217 void erase(const size_type idx) {
21218 // this erase only works for arrays
21219 if (JSON_HEDLEY_LIKELY(is_array())) {
21220 if (JSON_HEDLEY_UNLIKELY(idx >= size())) {
21221 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21222 }
21223
21224 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
21225 }
21226 else {
21227 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21228 }
21229 }
21230
21232
21234 // lookup //
21236
21239
21242 iterator find(const typename object_t::key_type& key) {
21243 auto result = end();
21244
21245 if (is_object()) {
21246 result.m_it.object_iterator = m_data.m_value.object->find(key);
21247 }
21248
21249 return result;
21250 }
21251
21254 const_iterator find(const typename object_t::key_type& key) const {
21255 auto result = cend();
21256
21257 if (is_object()) {
21258 result.m_it.object_iterator = m_data.m_value.object->find(key);
21259 }
21260
21261 return result;
21262 }
21263
21266 template<class KeyType, detail::enable_if_t<
21267 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21268 iterator find(KeyType&& key) {
21269 auto result = end();
21270
21271 if (is_object()) {
21272 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
21273 }
21274
21275 return result;
21276 }
21277
21280 template<class KeyType, detail::enable_if_t<
21281 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21282 const_iterator find(KeyType&& key) const {
21283 auto result = cend();
21284
21285 if (is_object()) {
21286 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
21287 }
21288
21289 return result;
21290 }
21291
21294 size_type count(const typename object_t::key_type& key) const {
21295 // return 0 for all nonobject types
21296 return is_object() ? m_data.m_value.object->count(key) : 0;
21297 }
21298
21301 template<class KeyType, detail::enable_if_t<
21302 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21303 size_type count(KeyType&& key) const {
21304 // return 0 for all nonobject types
21305 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
21306 }
21307
21310 bool contains(const typename object_t::key_type& key) const {
21311 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
21312 }
21313
21316 template<class KeyType, detail::enable_if_t<
21317 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21318 bool contains(KeyType&& key) const {
21319 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
21320 }
21321
21324 bool contains(const json_pointer& ptr) const {
21325 return ptr.contains(this);
21326 }
21327
21328 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
21329 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21330 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const {
21331 return ptr.contains(this);
21332 }
21333
21335
21337 // iterators //
21339
21342
21345 iterator begin() noexcept {
21346 iterator result(this);
21347 result.set_begin();
21348 return result;
21349 }
21350
21353 const_iterator begin() const noexcept {
21354 return cbegin();
21355 }
21356
21359 const_iterator cbegin() const noexcept {
21360 const_iterator result(this);
21361 result.set_begin();
21362 return result;
21363 }
21364
21367 iterator end() noexcept {
21368 iterator result(this);
21369 result.set_end();
21370 return result;
21371 }
21372
21375 const_iterator end() const noexcept {
21376 return cend();
21377 }
21378
21381 const_iterator cend() const noexcept {
21382 const_iterator result(this);
21383 result.set_end();
21384 return result;
21385 }
21386
21389 reverse_iterator rbegin() noexcept {
21390 return reverse_iterator(end());
21391 }
21392
21395 const_reverse_iterator rbegin() const noexcept {
21396 return crbegin();
21397 }
21398
21401 reverse_iterator rend() noexcept {
21402 return reverse_iterator(begin());
21403 }
21404
21407 const_reverse_iterator rend() const noexcept {
21408 return crend();
21409 }
21410
21413 const_reverse_iterator crbegin() const noexcept {
21414 return const_reverse_iterator(cend());
21415 }
21416
21419 const_reverse_iterator crend() const noexcept {
21420 return const_reverse_iterator(cbegin());
21421 }
21422
21423public:
21429 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
21430 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept {
21431 return ref.items();
21432 }
21433
21439 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
21440 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept {
21441 return ref.items();
21442 }
21443
21446 iteration_proxy<iterator> items() noexcept {
21447 return iteration_proxy<iterator>(*this);
21448 }
21449
21452 iteration_proxy<const_iterator> items() const noexcept {
21453 return iteration_proxy<const_iterator>(*this);
21454 }
21455
21457
21459 // capacity //
21461
21464
21467 bool empty() const noexcept {
21468 switch (m_data.m_type) {
21469 case value_t::null:
21470 {
21471 // null values are empty
21472 return true;
21473 }
21474
21475 case value_t::array:
21476 {
21477 // delegate call to array_t::empty()
21478 return m_data.m_value.array->empty();
21479 }
21480
21481 case value_t::object:
21482 {
21483 // delegate call to object_t::empty()
21484 return m_data.m_value.object->empty();
21485 }
21486
21487 case value_t::string:
21488 case value_t::boolean:
21489 case value_t::number_integer:
21490 case value_t::number_unsigned:
21491 case value_t::number_float:
21492 case value_t::binary:
21493 case value_t::discarded:
21494 default:
21495 {
21496 // all other types are nonempty
21497 return false;
21498 }
21499 }
21500 }
21501
21504 size_type size() const noexcept {
21505 switch (m_data.m_type) {
21506 case value_t::null:
21507 {
21508 // null values are empty
21509 return 0;
21510 }
21511
21512 case value_t::array:
21513 {
21514 // delegate call to array_t::size()
21515 return m_data.m_value.array->size();
21516 }
21517
21518 case value_t::object:
21519 {
21520 // delegate call to object_t::size()
21521 return m_data.m_value.object->size();
21522 }
21523
21524 case value_t::string:
21525 case value_t::boolean:
21526 case value_t::number_integer:
21527 case value_t::number_unsigned:
21528 case value_t::number_float:
21529 case value_t::binary:
21530 case value_t::discarded:
21531 default:
21532 {
21533 // all other types have size 1
21534 return 1;
21535 }
21536 }
21537 }
21538
21541 size_type max_size() const noexcept {
21542 switch (m_data.m_type) {
21543 case value_t::array:
21544 {
21545 // delegate call to array_t::max_size()
21546 return m_data.m_value.array->max_size();
21547 }
21548
21549 case value_t::object:
21550 {
21551 // delegate call to object_t::max_size()
21552 return m_data.m_value.object->max_size();
21553 }
21554
21555 case value_t::null:
21556 case value_t::string:
21557 case value_t::boolean:
21558 case value_t::number_integer:
21559 case value_t::number_unsigned:
21560 case value_t::number_float:
21561 case value_t::binary:
21562 case value_t::discarded:
21563 default:
21564 {
21565 // all other types have max_size() == size()
21566 return size();
21567 }
21568 }
21569 }
21570
21572
21574 // modifiers //
21576
21579
21582 void clear() noexcept {
21583 switch (m_data.m_type) {
21584 case value_t::number_integer:
21585 {
21586 m_data.m_value.number_integer = 0;
21587 break;
21588 }
21589
21590 case value_t::number_unsigned:
21591 {
21592 m_data.m_value.number_unsigned = 0;
21593 break;
21594 }
21595
21596 case value_t::number_float:
21597 {
21598 m_data.m_value.number_float = 0.0;
21599 break;
21600 }
21601
21602 case value_t::boolean:
21603 {
21604 m_data.m_value.boolean = false;
21605 break;
21606 }
21607
21608 case value_t::string:
21609 {
21610 m_data.m_value.string->clear();
21611 break;
21612 }
21613
21614 case value_t::binary:
21615 {
21616 m_data.m_value.binary->clear();
21617 break;
21618 }
21619
21620 case value_t::array:
21621 {
21622 m_data.m_value.array->clear();
21623 break;
21624 }
21625
21626 case value_t::object:
21627 {
21628 m_data.m_value.object->clear();
21629 break;
21630 }
21631
21632 case value_t::null:
21633 case value_t::discarded:
21634 default:
21635 break;
21636 }
21637 }
21638
21641 void push_back(basic_json&& val) {
21642 // push_back only works for null objects or arrays
21643 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) {
21644 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
21645 }
21646
21647 // transform a null object into an array
21648 if (is_null()) {
21649 m_data.m_type = value_t::array;
21650 m_data.m_value = value_t::array;
21651 assert_invariant();
21652 }
21653
21654 // add the element to the array (move semantics)
21655 const auto old_capacity = m_data.m_value.array->capacity();
21656 m_data.m_value.array->push_back(std::move(val));
21657 set_parent(m_data.m_value.array->back(), old_capacity);
21658 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
21659 }
21660
21663 reference operator+=(basic_json&& val) {
21664 push_back(std::move(val));
21665 return *this;
21666 }
21667
21670 void push_back(const basic_json& val) {
21671 // push_back only works for null objects or arrays
21672 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) {
21673 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
21674 }
21675
21676 // transform a null object into an array
21677 if (is_null()) {
21678 m_data.m_type = value_t::array;
21679 m_data.m_value = value_t::array;
21680 assert_invariant();
21681 }
21682
21683 // add the element to the array
21684 const auto old_capacity = m_data.m_value.array->capacity();
21685 m_data.m_value.array->push_back(val);
21686 set_parent(m_data.m_value.array->back(), old_capacity);
21687 }
21688
21691 reference operator+=(const basic_json& val) {
21692 push_back(val);
21693 return *this;
21694 }
21695
21698 void push_back(const typename object_t::value_type& val) {
21699 // push_back only works for null objects or objects
21700 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) {
21701 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
21702 }
21703
21704 // transform a null object into an object
21705 if (is_null()) {
21706 m_data.m_type = value_t::object;
21707 m_data.m_value = value_t::object;
21708 assert_invariant();
21709 }
21710
21711 // add the element to the object
21712 auto res = m_data.m_value.object->insert(val);
21713 set_parent(res.first->second);
21714 }
21715
21718 reference operator+=(const typename object_t::value_type& val) {
21719 push_back(val);
21720 return *this;
21721 }
21722
21725 void push_back(initializer_list_t init) {
21726 if (is_object() && init.size() == 2 && (*init.begin())->is_string()) {
21727 basic_json&& key = init.begin()->moved_or_copied();
21728 push_back(typename object_t::value_type(
21729 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
21730 }
21731 else {
21732 push_back(basic_json(init));
21733 }
21734 }
21735
21738 reference operator+=(initializer_list_t init) {
21739 push_back(init);
21740 return *this;
21741 }
21742
21745 template<class... Args>
21746 reference emplace_back(Args&& ... args) {
21747 // emplace_back only works for null objects or arrays
21748 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) {
21749 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
21750 }
21751
21752 // transform a null object into an array
21753 if (is_null()) {
21754 m_data.m_type = value_t::array;
21755 m_data.m_value = value_t::array;
21756 assert_invariant();
21757 }
21758
21759 // add the element to the array (perfect forwarding)
21760 const auto old_capacity = m_data.m_value.array->capacity();
21761 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
21762 return set_parent(m_data.m_value.array->back(), old_capacity);
21763 }
21764
21767 template<class... Args>
21768 std::pair<iterator, bool> emplace(Args&& ... args) {
21769 // emplace only works for null objects or arrays
21770 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) {
21771 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
21772 }
21773
21774 // transform a null object into an object
21775 if (is_null()) {
21776 m_data.m_type = value_t::object;
21777 m_data.m_value = value_t::object;
21778 assert_invariant();
21779 }
21780
21781 // add the element to the array (perfect forwarding)
21782 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
21783 set_parent(res.first->second);
21784
21785 // create a result iterator and set iterator to the result of emplace
21786 auto it = begin();
21787 it.m_it.object_iterator = res.first;
21788
21789 // return pair of iterator and boolean
21790 return { it, res.second };
21791 }
21792
21796 template<typename... Args>
21797 iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
21798 {
21799 iterator result(this);
21800 JSON_ASSERT(m_data.m_value.array != nullptr);
21801
21802 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
21803 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
21804 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
21805
21806 // This could have been written as:
21807 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
21808 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
21809
21810 set_parents();
21811 return result;
21812 }
21813
21816 iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
21817 {
21818 // insert only works for arrays
21819 if (JSON_HEDLEY_LIKELY(is_array())) {
21820 // check if iterator pos fits to this JSON value
21821 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) {
21822 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21823 }
21824
21825 // insert to array and return iterator
21826 return insert_iterator(pos, val);
21827 }
21828
21829 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
21830 }
21831
21834 iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
21835 {
21836 return insert(pos, val);
21837 }
21838
21841 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
21842 {
21843 // insert only works for arrays
21844 if (JSON_HEDLEY_LIKELY(is_array())) {
21845 // check if iterator pos fits to this JSON value
21846 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) {
21847 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21848 }
21849
21850 // insert to array and return iterator
21851 return insert_iterator(pos, cnt, val);
21852 }
21853
21854 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
21855 }
21856
21859 iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
21860 {
21861 // insert only works for arrays
21862 if (JSON_HEDLEY_UNLIKELY(!is_array())) {
21863 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
21864 }
21865
21866 // check if iterator pos fits to this JSON value
21867 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) {
21868 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21869 }
21870
21871 // check if range iterators belong to the same JSON object
21872 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
21873 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
21874 }
21875
21876 if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) {
21877 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
21878 }
21879
21880 // insert to array and return iterator
21881 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
21882 }
21883
21886 iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
21887 {
21888 // insert only works for arrays
21889 if (JSON_HEDLEY_UNLIKELY(!is_array())) {
21890 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
21891 }
21892
21893 // check if iterator pos fits to this JSON value
21894 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) {
21895 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21896 }
21897
21898 // insert to array and return iterator
21899 return insert_iterator(pos, ilist.begin(), ilist.end());
21900 }
21901
21904 void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
21905 {
21906 // insert only works for objects
21907 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
21908 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
21909 }
21910
21911 // check if range iterators belong to the same JSON object
21912 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
21913 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
21914 }
21915
21916 // passed iterators must belong to objects
21917 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) {
21918 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
21919 }
21920
21921 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
21922 set_parents();
21923 }
21924
21927 void update(const_reference j, bool merge_objects = false) {
21928 update(j.begin(), j.end(), merge_objects);
21929 }
21930
21933 void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
21934 {
21935 // implicitly convert a null value to an empty object
21936 if (is_null()) {
21937 m_data.m_type = value_t::object;
21938 m_data.m_value.object = create<object_t>();
21939 assert_invariant();
21940 }
21941
21942 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
21943 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
21944 }
21945
21946 // check if range iterators belong to the same JSON object
21947 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
21948 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
21949 }
21950
21951 // passed iterators must belong to objects
21952 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) {
21953 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
21954 }
21955
21956 for (auto it = first; it != last; ++it) {
21957 if (merge_objects && it.value().is_object()) {
21958 auto it2 = m_data.m_value.object->find(it.key());
21959 if (it2 != m_data.m_value.object->end()) {
21960 it2->second.update(it.value(), true);
21961 continue;
21962 }
21963 }
21964 m_data.m_value.object->operator[](it.key()) = it.value();
21965#if JSON_DIAGNOSTICS
21966 m_data.m_value.object->operator[](it.key()).m_parent = this;
21967#endif
21968 }
21969 }
21970
21973 void swap(reference other) noexcept (
21974 std::is_nothrow_move_constructible<value_t>::value&&
21975 std::is_nothrow_move_assignable<value_t>::value&&
21976 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
21977 std::is_nothrow_move_assignable<json_value>::value
21978 ) {
21979 std::swap(m_data.m_type, other.m_data.m_type);
21980 std::swap(m_data.m_value, other.m_data.m_value);
21981
21982 set_parents();
21983 other.set_parents();
21984 assert_invariant();
21985 }
21986
21989 friend void swap(reference left, reference right) noexcept (
21990 std::is_nothrow_move_constructible<value_t>::value&&
21991 std::is_nothrow_move_assignable<value_t>::value&&
21992 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
21993 std::is_nothrow_move_assignable<json_value>::value
21994 ) {
21995 left.swap(right);
21996 }
21997
22000 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22001 {
22002 // swap only works for arrays
22003 if (JSON_HEDLEY_LIKELY(is_array())) {
22004 using std::swap;
22005 swap(*(m_data.m_value.array), other);
22006 }
22007 else {
22008 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
22009 }
22010 }
22011
22014 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22015 {
22016 // swap only works for objects
22017 if (JSON_HEDLEY_LIKELY(is_object())) {
22018 using std::swap;
22019 swap(*(m_data.m_value.object), other);
22020 }
22021 else {
22022 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
22023 }
22024 }
22025
22028 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22029 {
22030 // swap only works for strings
22031 if (JSON_HEDLEY_LIKELY(is_string())) {
22032 using std::swap;
22033 swap(*(m_data.m_value.string), other);
22034 }
22035 else {
22036 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
22037 }
22038 }
22039
22042 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22043 {
22044 // swap only works for strings
22045 if (JSON_HEDLEY_LIKELY(is_binary())) {
22046 using std::swap;
22047 swap(*(m_data.m_value.binary), other);
22048 }
22049 else {
22050 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
22051 }
22052 }
22053
22056 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
22057 {
22058 // swap only works for strings
22059 if (JSON_HEDLEY_LIKELY(is_binary())) {
22060 using std::swap;
22061 swap(*(m_data.m_value.binary), other);
22062 }
22063 else {
22064 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
22065 }
22066 }
22067
22069
22071 // lexicographical comparison operators //
22073
22076
22077 // note parentheses around operands are necessary; see
22078 // https://github.com/nlohmann/json/issues/1530
22079#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
22080 const auto lhs_type = lhs.type(); \
22081 const auto rhs_type = rhs.type(); \
22082 \
22083 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
22084 { \
22085 switch (lhs_type) \
22086 { \
22087 case value_t::array: \
22088 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
22089 \
22090 case value_t::object: \
22091 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
22092 \
22093 case value_t::null: \
22094 return (null_result); \
22095 \
22096 case value_t::string: \
22097 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
22098 \
22099 case value_t::boolean: \
22100 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
22101 \
22102 case value_t::number_integer: \
22103 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
22104 \
22105 case value_t::number_unsigned: \
22106 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
22107 \
22108 case value_t::number_float: \
22109 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
22110 \
22111 case value_t::binary: \
22112 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
22113 \
22114 case value_t::discarded: \
22115 default: \
22116 return (unordered_result); \
22117 } \
22118 } \
22119 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
22120 { \
22121 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
22122 } \
22123 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
22124 { \
22125 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
22126 } \
22127 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
22128 { \
22129 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
22130 } \
22131 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
22132 { \
22133 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
22134 } \
22135 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
22136 { \
22137 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
22138 } \
22139 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
22140 { \
22141 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
22142 } \
22143 else if(compares_unordered(lhs, rhs))\
22144 {\
22145 return (unordered_result);\
22146 }\
22147 \
22148 return (default_result);
22149
22150JSON_PRIVATE_UNLESS_TESTED:
22151 // returns true if:
22152 // - any operand is NaN and the other operand is of number type
22153 // - any operand is discarded
22154 // in legacy mode, discarded values are considered ordered if
22155 // an operation is computed as an odd number of inverses of others
22156 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept {
22157 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
22158 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number())) {
22159 return true;
22160 }
22161#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22162 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
22163#else
22164 static_cast<void>(inverse);
22165 return lhs.is_discarded() || rhs.is_discarded();
22166#endif
22167 }
22168
22169private:
22170 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept {
22171 return compares_unordered(*this, rhs, inverse);
22172 }
22173
22174public:
22175#if JSON_HAS_THREE_WAY_COMPARISON
22178 bool operator==(const_reference rhs) const noexcept {
22179#ifdef __GNUC__
22180#pragma GCC diagnostic push
22181#pragma GCC diagnostic ignored "-Wfloat-equal"
22182#endif
22183 const_reference lhs = *this;
22184 JSON_IMPLEMENT_OPERATOR(== , true, false, false)
22185#ifdef __GNUC__
22186#pragma GCC diagnostic pop
22187#endif
22188 }
22189
22192 template<typename ScalarType>
22193 requires std::is_scalar_v<ScalarType>
22194 bool operator==(ScalarType rhs) const noexcept {
22195 return *this == basic_json(rhs);
22196 }
22197
22200 bool operator!=(const_reference rhs) const noexcept {
22201 if (compares_unordered(rhs, true)) {
22202 return false;
22203 }
22204 return !operator==(rhs);
22205 }
22206
22209 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
22210 {
22211 const_reference lhs = *this;
22212 // default_result is used if we cannot compare values. In that case,
22213 // we compare types.
22214 JSON_IMPLEMENT_OPERATOR(<=> , // *NOPAD*
22215 std::partial_ordering::equivalent,
22216 std::partial_ordering::unordered,
22217 lhs_type <=> rhs_type) // *NOPAD*
22218 }
22219
22222 template<typename ScalarType>
22223 requires std::is_scalar_v<ScalarType>
22224 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
22225 {
22226 return *this <=> basic_json(rhs); // *NOPAD*
22227 }
22228
22229#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22230 // all operators that are computed as an odd number of inverses of others
22231 // need to be overloaded to emulate the legacy comparison behavior
22232
22235 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
22236 bool operator<=(const_reference rhs) const noexcept {
22237 if (compares_unordered(rhs, true)) {
22238 return false;
22239 }
22240 return !(rhs < *this);
22241 }
22242
22245 template<typename ScalarType>
22246 requires std::is_scalar_v<ScalarType>
22247 bool operator<=(ScalarType rhs) const noexcept {
22248 return *this <= basic_json(rhs);
22249 }
22250
22253 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
22254 bool operator>=(const_reference rhs) const noexcept {
22255 if (compares_unordered(rhs, true)) {
22256 return false;
22257 }
22258 return !(*this < rhs);
22259 }
22260
22263 template<typename ScalarType>
22264 requires std::is_scalar_v<ScalarType>
22265 bool operator>=(ScalarType rhs) const noexcept {
22266 return *this >= basic_json(rhs);
22267 }
22268#endif
22269#else
22272 friend bool operator==(const_reference lhs, const_reference rhs) noexcept {
22273#ifdef __GNUC__
22274#pragma GCC diagnostic push
22275#pragma GCC diagnostic ignored "-Wfloat-equal"
22276#endif
22277 JSON_IMPLEMENT_OPERATOR(== , true, false, false)
22278#ifdef __GNUC__
22279#pragma GCC diagnostic pop
22280#endif
22281 }
22282
22285 template<typename ScalarType, typename std::enable_if<
22286 std::is_scalar<ScalarType>::value, int>::type = 0>
22287 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept {
22288 return lhs == basic_json(rhs);
22289 }
22290
22293 template<typename ScalarType, typename std::enable_if<
22294 std::is_scalar<ScalarType>::value, int>::type = 0>
22295 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept {
22296 return basic_json(lhs) == rhs;
22297 }
22298
22301 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept {
22302 if (compares_unordered(lhs, rhs, true)) {
22303 return false;
22304 }
22305 return !(lhs == rhs);
22306 }
22307
22310 template<typename ScalarType, typename std::enable_if<
22311 std::is_scalar<ScalarType>::value, int>::type = 0>
22312 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept {
22313 return lhs != basic_json(rhs);
22314 }
22315
22318 template<typename ScalarType, typename std::enable_if<
22319 std::is_scalar<ScalarType>::value, int>::type = 0>
22320 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept {
22321 return basic_json(lhs) != rhs;
22322 }
22323
22326 friend bool operator<(const_reference lhs, const_reference rhs) noexcept {
22327 // default_result is used if we cannot compare values. In that case,
22328 // we compare types. Note we have to call the operator explicitly,
22329 // because MSVC has problems otherwise.
22330 JSON_IMPLEMENT_OPERATOR(< , false, false, operator<(lhs_type, rhs_type))
22331 }
22332
22335 template<typename ScalarType, typename std::enable_if<
22336 std::is_scalar<ScalarType>::value, int>::type = 0>
22337 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept {
22338 return lhs < basic_json(rhs);
22339 }
22340
22343 template<typename ScalarType, typename std::enable_if<
22344 std::is_scalar<ScalarType>::value, int>::type = 0>
22345 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept {
22346 return basic_json(lhs) < rhs;
22347 }
22348
22351 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept {
22352 if (compares_unordered(lhs, rhs, true)) {
22353 return false;
22354 }
22355 return !(rhs < lhs);
22356 }
22357
22360 template<typename ScalarType, typename std::enable_if<
22361 std::is_scalar<ScalarType>::value, int>::type = 0>
22362 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept {
22363 return lhs <= basic_json(rhs);
22364 }
22365
22368 template<typename ScalarType, typename std::enable_if<
22369 std::is_scalar<ScalarType>::value, int>::type = 0>
22370 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept {
22371 return basic_json(lhs) <= rhs;
22372 }
22373
22376 friend bool operator>(const_reference lhs, const_reference rhs) noexcept {
22377 // double inverse
22378 if (compares_unordered(lhs, rhs)) {
22379 return false;
22380 }
22381 return !(lhs <= rhs);
22382 }
22383
22386 template<typename ScalarType, typename std::enable_if<
22387 std::is_scalar<ScalarType>::value, int>::type = 0>
22388 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept {
22389 return lhs > basic_json(rhs);
22390 }
22391
22394 template<typename ScalarType, typename std::enable_if<
22395 std::is_scalar<ScalarType>::value, int>::type = 0>
22396 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept {
22397 return basic_json(lhs) > rhs;
22398 }
22399
22402 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept {
22403 if (compares_unordered(lhs, rhs, true)) {
22404 return false;
22405 }
22406 return !(lhs < rhs);
22407 }
22408
22411 template<typename ScalarType, typename std::enable_if<
22412 std::is_scalar<ScalarType>::value, int>::type = 0>
22413 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept {
22414 return lhs >= basic_json(rhs);
22415 }
22416
22419 template<typename ScalarType, typename std::enable_if<
22420 std::is_scalar<ScalarType>::value, int>::type = 0>
22421 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept {
22422 return basic_json(lhs) >= rhs;
22423 }
22424#endif
22425
22426#undef JSON_IMPLEMENT_OPERATOR
22427
22429
22431 // serialization //
22433
22436#ifndef JSON_NO_IO
22439 friend std::ostream& operator<<(std::ostream& o, const basic_json& j) {
22440 // read width member and use it as the indentation parameter if nonzero
22441 const bool pretty_print = o.width() > 0;
22442 const auto indentation = pretty_print ? o.width() : 0;
22443
22444 // reset width to 0 for subsequent calls to this stream
22445 o.width(0);
22446
22447 // do the actual serialization
22448 serializer s(detail::output_adapter<char>(o), o.fill());
22449 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
22450 return o;
22451 }
22452
22459 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
22460 friend std::ostream& operator>>(const basic_json& j, std::ostream& o) {
22461 return o << j;
22462 }
22463#endif // JSON_NO_IO
22465
22467 // deserialization //
22469
22472
22475 template<typename InputType>
22476 JSON_HEDLEY_WARN_UNUSED_RESULT
22477 static basic_json parse(InputType&& i,
22478 parser_callback_t cb = nullptr,
22479 const bool allow_exceptions = true,
22480 const bool ignore_comments = false,
22481 const bool ignore_trailing_commas = false) {
22482 basic_json result;
22483 parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved,accessForwarded]
22484 return result;
22485 }
22486
22489 template<typename IteratorType>
22490 JSON_HEDLEY_WARN_UNUSED_RESULT
22491 static basic_json parse(IteratorType first,
22492 IteratorType last,
22493 parser_callback_t cb = nullptr,
22494 const bool allow_exceptions = true,
22495 const bool ignore_comments = false,
22496 const bool ignore_trailing_commas = false) {
22497 basic_json result;
22498 parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
22499 return result;
22500 }
22501
22502 JSON_HEDLEY_WARN_UNUSED_RESULT
22503 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
22504 static basic_json parse(detail::span_input_adapter&& i,
22505 parser_callback_t cb = nullptr,
22506 const bool allow_exceptions = true,
22507 const bool ignore_comments = false,
22508 const bool ignore_trailing_commas = false) {
22509 basic_json result;
22510 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
22511 return result;
22512 }
22513
22516 template<typename InputType>
22517 static bool accept(InputType&& i,
22518 const bool ignore_comments = false,
22519 const bool ignore_trailing_commas = false) {
22520 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
22521 }
22522
22525 template<typename IteratorType>
22526 static bool accept(IteratorType first, IteratorType last,
22527 const bool ignore_comments = false,
22528 const bool ignore_trailing_commas = false) {
22529 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
22530 }
22531
22532 JSON_HEDLEY_WARN_UNUSED_RESULT
22533 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
22534 static bool accept(detail::span_input_adapter&& i,
22535 const bool ignore_comments = false,
22536 const bool ignore_trailing_commas = false) {
22537 return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
22538 }
22539
22542 template <typename InputType, typename SAX>
22543 JSON_HEDLEY_NON_NULL(2)
22544 static bool sax_parse(InputType&& i, SAX* sax,
22545 input_format_t format = input_format_t::json,
22546 const bool strict = true,
22547 const bool ignore_comments = false,
22548 const bool ignore_trailing_commas = false) {
22549#if defined(__clang__)
22550#pragma clang diagnostic push
22551#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
22552#elif defined(__GNUC__)
22553#pragma GCC diagnostic push
22554#pragma GCC diagnostic ignored "-Wnonnull-compare"
22555#endif
22556 if (sax == nullptr) {
22557 JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
22558 }
22559#if defined(__clang__)
22560#pragma clang diagnostic pop
22561#elif defined(__GNUC__)
22562#pragma GCC diagnostic pop
22563#endif
22564 auto ia = detail::input_adapter(std::forward<InputType>(i));
22565 return format == input_format_t::json
22566 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
22567 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
22568 }
22569
22572 template<class IteratorType, class SAX>
22573 JSON_HEDLEY_NON_NULL(3)
22574 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
22575 input_format_t format = input_format_t::json,
22576 const bool strict = true,
22577 const bool ignore_comments = false,
22578 const bool ignore_trailing_commas = false) {
22579#if defined(__clang__)
22580#pragma clang diagnostic push
22581#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
22582#elif defined(__GNUC__)
22583#pragma GCC diagnostic push
22584#pragma GCC diagnostic ignored "-Wnonnull-compare"
22585#endif
22586 if (sax == nullptr) {
22587 JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
22588 }
22589#if defined(__clang__)
22590#pragma clang diagnostic pop
22591#elif defined(__GNUC__)
22592#pragma GCC diagnostic pop
22593#endif
22594 auto ia = detail::input_adapter(std::move(first), std::move(last));
22595 return format == input_format_t::json
22596 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
22597 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
22598 }
22599
22605 template <typename SAX>
22606 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
22607 JSON_HEDLEY_NON_NULL(2)
22608 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
22609 input_format_t format = input_format_t::json,
22610 const bool strict = true,
22611 const bool ignore_comments = false,
22612 const bool ignore_trailing_commas = false) {
22613#if defined(__clang__)
22614#pragma clang diagnostic push
22615#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
22616#elif defined(__GNUC__)
22617#pragma GCC diagnostic push
22618#pragma GCC diagnostic ignored "-Wnonnull-compare"
22619#endif
22620 if (sax == nullptr) {
22621 JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
22622 }
22623#if defined(__clang__)
22624#pragma clang diagnostic pop
22625#elif defined(__GNUC__)
22626#pragma GCC diagnostic pop
22627#endif
22628 auto ia = i.get();
22629 return format == input_format_t::json
22630 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22631 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
22632 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22633 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
22634 }
22635#ifndef JSON_NO_IO
22642 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
22643 friend std::istream& operator<<(basic_json& j, std::istream& i) {
22644 return operator>>(i, j);
22645 }
22646
22649 friend std::istream& operator>>(std::istream& i, basic_json& j) {
22650 parser(detail::input_adapter(i)).parse(false, j);
22651 return i;
22652 }
22653#endif // JSON_NO_IO
22655
22657 // convenience functions //
22659
22662 JSON_HEDLEY_RETURNS_NON_NULL
22663 const char* type_name() const noexcept {
22664 switch (m_data.m_type) {
22665 case value_t::null:
22666 return "null";
22667 case value_t::object:
22668 return "object";
22669 case value_t::array:
22670 return "array";
22671 case value_t::string:
22672 return "string";
22673 case value_t::boolean:
22674 return "boolean";
22675 case value_t::binary:
22676 return "binary";
22677 case value_t::discarded:
22678 return "discarded";
22679 case value_t::number_integer:
22680 case value_t::number_unsigned:
22681 case value_t::number_float:
22682 return "number";
22683 default:
22684 return "invalid";
22685 }
22686 }
22687
22688JSON_PRIVATE_UNLESS_TESTED:
22690 // member variables //
22692
22693 struct data {
22695 value_t m_type = value_t::null;
22696
22698 json_value m_value = {};
22699
22700 data(const value_t v)
22701 : m_type(v), m_value(v) {}
22702
22703 data(size_type cnt, const basic_json& val)
22704 : m_type(value_t::array) {
22705 m_value.array = create<array_t>(cnt, val);
22706 }
22707
22708 data() noexcept = default;
22709 data(data&&) noexcept = default;
22710 data(const data&) noexcept = delete;
22711 data& operator=(data&&) noexcept = delete;
22712 data& operator=(const data&) noexcept = delete;
22713
22714 ~data() noexcept {
22715 m_value.destroy(m_type);
22716 }
22717 };
22718
22719 data m_data = {};
22720
22721#if JSON_DIAGNOSTICS
22723 basic_json* m_parent = nullptr;
22724#endif
22725
22726#if JSON_DIAGNOSTIC_POSITIONS
22728 std::size_t start_position = std::string::npos;
22730 std::size_t end_position = std::string::npos;
22731public:
22732 constexpr std::size_t start_pos() const noexcept {
22733 return start_position;
22734 }
22735
22736 constexpr std::size_t end_pos() const noexcept {
22737 return end_position;
22738 }
22739#endif
22740
22742 // binary serialization/deserialization //
22744
22747
22748public:
22751 static std::vector<std::uint8_t> to_cbor(const basic_json& j) {
22752 std::vector<std::uint8_t> result;
22753 to_cbor(j, result);
22754 return result;
22755 }
22756
22759 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o) {
22760 binary_writer<std::uint8_t>(o).write_cbor(j);
22761 }
22762
22765 static void to_cbor(const basic_json& j, detail::output_adapter<char> o) {
22766 binary_writer<char>(o).write_cbor(j);
22767 }
22768
22771 static std::vector<std::uint8_t> to_msgpack(const basic_json& j) {
22772 std::vector<std::uint8_t> result;
22773 to_msgpack(j, result);
22774 return result;
22775 }
22776
22779 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o) {
22780 binary_writer<std::uint8_t>(o).write_msgpack(j);
22781 }
22782
22785 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o) {
22786 binary_writer<char>(o).write_msgpack(j);
22787 }
22788
22791 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
22792 const bool use_size = false,
22793 const bool use_type = false) {
22794 std::vector<std::uint8_t> result;
22795 to_ubjson(j, result, use_size, use_type);
22796 return result;
22797 }
22798
22801 static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
22802 const bool use_size = false, const bool use_type = false) {
22803 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
22804 }
22805
22808 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
22809 const bool use_size = false, const bool use_type = false) {
22810 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
22811 }
22812
22815 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
22816 const bool use_size = false,
22817 const bool use_type = false,
22818 const bjdata_version_t version = bjdata_version_t::draft2) {
22819 std::vector<std::uint8_t> result;
22820 to_bjdata(j, result, use_size, use_type, version);
22821 return result;
22822 }
22823
22826 static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
22827 const bool use_size = false, const bool use_type = false,
22828 const bjdata_version_t version = bjdata_version_t::draft2) {
22829 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true, version);
22830 }
22831
22834 static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
22835 const bool use_size = false, const bool use_type = false,
22836 const bjdata_version_t version = bjdata_version_t::draft2) {
22837 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true, version);
22838 }
22839
22842 static std::vector<std::uint8_t> to_bson(const basic_json& j) {
22843 std::vector<std::uint8_t> result;
22844 to_bson(j, result);
22845 return result;
22846 }
22847
22850 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o) {
22851 binary_writer<std::uint8_t>(o).write_bson(j);
22852 }
22853
22856 static void to_bson(const basic_json& j, detail::output_adapter<char> o) {
22857 binary_writer<char>(o).write_bson(j);
22858 }
22859
22862 template<typename InputType>
22863 JSON_HEDLEY_WARN_UNUSED_RESULT
22864 static basic_json from_cbor(InputType&& i,
22865 const bool strict = true,
22866 const bool allow_exceptions = true,
22867 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) {
22868 basic_json result;
22869 auto ia = detail::input_adapter(std::forward<InputType>(i));
22870 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
22871 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]
22872 return res ? result : basic_json(value_t::discarded);
22873 }
22874
22877 template<typename IteratorType>
22878 JSON_HEDLEY_WARN_UNUSED_RESULT
22879 static basic_json from_cbor(IteratorType first, IteratorType last,
22880 const bool strict = true,
22881 const bool allow_exceptions = true,
22882 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) {
22883 basic_json result;
22884 auto ia = detail::input_adapter(std::move(first), std::move(last));
22885 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
22886 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]
22887 return res ? result : basic_json(value_t::discarded);
22888 }
22889
22890 template<typename T>
22891 JSON_HEDLEY_WARN_UNUSED_RESULT
22892 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
22893 static basic_json from_cbor(const T* ptr, std::size_t len,
22894 const bool strict = true,
22895 const bool allow_exceptions = true,
22896 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) {
22897 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
22898 }
22899
22900 JSON_HEDLEY_WARN_UNUSED_RESULT
22901 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
22902 static basic_json from_cbor(detail::span_input_adapter&& i,
22903 const bool strict = true,
22904 const bool allow_exceptions = true,
22905 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) {
22906 basic_json result;
22907 auto ia = i.get();
22908 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
22909 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22910 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]
22911 return res ? result : basic_json(value_t::discarded);
22912 }
22913
22916 template<typename InputType>
22917 JSON_HEDLEY_WARN_UNUSED_RESULT
22918 static basic_json from_msgpack(InputType&& i,
22919 const bool strict = true,
22920 const bool allow_exceptions = true) {
22921 basic_json result;
22922 auto ia = detail::input_adapter(std::forward<InputType>(i));
22923 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
22924 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]
22925 return res ? result : basic_json(value_t::discarded);
22926 }
22927
22930 template<typename IteratorType>
22931 JSON_HEDLEY_WARN_UNUSED_RESULT
22932 static basic_json from_msgpack(IteratorType first, IteratorType last,
22933 const bool strict = true,
22934 const bool allow_exceptions = true) {
22935 basic_json result;
22936 auto ia = detail::input_adapter(std::move(first), std::move(last));
22937 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
22938 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]
22939 return res ? result : basic_json(value_t::discarded);
22940 }
22941
22942 template<typename T>
22943 JSON_HEDLEY_WARN_UNUSED_RESULT
22944 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
22945 static basic_json from_msgpack(const T* ptr, std::size_t len,
22946 const bool strict = true,
22947 const bool allow_exceptions = true) {
22948 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
22949 }
22950
22951 JSON_HEDLEY_WARN_UNUSED_RESULT
22952 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
22953 static basic_json from_msgpack(detail::span_input_adapter&& i,
22954 const bool strict = true,
22955 const bool allow_exceptions = true) {
22956 basic_json result;
22957 auto ia = i.get();
22958 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
22959 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22960 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]
22961 return res ? result : basic_json(value_t::discarded);
22962 }
22963
22966 template<typename InputType>
22967 JSON_HEDLEY_WARN_UNUSED_RESULT
22968 static basic_json from_ubjson(InputType&& i,
22969 const bool strict = true,
22970 const bool allow_exceptions = true) {
22971 basic_json result;
22972 auto ia = detail::input_adapter(std::forward<InputType>(i));
22973 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
22974 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]
22975 return res ? result : basic_json(value_t::discarded);
22976 }
22977
22980 template<typename IteratorType>
22981 JSON_HEDLEY_WARN_UNUSED_RESULT
22982 static basic_json from_ubjson(IteratorType first, IteratorType last,
22983 const bool strict = true,
22984 const bool allow_exceptions = true) {
22985 basic_json result;
22986 auto ia = detail::input_adapter(std::move(first), std::move(last));
22987 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
22988 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]
22989 return res ? result : basic_json(value_t::discarded);
22990 }
22991
22992 template<typename T>
22993 JSON_HEDLEY_WARN_UNUSED_RESULT
22994 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
22995 static basic_json from_ubjson(const T* ptr, std::size_t len,
22996 const bool strict = true,
22997 const bool allow_exceptions = true) {
22998 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
22999 }
23000
23001 JSON_HEDLEY_WARN_UNUSED_RESULT
23002 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23003 static basic_json from_ubjson(detail::span_input_adapter&& i,
23004 const bool strict = true,
23005 const bool allow_exceptions = true) {
23006 basic_json result;
23007 auto ia = i.get();
23008 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
23009 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23010 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]
23011 return res ? result : basic_json(value_t::discarded);
23012 }
23013
23016 template<typename InputType>
23017 JSON_HEDLEY_WARN_UNUSED_RESULT
23018 static basic_json from_bjdata(InputType&& i,
23019 const bool strict = true,
23020 const bool allow_exceptions = true) {
23021 basic_json result;
23022 auto ia = detail::input_adapter(std::forward<InputType>(i));
23023 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
23024 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]
23025 return res ? result : basic_json(value_t::discarded);
23026 }
23027
23030 template<typename IteratorType>
23031 JSON_HEDLEY_WARN_UNUSED_RESULT
23032 static basic_json from_bjdata(IteratorType first, IteratorType last,
23033 const bool strict = true,
23034 const bool allow_exceptions = true) {
23035 basic_json result;
23036 auto ia = detail::input_adapter(std::move(first), std::move(last));
23037 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
23038 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]
23039 return res ? result : basic_json(value_t::discarded);
23040 }
23041
23044 template<typename InputType>
23045 JSON_HEDLEY_WARN_UNUSED_RESULT
23046 static basic_json from_bson(InputType&& i,
23047 const bool strict = true,
23048 const bool allow_exceptions = true) {
23049 basic_json result;
23050 auto ia = detail::input_adapter(std::forward<InputType>(i));
23051 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
23052 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]
23053 return res ? result : basic_json(value_t::discarded);
23054 }
23055
23058 template<typename IteratorType>
23059 JSON_HEDLEY_WARN_UNUSED_RESULT
23060 static basic_json from_bson(IteratorType first, IteratorType last,
23061 const bool strict = true,
23062 const bool allow_exceptions = true) {
23063 basic_json result;
23064 auto ia = detail::input_adapter(std::move(first), std::move(last));
23065 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
23066 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]
23067 return res ? result : basic_json(value_t::discarded);
23068 }
23069
23070 template<typename T>
23071 JSON_HEDLEY_WARN_UNUSED_RESULT
23072 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23073 static basic_json from_bson(const T* ptr, std::size_t len,
23074 const bool strict = true,
23075 const bool allow_exceptions = true) {
23076 return from_bson(ptr, ptr + len, strict, allow_exceptions);
23077 }
23078
23079 JSON_HEDLEY_WARN_UNUSED_RESULT
23080 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23081 static basic_json from_bson(detail::span_input_adapter&& i,
23082 const bool strict = true,
23083 const bool allow_exceptions = true) {
23084 basic_json result;
23085 auto ia = i.get();
23086 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
23087 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23088 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]
23089 return res ? result : basic_json(value_t::discarded);
23090 }
23092
23094 // JSON Pointer support //
23096
23099
23102 reference operator[](const json_pointer& ptr) {
23103 return ptr.get_unchecked(this);
23104 }
23105
23106 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23107 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23108 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) {
23109 return ptr.get_unchecked(this);
23110 }
23111
23114 const_reference operator[](const json_pointer& ptr) const {
23115 return ptr.get_unchecked(this);
23116 }
23117
23118 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23119 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23120 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const {
23121 return ptr.get_unchecked(this);
23122 }
23123
23126 reference at(const json_pointer& ptr) {
23127 return ptr.get_checked(this);
23128 }
23129
23130 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23131 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23132 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) {
23133 return ptr.get_checked(this);
23134 }
23135
23138 const_reference at(const json_pointer& ptr) const {
23139 return ptr.get_checked(this);
23140 }
23141
23142 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23143 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23144 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const {
23145 return ptr.get_checked(this);
23146 }
23147
23150 basic_json flatten() const {
23151 basic_json result(value_t::object);
23152 json_pointer::flatten("", *this, result);
23153 return result;
23154 }
23155
23158 basic_json unflatten() const {
23159 return json_pointer::unflatten(*this);
23160 }
23161
23163
23165 // JSON Patch functions //
23167
23170
23173 void patch_inplace(const basic_json& json_patch) {
23174 basic_json& result = *this;
23175 // the valid JSON Patch operations
23176 enum class patch_operations { add, remove, replace, move, copy, test, invalid };
23177
23178 const auto get_op = [](const string_t& op) {
23179 if (op == "add") {
23180 return patch_operations::add;
23181 }
23182 if (op == "remove") {
23183 return patch_operations::remove;
23184 }
23185 if (op == "replace") {
23186 return patch_operations::replace;
23187 }
23188 if (op == "move") {
23189 return patch_operations::move;
23190 }
23191 if (op == "copy") {
23192 return patch_operations::copy;
23193 }
23194 if (op == "test") {
23195 return patch_operations::test;
23196 }
23197
23198 return patch_operations::invalid;
23199 };
23200
23201 // wrapper for "add" operation; add value at ptr
23202 const auto operation_add = [&result](json_pointer& ptr, const basic_json& val) {
23203 // adding to the root of the target document means replacing it
23204 if (ptr.empty()) {
23205 result = val;
23206 return;
23207 }
23208
23209 // make sure the top element of the pointer exists
23210 json_pointer const top_pointer = ptr.top();
23211 if (top_pointer != ptr) {
23212 result.at(top_pointer);
23213 }
23214
23215 // get reference to the parent of the JSON pointer ptr
23216 const auto last_path = ptr.back();
23217 ptr.pop_back();
23218 // parent must exist when performing patch add per RFC6902 specs
23219 basic_json& parent = result.at(ptr);
23220
23221 switch (parent.m_data.m_type) {
23222 case value_t::null:
23223 case value_t::object:
23224 {
23225 // use operator[] to add value
23226 parent[last_path] = val;
23227 break;
23228 }
23229
23230 case value_t::array:
23231 {
23232 if (last_path == "-") {
23233 // special case: append to back
23234 parent.push_back(val);
23235 }
23236 else {
23237 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
23238 if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) {
23239 // avoid undefined behavior
23240 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
23241 }
23242
23243 // default case: insert add offset
23244 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
23245 }
23246 break;
23247 }
23248
23249 // if there exists a parent, it cannot be primitive
23250 case value_t::string: // LCOV_EXCL_LINE
23251 case value_t::boolean: // LCOV_EXCL_LINE
23252 case value_t::number_integer: // LCOV_EXCL_LINE
23253 case value_t::number_unsigned: // LCOV_EXCL_LINE
23254 case value_t::number_float: // LCOV_EXCL_LINE
23255 case value_t::binary: // LCOV_EXCL_LINE
23256 case value_t::discarded: // LCOV_EXCL_LINE
23257 default: // LCOV_EXCL_LINE
23258 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
23259 }
23260 };
23261
23262 // wrapper for "remove" operation; remove value at ptr
23263 const auto operation_remove = [this, &result](json_pointer& ptr) {
23264 // get reference to the parent of the JSON pointer ptr
23265 const auto last_path = ptr.back();
23266 ptr.pop_back();
23267 basic_json& parent = result.at(ptr);
23268
23269 // remove child
23270 if (parent.is_object()) {
23271 // perform range check
23272 auto it = parent.find(last_path);
23273 if (JSON_HEDLEY_LIKELY(it != parent.end())) {
23274 parent.erase(it);
23275 }
23276 else {
23277 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
23278 }
23279 }
23280 else if (parent.is_array()) {
23281 // note erase performs range check
23282 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
23283 }
23284 };
23285
23286 // type check: top level value must be an array
23287 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) {
23288 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
23289 }
23290
23291 // iterate and apply the operations
23292 for (const auto& val : json_patch) {
23293 // wrapper to get a value for an operation
23294 const auto get_value = [&val](const string_t& op,
23295 const string_t& member,
23296 bool string_type) -> basic_json& {
23297 // find value
23298 auto it = val.m_data.m_value.object->find(member);
23299
23300 // context-sensitive error message
23301 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
23302
23303 // check if the desired value is present
23304 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end())) {
23305 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
23306 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
23307 }
23308
23309 // check if the result is of type string
23310 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) {
23311 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
23312 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
23313 }
23314
23315 // no error: return value
23316 return it->second;
23317 };
23318
23319 // type check: every element of the array must be an object
23320 if (JSON_HEDLEY_UNLIKELY(!val.is_object())) {
23321 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
23322 }
23323
23324 // collect mandatory members
23325 const auto op = get_value("op", "op", true).template get<string_t>();
23326 const auto path = get_value(op, "path", true).template get<string_t>();
23327 json_pointer ptr(path);
23328
23329 switch (get_op(op)) {
23330 case patch_operations::add:
23331 {
23332 operation_add(ptr, get_value("add", "value", false));
23333 break;
23334 }
23335
23336 case patch_operations::remove:
23337 {
23338 operation_remove(ptr);
23339 break;
23340 }
23341
23342 case patch_operations::replace:
23343 {
23344 // the "path" location must exist - use at()
23345 result.at(ptr) = get_value("replace", "value", false);
23346 break;
23347 }
23348
23349 case patch_operations::move:
23350 {
23351 const auto from_path = get_value("move", "from", true).template get<string_t>();
23352 json_pointer from_ptr(from_path);
23353
23354 // the "from" location must exist - use at()
23355 basic_json const v = result.at(from_ptr);
23356
23357 // The move operation is functionally identical to a
23358 // "remove" operation on the "from" location, followed
23359 // immediately by an "add" operation at the target
23360 // location with the value that was just removed.
23361 operation_remove(from_ptr);
23362 operation_add(ptr, v);
23363 break;
23364 }
23365
23366 case patch_operations::copy:
23367 {
23368 const auto from_path = get_value("copy", "from", true).template get<string_t>();
23369 const json_pointer from_ptr(from_path);
23370
23371 // the "from" location must exist - use at()
23372 basic_json const v = result.at(from_ptr);
23373
23374 // The copy is functionally identical to an "add"
23375 // operation at the target location using the value
23376 // specified in the "from" member.
23377 operation_add(ptr, v);
23378 break;
23379 }
23380
23381 case patch_operations::test:
23382 {
23383 bool success = false;
23384 JSON_TRY
23385 {
23386 // check if "value" matches the one at "path"
23387 // the "path" location must exist - use at()
23388 success = (result.at(ptr) == get_value("test", "value", false));
23389 }
23390 JSON_INTERNAL_CATCH(out_of_range&) {
23391 // ignore out of range errors: success remains false
23392 }
23393
23394 // throw an exception if the test fails
23395 if (JSON_HEDLEY_UNLIKELY(!success)) {
23396 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
23397 }
23398
23399 break;
23400 }
23401
23402 case patch_operations::invalid:
23403 default:
23404 {
23405 // op must be "add", "remove", "replace", "move", "copy", or
23406 // "test"
23407 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
23408 }
23409 }
23410 }
23411 }
23412
23415 basic_json patch(const basic_json& json_patch) const {
23416 basic_json result = *this;
23417 result.patch_inplace(json_patch);
23418 return result;
23419 }
23420
23423 JSON_HEDLEY_WARN_UNUSED_RESULT
23424 static basic_json diff(const basic_json& source, const basic_json& target,
23425 const string_t& path = "") {
23426 // the patch
23427 basic_json result(value_t::array);
23428
23429 // if the values are the same, return an empty patch
23430 if (source == target) {
23431 return result;
23432 }
23433
23434 if (source.type() != target.type()) {
23435 // different types: replace value
23436 result.push_back(
23437 {
23438 {"op", "replace"}, {"path", path}, {"value", target}
23439 });
23440 return result;
23441 }
23442
23443 switch (source.type()) {
23444 case value_t::array:
23445 {
23446 // first pass: traverse common elements
23447 std::size_t i = 0;
23448 while (i < source.size() && i < target.size()) {
23449 // recursive call to compare array values at index i
23450 auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
23451 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
23452 ++i;
23453 }
23454
23455 // We now reached the end of at least one array
23456 // in a second pass, traverse the remaining elements
23457
23458 // remove my remaining elements
23459 const auto end_index = static_cast<difference_type>(result.size());
23460 while (i < source.size()) {
23461 // add operations in reverse order to avoid invalid
23462 // indices
23463 result.insert(result.begin() + end_index, object(
23464 {
23465 {"op", "remove"},
23466 {"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
23467 }));
23468 ++i;
23469 }
23470
23471 // add other remaining elements
23472 while (i < target.size()) {
23473 result.push_back(
23474 {
23475 {"op", "add"},
23476 {"path", detail::concat<string_t>(path, "/-")},
23477 {"value", target[i]}
23478 });
23479 ++i;
23480 }
23481
23482 break;
23483 }
23484
23485 case value_t::object:
23486 {
23487 // first pass: traverse this object's elements
23488 for (auto it = source.cbegin(); it != source.cend(); ++it) {
23489 // escape the key name to be used in a JSON patch
23490 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
23491
23492 if (target.find(it.key()) != target.end()) {
23493 // recursive call to compare object values at key it
23494 auto temp_diff = diff(it.value(), target[it.key()], path_key);
23495 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
23496 }
23497 else {
23498 // found a key that is not in o -> remove it
23499 result.push_back(object(
23500 {
23501 {"op", "remove"}, {"path", path_key}
23502 }));
23503 }
23504 }
23505
23506 // second pass: traverse other object's elements
23507 for (auto it = target.cbegin(); it != target.cend(); ++it) {
23508 if (source.find(it.key()) == source.end()) {
23509 // found a key that is not in this -> add it
23510 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
23511 result.push_back(
23512 {
23513 {"op", "add"}, {"path", path_key},
23514 {"value", it.value()}
23515 });
23516 }
23517 }
23518
23519 break;
23520 }
23521
23522 case value_t::null:
23523 case value_t::string:
23524 case value_t::boolean:
23525 case value_t::number_integer:
23526 case value_t::number_unsigned:
23527 case value_t::number_float:
23528 case value_t::binary:
23529 case value_t::discarded:
23530 default:
23531 {
23532 // both primitive types: replace value
23533 result.push_back(
23534 {
23535 {"op", "replace"}, {"path", path}, {"value", target}
23536 });
23537 break;
23538 }
23539 }
23540
23541 return result;
23542 }
23544
23546 // JSON Merge Patch functions //
23548
23551
23554 void merge_patch(const basic_json& apply_patch) {
23555 if (apply_patch.is_object()) {
23556 if (!is_object()) {
23557 *this = object();
23558 }
23559 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) {
23560 if (it.value().is_null()) {
23561 erase(it.key());
23562 }
23563 else {
23564 operator[](it.key()).merge_patch(it.value());
23565 }
23566 }
23567 }
23568 else {
23569 *this = apply_patch;
23570 }
23571 }
23572
23574};
23575
23578NLOHMANN_BASIC_JSON_TPL_DECLARATION
23579std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) {
23580 return j.dump();
23581}
23582
23583inline namespace literals {
23584 inline namespace json_literals {
23585
23588 JSON_HEDLEY_NON_NULL(1)
23589#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
23590 inline nlohmann::json operator""_json(const char* s, std::size_t n)
23591#else
23592 // GCC 4.8 requires a space between "" and suffix
23593 inline nlohmann::json operator"" _json(const char* s, std::size_t n)
23594#endif
23595 {
23596 return nlohmann::json::parse(s, s + n);
23597 }
23598
23599#if defined(__cpp_char8_t)
23600 JSON_HEDLEY_NON_NULL(1)
23601 inline nlohmann::json operator""_json(const char8_t* s, std::size_t n) {
23602 return nlohmann::json::parse(reinterpret_cast<const char*>(s),
23603 reinterpret_cast<const char*>(s) + n);
23604 }
23605#endif
23606
23609 JSON_HEDLEY_NON_NULL(1)
23610#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
23611 inline nlohmann::json::json_pointer operator""_json_pointer(const char* s, std::size_t n)
23612#else
23613 // GCC 4.8 requires a space between "" and suffix
23614 inline nlohmann::json::json_pointer operator"" _json_pointer(const char* s, std::size_t n)
23615#endif
23616 {
23617 return nlohmann::json::json_pointer(std::string(s, n));
23618 }
23619
23620#if defined(__cpp_char8_t)
23621 inline nlohmann::json::json_pointer operator""_json_pointer(const char8_t* s, std::size_t n) {
23622 return nlohmann::json::json_pointer(std::string(reinterpret_cast<const char*>(s), n));
23623 }
23624#endif
23625
23626 } // namespace json_literals
23627} // namespace literals
23628NLOHMANN_JSON_NAMESPACE_END
23629
23631// nonmember support //
23633
23634namespace std // NOLINT(cert-dcl58-cpp)
23635{
23636
23639 NLOHMANN_BASIC_JSON_TPL_DECLARATION
23640 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
23641 {
23642 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const {
23643 return nlohmann::detail::hash(j);
23644 }
23645 };
23646
23647 // specialization for std::less<value_t>
23648 template<>
23649 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
23650 {
23655 bool operator()(::nlohmann::detail::value_t lhs,
23656 ::nlohmann::detail::value_t rhs) const noexcept {
23657#if JSON_HAS_THREE_WAY_COMPARISON
23658 return std::is_lt(lhs <=> rhs); // *NOPAD*
23659#else
23660 return ::nlohmann::detail::operator<(lhs, rhs);
23661#endif
23662 }
23663 };
23664
23665 // C++20 prohibit function specialization in the std namespace.
23666#ifndef JSON_HAS_CPP_20
23667
23670 NLOHMANN_BASIC_JSON_TPL_DECLARATION
23671 inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
23672 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23673 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value) {
23674 j1.swap(j2);
23675 }
23676
23677#endif
23678
23679} // namespace std
23680
23681#if JSON_USE_GLOBAL_UDLS
23682#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
23683using nlohmann::literals::json_literals::operator""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
23684using nlohmann::literals::json_literals::operator""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
23685#else
23686 // GCC 4.8 requires a space between "" and suffix
23687using nlohmann::literals::json_literals::operator"" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
23688using nlohmann::literals::json_literals::operator"" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
23689#endif
23690#endif
23691
23692// #include <nlohmann/detail/macro_unscope.hpp>
23693// __ _____ _____ _____
23694// __| | __| | | | JSON for Modern C++
23695// | | |__ | | | | | | version 3.12.0
23696// |_____|_____|_____|_|___| https://github.com/nlohmann/json
23697//
23698// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
23699// SPDX-License-Identifier: MIT
23700
23701
23702
23703// restore clang diagnostic settings
23704#if defined(__clang__)
23705#pragma clang diagnostic pop
23706#endif
23707
23708// clean up
23709#undef JSON_ASSERT
23710#undef JSON_INTERNAL_CATCH
23711#undef JSON_THROW
23712#undef JSON_PRIVATE_UNLESS_TESTED
23713#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
23714#undef NLOHMANN_BASIC_JSON_TPL
23715#undef JSON_EXPLICIT
23716#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
23717#undef JSON_INLINE_VARIABLE
23718#undef JSON_NO_UNIQUE_ADDRESS
23719#undef JSON_DISABLE_ENUM_SERIALIZATION
23720#undef JSON_USE_GLOBAL_UDLS
23721
23722#ifndef JSON_TEST_KEEP_MACROS
23723#undef JSON_CATCH
23724#undef JSON_TRY
23725#undef JSON_HAS_CPP_11
23726#undef JSON_HAS_CPP_14
23727#undef JSON_HAS_CPP_17
23728#undef JSON_HAS_CPP_20
23729#undef JSON_HAS_CPP_23
23730#undef JSON_HAS_CPP_26
23731#undef JSON_HAS_FILESYSTEM
23732#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
23733#undef JSON_HAS_THREE_WAY_COMPARISON
23734#undef JSON_HAS_RANGES
23735#undef JSON_HAS_STATIC_RTTI
23736#undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23737#endif
23738
23739// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
23740// __ _____ _____ _____
23741// __| | __| | | | JSON for Modern C++
23742// | | |__ | | | | | | version 3.12.0
23743// |_____|_____|_____|_|___| https://github.com/nlohmann/json
23744//
23745// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
23746// SPDX-License-Identifier: MIT
23747
23748
23749
23750#undef JSON_HEDLEY_ALWAYS_INLINE
23751#undef JSON_HEDLEY_ARM_VERSION
23752#undef JSON_HEDLEY_ARM_VERSION_CHECK
23753#undef JSON_HEDLEY_ARRAY_PARAM
23754#undef JSON_HEDLEY_ASSUME
23755#undef JSON_HEDLEY_BEGIN_C_DECLS
23756#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
23757#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
23758#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
23759#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
23760#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
23761#undef JSON_HEDLEY_CLANG_HAS_FEATURE
23762#undef JSON_HEDLEY_CLANG_HAS_WARNING
23763#undef JSON_HEDLEY_COMPCERT_VERSION
23764#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
23765#undef JSON_HEDLEY_CONCAT
23766#undef JSON_HEDLEY_CONCAT3
23767#undef JSON_HEDLEY_CONCAT3_EX
23768#undef JSON_HEDLEY_CONCAT_EX
23769#undef JSON_HEDLEY_CONST
23770#undef JSON_HEDLEY_CONSTEXPR
23771#undef JSON_HEDLEY_CONST_CAST
23772#undef JSON_HEDLEY_CPP_CAST
23773#undef JSON_HEDLEY_CRAY_VERSION
23774#undef JSON_HEDLEY_CRAY_VERSION_CHECK
23775#undef JSON_HEDLEY_C_DECL
23776#undef JSON_HEDLEY_DEPRECATED
23777#undef JSON_HEDLEY_DEPRECATED_FOR
23778#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
23779#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
23780#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
23781#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
23782#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
23783#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
23784#undef JSON_HEDLEY_DIAGNOSTIC_POP
23785#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
23786#undef JSON_HEDLEY_DMC_VERSION
23787#undef JSON_HEDLEY_DMC_VERSION_CHECK
23788#undef JSON_HEDLEY_EMPTY_BASES
23789#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
23790#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
23791#undef JSON_HEDLEY_END_C_DECLS
23792#undef JSON_HEDLEY_FLAGS
23793#undef JSON_HEDLEY_FLAGS_CAST
23794#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
23795#undef JSON_HEDLEY_GCC_HAS_BUILTIN
23796#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
23797#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
23798#undef JSON_HEDLEY_GCC_HAS_EXTENSION
23799#undef JSON_HEDLEY_GCC_HAS_FEATURE
23800#undef JSON_HEDLEY_GCC_HAS_WARNING
23801#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
23802#undef JSON_HEDLEY_GCC_VERSION
23803#undef JSON_HEDLEY_GCC_VERSION_CHECK
23804#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
23805#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
23806#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
23807#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
23808#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
23809#undef JSON_HEDLEY_GNUC_HAS_FEATURE
23810#undef JSON_HEDLEY_GNUC_HAS_WARNING
23811#undef JSON_HEDLEY_GNUC_VERSION
23812#undef JSON_HEDLEY_GNUC_VERSION_CHECK
23813#undef JSON_HEDLEY_HAS_ATTRIBUTE
23814#undef JSON_HEDLEY_HAS_BUILTIN
23815#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
23816#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
23817#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
23818#undef JSON_HEDLEY_HAS_EXTENSION
23819#undef JSON_HEDLEY_HAS_FEATURE
23820#undef JSON_HEDLEY_HAS_WARNING
23821#undef JSON_HEDLEY_IAR_VERSION
23822#undef JSON_HEDLEY_IAR_VERSION_CHECK
23823#undef JSON_HEDLEY_IBM_VERSION
23824#undef JSON_HEDLEY_IBM_VERSION_CHECK
23825#undef JSON_HEDLEY_IMPORT
23826#undef JSON_HEDLEY_INLINE
23827#undef JSON_HEDLEY_INTEL_CL_VERSION
23828#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
23829#undef JSON_HEDLEY_INTEL_VERSION
23830#undef JSON_HEDLEY_INTEL_VERSION_CHECK
23831#undef JSON_HEDLEY_IS_CONSTANT
23832#undef JSON_HEDLEY_IS_CONSTEXPR_
23833#undef JSON_HEDLEY_LIKELY
23834#undef JSON_HEDLEY_MALLOC
23835#undef JSON_HEDLEY_MCST_LCC_VERSION
23836#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
23837#undef JSON_HEDLEY_MESSAGE
23838#undef JSON_HEDLEY_MSVC_VERSION
23839#undef JSON_HEDLEY_MSVC_VERSION_CHECK
23840#undef JSON_HEDLEY_NEVER_INLINE
23841#undef JSON_HEDLEY_NON_NULL
23842#undef JSON_HEDLEY_NO_ESCAPE
23843#undef JSON_HEDLEY_NO_RETURN
23844#undef JSON_HEDLEY_NO_THROW
23845#undef JSON_HEDLEY_NULL
23846#undef JSON_HEDLEY_PELLES_VERSION
23847#undef JSON_HEDLEY_PELLES_VERSION_CHECK
23848#undef JSON_HEDLEY_PGI_VERSION
23849#undef JSON_HEDLEY_PGI_VERSION_CHECK
23850#undef JSON_HEDLEY_PREDICT
23851#undef JSON_HEDLEY_PRINTF_FORMAT
23852#undef JSON_HEDLEY_PRIVATE
23853#undef JSON_HEDLEY_PUBLIC
23854#undef JSON_HEDLEY_PURE
23855#undef JSON_HEDLEY_REINTERPRET_CAST
23856#undef JSON_HEDLEY_REQUIRE
23857#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
23858#undef JSON_HEDLEY_REQUIRE_MSG
23859#undef JSON_HEDLEY_RESTRICT
23860#undef JSON_HEDLEY_RETURNS_NON_NULL
23861#undef JSON_HEDLEY_SENTINEL
23862#undef JSON_HEDLEY_STATIC_ASSERT
23863#undef JSON_HEDLEY_STATIC_CAST
23864#undef JSON_HEDLEY_STRINGIFY
23865#undef JSON_HEDLEY_STRINGIFY_EX
23866#undef JSON_HEDLEY_SUNPRO_VERSION
23867#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
23868#undef JSON_HEDLEY_TINYC_VERSION
23869#undef JSON_HEDLEY_TINYC_VERSION_CHECK
23870#undef JSON_HEDLEY_TI_ARMCL_VERSION
23871#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
23872#undef JSON_HEDLEY_TI_CL2000_VERSION
23873#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
23874#undef JSON_HEDLEY_TI_CL430_VERSION
23875#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
23876#undef JSON_HEDLEY_TI_CL6X_VERSION
23877#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
23878#undef JSON_HEDLEY_TI_CL7X_VERSION
23879#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
23880#undef JSON_HEDLEY_TI_CLPRU_VERSION
23881#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
23882#undef JSON_HEDLEY_TI_VERSION
23883#undef JSON_HEDLEY_TI_VERSION_CHECK
23884#undef JSON_HEDLEY_UNAVAILABLE
23885#undef JSON_HEDLEY_UNLIKELY
23886#undef JSON_HEDLEY_UNPREDICTABLE
23887#undef JSON_HEDLEY_UNREACHABLE
23888#undef JSON_HEDLEY_UNREACHABLE_RETURN
23889#undef JSON_HEDLEY_VERSION
23890#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
23891#undef JSON_HEDLEY_VERSION_DECODE_MINOR
23892#undef JSON_HEDLEY_VERSION_DECODE_REVISION
23893#undef JSON_HEDLEY_VERSION_ENCODE
23894#undef JSON_HEDLEY_WARNING
23895#undef JSON_HEDLEY_WARN_UNUSED_RESULT
23896#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
23897#undef JSON_HEDLEY_FALL_THROUGH
23898
23899
23900
23901#endif // INCLUDE_NLOHMANN_JSON_HPP_
namespace for Niels Lohmann
Definition json.hpp:18860
an internal type for a backed binary type
Definition json.hpp:6080
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.hpp:6086
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6104
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6094
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.hpp:6127
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.hpp:6098
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.hpp:6133
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.hpp:6090
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.hpp:6120
void clear_subtype() noexcept
clears the binary subtype
Definition json.hpp:6139
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:9454
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.hpp:9470
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:9490
void write_bson(const BasicJsonType &j)
Definition json.hpp:14962
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:15552
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition json.hpp:14954
void write_msgpack(const BasicJsonType &j)
Definition json.hpp:15264
void write_cbor(const BasicJsonType &j)
Definition json.hpp:14989
general exception of the basic_json class
Definition json.hpp:4489
const int id
the id of the exception
Definition json.hpp:4497
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:4492
Definition json.hpp:6363
Definition json.hpp:6404
exception indicating errors with iterators
Definition json.hpp:4638
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:13488
iter_impl(pointer object) noexcept
constructor for a given JSON instance
Definition json.hpp:12992
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:13071
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:13437
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:13062
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:13385
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:13421
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:13480
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:13302
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:13580
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.hpp:13341
iter_impl operator++(int) &
post-increment (it++)
Definition json.hpp:13242
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:13445
reference operator[](difference_type n) const
access to successor
Definition json.hpp:13545
pointer operator->() const
dereference the iterator
Definition json.hpp:13203
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:13518
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:13498
reference value() const
return the value of an iterator
Definition json.hpp:13594
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:13429
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:13253
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:13162
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:13508
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.hpp:13049
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition json.hpp:13377
iter_impl operator--(int) &
post-decrement (it–)
Definition json.hpp:13291
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.hpp:13040
void set_end() noexcept
set the iterator past the last value
Definition json.hpp:13125
Definition json.hpp:5417
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.hpp:5479
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.hpp:5484
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:5463
const iteration_proxy_value & operator*() const
dereference operator (needed for range-based for)
Definition json.hpp:5458
IteratorType::reference value() const
return value of the iterator
Definition json.hpp:5522
const string_type & key() const
return key of the iterator
Definition json.hpp:5489
proxy class for the items() function
Definition json.hpp:5528
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.hpp:5552
iteration_proxy_value< IteratorType > begin() const noexcept
return iterator begin (needed for range-based for)
Definition json.hpp:5547
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:5537
Definition json.hpp:6461
Definition json.hpp:14702
Definition json.hpp:9189
Definition json.hpp:8798
SAX implementation to create a JSON value from SAX events.
Definition json.hpp:8521
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.hpp:8535
Definition json.hpp:6861
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:6887
token_type
token types for the parser
Definition json.hpp:6864
@ value_float
an floating point number – use get_number_float() for actual value
Definition json.hpp:6872
@ begin_array
the character for array begin [
Definition json.hpp:6873
@ value_string
a string – use get_string() for actual value
Definition json.hpp:6869
@ end_array
the character for array end ]
Definition json.hpp:6875
@ uninitialized
indicating the scanner is uninitialized
Definition json.hpp:6865
@ parse_error
indicating a parse error
Definition json.hpp:6879
@ value_integer
a signed integer – use get_number_integer() for actual value
Definition json.hpp:6871
@ value_separator
the value separator ,
Definition json.hpp:6878
@ end_object
the character for object end }
Definition json.hpp:6876
@ literal_true
the true literal
Definition json.hpp:6866
@ begin_object
the character for object begin {
Definition json.hpp:6874
@ value_unsigned
an unsigned integer – use get_number_unsigned() for actual value
Definition json.hpp:6870
@ literal_null
the null literal
Definition json.hpp:6868
@ end_of_input
indicating the end of the input buffer
Definition json.hpp:6880
@ name_separator
the name separator :
Definition json.hpp:6877
@ literal_or_value
a literal or the begin of a value (only for diagnostics)
Definition json.hpp:6881
@ literal_false
the false literal
Definition json.hpp:6867
lexical analysis
Definition json.hpp:6934
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.hpp:8234
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.hpp:8222
std::string get_token_string() const
Definition json.hpp:8201
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.hpp:8166
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.hpp:8194
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.hpp:8171
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.hpp:8181
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.hpp:8176
exception indicating other library errors
Definition json.hpp:4684
exception indicating access out of the defined range
Definition json.hpp:4669
Definition json.hpp:14898
Definition json.hpp:14858
Definition json.hpp:14879
Definition json.hpp:14837
exception indicating a parse error
Definition json.hpp:4589
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:4601
const std::size_t byte
byte index of the parse error
Definition json.hpp:4624
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.hpp:12340
bool accept(const bool strict=true)
public accept interface
Definition json.hpp:12392
Definition json.hpp:12773
Definition json.hpp:17649
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:17664
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:17703
Definition json.hpp:6775
exception indicating executing a member function with a wrong type
Definition json.hpp:4654
Definition json.hpp:6612
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition json.hpp:3517
implements the Grisu2 algorithm for binary to decimal floating-point conversion.
Definition json.hpp:16586
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
Definition json.hpp:17024
cached_power get_cached_power_for_binary_exponent(int e)
Definition json.hpp:16861
boundaries compute_boundaries(FloatType value)
Definition json.hpp:16723
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition json.hpp:17343
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition json.hpp:17107
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition json.hpp:17441
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:17487
detail namespace with internal helper functions
Definition json.hpp:259
input_format_t
the supported input formats
Definition json.hpp:6352
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:17566
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.hpp:3091
bool little_endianness(int num=1) noexcept
determine system byte order
Definition json.hpp:9442
cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:9429
@ ignore
ignore tags
Definition json.hpp:9431
@ store
store tags as binary type
Definition json.hpp:9432
@ error
throw a parse_error exception in case of a tag
Definition json.hpp:9430
value_t
the JSON type enumeration
Definition json.hpp:2996
@ null
null value
Definition json.hpp:2997
@ number_integer
number value (signed integer)
Definition json.hpp:3002
@ boolean
boolean value
Definition json.hpp:3001
@ discarded
discarded by the parser callback function
Definition json.hpp:3006
@ binary
binary array (ordered collection of bytes)
Definition json.hpp:3005
@ object
object (unordered set of name/value pairs)
Definition json.hpp:2998
@ string
string value
Definition json.hpp:3000
@ number_float
number value (floating-point)
Definition json.hpp:3004
@ number_unsigned
number value (unsigned integer)
Definition json.hpp:3003
@ array
array (ordered collection of values)
Definition json.hpp:2999
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition json.hpp:6198
void unescape(StringType &s)
string unescaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3124
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:3025
error_handler_t
Definition json.hpp:17642
@ strict
throw a type_error exception in case of invalid UTF-8
Definition json.hpp:17643
@ replace
replace invalid UTF-8 sequences with U+FFFD
Definition json.hpp:17644
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3110
namespace for Niels Lohmann
Definition json.hpp:6026
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:6048
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:6039
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:6030
Definition json.hpp:3682
Definition json.hpp:3698
Definition json.hpp:3765
Definition json.hpp:4814
Definition json.hpp:4791
Definition json.hpp:4811
Definition json.hpp:4802
Definition json.hpp:4808
Definition json.hpp:4782
Definition json.hpp:4805
Definition json.hpp:287
Definition json.hpp:16710
Definition json.hpp:16848
Definition json.hpp:16598
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition json.hpp:16621
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:16700
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition json.hpp:16685
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition json.hpp:16610
Definition json.hpp:5632
Definition json.hpp:5297
Definition json.hpp:3626
Definition json.hpp:3678
Definition json.hpp:3649
Definition json.hpp:3663
Definition json.hpp:4726
Definition json.hpp:3236
an iterator value
Definition json.hpp:12874
Definition json.hpp:3575
Definition json.hpp:3563
Definition json.hpp:4301
Definition json.hpp:4108
Definition json.hpp:3961
Definition json.hpp:4032
Definition json.hpp:3884
Definition json.hpp:4069
Definition json.hpp:3920
Definition json.hpp:4035
Definition json.hpp:4048
Definition json.hpp:3857
Definition json.hpp:4005
Definition json.hpp:3917
Definition json.hpp:3926
Definition json.hpp:4072
Definition json.hpp:3797
Definition json.hpp:3778
Definition json.hpp:302
Definition json.hpp:3633
Definition json.hpp:6669
Definition json.hpp:3812
Definition json.hpp:4078
Definition json.hpp:4098
Definition json.hpp:3585
Definition json.hpp:4175
Definition json.hpp:4172
Definition json.hpp:3829
Definition json.hpp:9363
Definition json.hpp:9333
Definition json.hpp:4088
Definition json.hpp:4321
Definition json.hpp:3396
Definition json.hpp:3378
Default base class of the basic_json class.
Definition json.hpp:13763
Definition json.hpp:261
Definition json.hpp:3772
Definition json.hpp:274
struct to capture the start position of the current token
Definition json.hpp:3152
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:3156
std::size_t lines_read
the number of lines read
Definition json.hpp:3158
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:3154
Definition json.hpp:3313
Definition json.hpp:3318
Definition json.hpp:5995
Definition json.hpp:3254
Definition json.hpp:3270
Definition json.hpp:4256
Definition json.hpp:4218
Definition json.hpp:6507
SAX interface.
Definition json.hpp:8389
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
virtual bool end_array()=0
the end of an array was read
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
virtual bool null()=0
a null value was read
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
a minimal map-like container that preserves insertion order
Definition json.hpp:3528
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:23655
Definition json.hpp:13824