A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
json.h
Go to the documentation of this file.
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.12.0
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9/****************************************************************************\
10 * Note on documentation: The source files contain links to the online *
11 * documentation of the public API at https://json.nlohmann.me. This URL *
12 * contains the most recent documentation and should also be applicable to *
13 * previous versions; documentation for deprecated functions is not *
14 * removed, but marked deprecated. See "Generate documentation" section in *
15 * file docs/README.md. *
16\****************************************************************************/
17
18// NOLINTBEGIN(modernize-type-traits)
19
20#ifndef INCLUDE_NLOHMANN_JSON_HPP_
21#define INCLUDE_NLOHMANN_JSON_HPP_
22
23#include <algorithm> // all_of, find, for_each
24#include <cstddef> // nullptr_t, ptrdiff_t, size_t
25#include <functional> // hash, less
26#include <initializer_list> // initializer_list
27#ifndef JSON_NO_IO
28 #include <iosfwd> // istream, ostream
29#endif // JSON_NO_IO
30#include <iterator> // random_access_iterator_tag
31#include <memory> // unique_ptr
32#include <string> // string, stoi, to_string
33#include <utility> // declval, forward, move, pair, swap
34#include <vector> // vector
35
36// #include <nlohmann/adl_serializer.hpp>
37// __ _____ _____ _____
38// __| | __| | | | JSON for Modern C++
39// | | |__ | | | | | | version 3.12.0
40// |_____|_____|_____|_|___| https://github.com/nlohmann/json
41//
42// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
43// SPDX-License-Identifier: MIT
44
45
46
47#include <utility>
48
49// #include <nlohmann/detail/abi_macros.hpp>
50// __ _____ _____ _____
51// __| | __| | | | JSON for Modern C++
52// | | |__ | | | | | | version 3.12.0
53// |_____|_____|_____|_|___| https://github.com/nlohmann/json
54//
55// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
56// SPDX-License-Identifier: MIT
57
58
59
60// This file contains all macro definitions affecting or depending on the ABI
61
62#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
63 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
64 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0
65 #warning "Already included a different version of the library!"
66 #endif
67 #endif
68#endif
69
70#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
71#define NLOHMANN_JSON_VERSION_MINOR 12 // NOLINT(modernize-macro-to-enum)
72#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum)
73
74#ifndef JSON_DIAGNOSTICS
75 #define JSON_DIAGNOSTICS 0
76#endif
77
78#ifndef JSON_DIAGNOSTIC_POSITIONS
79 #define JSON_DIAGNOSTIC_POSITIONS 0
80#endif
81
82#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
83 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
84#endif
85
86#if JSON_DIAGNOSTICS
87 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
88#else
89 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
90#endif
91
92#if JSON_DIAGNOSTIC_POSITIONS
93 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp
94#else
95 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS
96#endif
97
98#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
99 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
100#else
101 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
102#endif
103
104#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
105 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
106#endif
107
108// Construct the namespace ABI tags component
109#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c
110#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \
111 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c)
112
113#define NLOHMANN_JSON_ABI_TAGS \
114 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
115 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
116 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \
117 NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS)
118
119// Construct the namespace version component
120#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
121 _v ## major ## _ ## minor ## _ ## patch
122#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
123 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
124
125#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
126#define NLOHMANN_JSON_NAMESPACE_VERSION
127#else
128#define NLOHMANN_JSON_NAMESPACE_VERSION \
129 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
130 NLOHMANN_JSON_VERSION_MINOR, \
131 NLOHMANN_JSON_VERSION_PATCH)
132#endif
133
134// Combine namespace components
135#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
136#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
137 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
138
139#ifndef NLOHMANN_JSON_NAMESPACE
140#define NLOHMANN_JSON_NAMESPACE \
141 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
142 NLOHMANN_JSON_ABI_TAGS, \
143 NLOHMANN_JSON_NAMESPACE_VERSION)
144#endif
145
146#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
147#define NLOHMANN_JSON_NAMESPACE_BEGIN \
148 namespace nlohmann \
149 { \
150 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
151 NLOHMANN_JSON_ABI_TAGS, \
152 NLOHMANN_JSON_NAMESPACE_VERSION) \
153 {
154#endif
155
156#ifndef NLOHMANN_JSON_NAMESPACE_END
157#define NLOHMANN_JSON_NAMESPACE_END \
158 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
159 } // namespace nlohmann
160#endif
161
162// #include <nlohmann/detail/conversions/from_json.hpp>
163// __ _____ _____ _____
164// __| | __| | | | JSON for Modern C++
165// | | |__ | | | | | | version 3.12.0
166// |_____|_____|_____|_|___| https://github.com/nlohmann/json
167//
168// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
169// SPDX-License-Identifier: MIT
170
171
172
173#include <algorithm> // transform
174#include <array> // array
175#include <forward_list> // forward_list
176#include <iterator> // inserter, front_inserter, end
177#include <map> // map
178#include <string> // string
179#include <tuple> // tuple, make_tuple
180#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
181#include <unordered_map> // unordered_map
182#include <utility> // pair, declval
183#include <valarray> // valarray
184
185// #include <nlohmann/detail/exceptions.hpp>
186// __ _____ _____ _____
187// __| | __| | | | JSON for Modern C++
188// | | |__ | | | | | | version 3.12.0
189// |_____|_____|_____|_|___| https://github.com/nlohmann/json
190//
191// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
192// SPDX-License-Identifier: MIT
193
194
195
196#include <cstddef> // nullptr_t
197#include <exception> // exception
198#if JSON_DIAGNOSTICS
199 #include <numeric> // accumulate
200#endif
201#include <stdexcept> // runtime_error
202#include <string> // to_string
203#include <vector> // vector
204
205// #include <nlohmann/detail/value_t.hpp>
206// __ _____ _____ _____
207// __| | __| | | | JSON for Modern C++
208// | | |__ | | | | | | version 3.12.0
209// |_____|_____|_____|_|___| https://github.com/nlohmann/json
210//
211// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
212// SPDX-License-Identifier: MIT
213
214
215
216#include <array> // array
217#include <cstddef> // size_t
218#include <cstdint> // uint8_t
219#include <string> // string
220
221// #include <nlohmann/detail/macro_scope.hpp>
222// __ _____ _____ _____
223// __| | __| | | | JSON for Modern C++
224// | | |__ | | | | | | version 3.12.0
225// |_____|_____|_____|_|___| https://github.com/nlohmann/json
226//
227// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
228// SPDX-License-Identifier: MIT
229
230
231
232#include <utility> // declval, pair
233// #include <nlohmann/detail/meta/detected.hpp>
234// __ _____ _____ _____
235// __| | __| | | | JSON for Modern C++
236// | | |__ | | | | | | version 3.12.0
237// |_____|_____|_____|_|___| https://github.com/nlohmann/json
238//
239// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
240// SPDX-License-Identifier: MIT
241
242
243
244#include <type_traits>
245
246// #include <nlohmann/detail/meta/void_t.hpp>
247// __ _____ _____ _____
248// __| | __| | | | JSON for Modern C++
249// | | |__ | | | | | | version 3.12.0
250// |_____|_____|_____|_|___| https://github.com/nlohmann/json
251//
252// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
253// SPDX-License-Identifier: MIT
254
255
256
257// #include <nlohmann/detail/abi_macros.hpp>
258
259
261namespace detail
262{
263
264template<typename ...Ts> struct make_void
265{
266 using type = void;
267};
268template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
269
270} // namespace detail
272
273
275namespace detail
276{
277
278// https://en.cppreference.com/w/cpp/experimental/is_detected
280{
281 nonesuch() = delete;
282 ~nonesuch() = delete;
283 nonesuch(nonesuch const&) = delete;
284 nonesuch(nonesuch const&&) = delete;
285 void operator=(nonesuch const&) = delete;
286 void operator=(nonesuch&&) = delete;
287};
288
289template<class Default,
290 class AlwaysVoid,
291 template<class...> class Op,
292 class... Args>
294{
295 using value_t = std::false_type;
296 using type = Default;
297};
298
299template<class Default, template<class...> class Op, class... Args>
300struct detector<Default, void_t<Op<Args...>>, Op, Args...>
301{
302 using value_t = std::true_type;
303 using type = Op<Args...>;
304};
305
306template<template<class...> class Op, class... Args>
307using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
308
309template<template<class...> class Op, class... Args>
310struct is_detected_lazy : is_detected<Op, Args...> { };
311
312template<template<class...> class Op, class... Args>
313using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
314
315template<class Default, template<class...> class Op, class... Args>
316using detected_or = detector<Default, void, Op, Args...>;
317
318template<class Default, template<class...> class Op, class... Args>
319using detected_or_t = typename detected_or<Default, Op, Args...>::type;
320
321template<class Expected, template<class...> class Op, class... Args>
322using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
323
324template<class To, template<class...> class Op, class... Args>
326 std::is_convertible<detected_t<Op, Args...>, To>;
327
328} // namespace detail
330
331// #include <nlohmann/thirdparty/hedley/hedley.hpp>
332
333
334// __ _____ _____ _____
335// __| | __| | | | JSON for Modern C++
336// | | |__ | | | | | | version 3.12.0
337// |_____|_____|_____|_|___| https://github.com/nlohmann/json
338//
339// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
340// SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson <evan@nemerson.com>
341// SPDX-License-Identifier: MIT
342
343/* Hedley - https://nemequ.github.io/hedley
344 * Created by Evan Nemerson <evan@nemerson.com>
345 */
346
347#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
348#if defined(JSON_HEDLEY_VERSION)
349 #undef JSON_HEDLEY_VERSION
350#endif
351#define JSON_HEDLEY_VERSION 15
352
353#if defined(JSON_HEDLEY_STRINGIFY_EX)
354 #undef JSON_HEDLEY_STRINGIFY_EX
355#endif
356#define JSON_HEDLEY_STRINGIFY_EX(x) #x
357
358#if defined(JSON_HEDLEY_STRINGIFY)
359 #undef JSON_HEDLEY_STRINGIFY
360#endif
361#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
362
363#if defined(JSON_HEDLEY_CONCAT_EX)
364 #undef JSON_HEDLEY_CONCAT_EX
365#endif
366#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
367
368#if defined(JSON_HEDLEY_CONCAT)
369 #undef JSON_HEDLEY_CONCAT
370#endif
371#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
372
373#if defined(JSON_HEDLEY_CONCAT3_EX)
374 #undef JSON_HEDLEY_CONCAT3_EX
375#endif
376#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
377
378#if defined(JSON_HEDLEY_CONCAT3)
379 #undef JSON_HEDLEY_CONCAT3
380#endif
381#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
382
383#if defined(JSON_HEDLEY_VERSION_ENCODE)
384 #undef JSON_HEDLEY_VERSION_ENCODE
385#endif
386#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
387
388#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
389 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
390#endif
391#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
392
393#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
394 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
395#endif
396#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
397
398#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
399 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
400#endif
401#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
402
403#if defined(JSON_HEDLEY_GNUC_VERSION)
404 #undef JSON_HEDLEY_GNUC_VERSION
405#endif
406#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
407 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
408#elif defined(__GNUC__)
409 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
410#endif
411
412#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
413 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
414#endif
415#if defined(JSON_HEDLEY_GNUC_VERSION)
416 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
417#else
418 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
419#endif
420
421#if defined(JSON_HEDLEY_MSVC_VERSION)
422 #undef JSON_HEDLEY_MSVC_VERSION
423#endif
424#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
425 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
426#elif defined(_MSC_FULL_VER) && !defined(__ICL)
427 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
428#elif defined(_MSC_VER) && !defined(__ICL)
429 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
430#endif
431
432#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
433 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
434#endif
435#if !defined(JSON_HEDLEY_MSVC_VERSION)
436 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
437#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
438 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
439#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
440 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
441#else
442 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
443#endif
444
445#if defined(JSON_HEDLEY_INTEL_VERSION)
446 #undef JSON_HEDLEY_INTEL_VERSION
447#endif
448#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
449 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
450#elif defined(__INTEL_COMPILER) && !defined(__ICL)
451 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
452#endif
453
454#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
455 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
456#endif
457#if defined(JSON_HEDLEY_INTEL_VERSION)
458 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
459#else
460 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
461#endif
462
463#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
464 #undef JSON_HEDLEY_INTEL_CL_VERSION
465#endif
466#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
467 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
468#endif
469
470#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
471 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
472#endif
473#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
474 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
475#else
476 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
477#endif
478
479#if defined(JSON_HEDLEY_PGI_VERSION)
480 #undef JSON_HEDLEY_PGI_VERSION
481#endif
482#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
483 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
484#endif
485
486#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
487 #undef JSON_HEDLEY_PGI_VERSION_CHECK
488#endif
489#if defined(JSON_HEDLEY_PGI_VERSION)
490 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
491#else
492 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
493#endif
494
495#if defined(JSON_HEDLEY_SUNPRO_VERSION)
496 #undef JSON_HEDLEY_SUNPRO_VERSION
497#endif
498#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
499 #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)
500#elif defined(__SUNPRO_C)
501 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
502#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
503 #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)
504#elif defined(__SUNPRO_CC)
505 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
506#endif
507
508#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
509 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
510#endif
511#if defined(JSON_HEDLEY_SUNPRO_VERSION)
512 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
513#else
514 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
515#endif
516
517#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
518 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
519#endif
520#if defined(__EMSCRIPTEN__)
521 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
522#endif
523
524#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
525 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
526#endif
527#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
528 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
529#else
530 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
531#endif
532
533#if defined(JSON_HEDLEY_ARM_VERSION)
534 #undef JSON_HEDLEY_ARM_VERSION
535#endif
536#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
537 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
538#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
539 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
540#endif
541
542#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
543 #undef JSON_HEDLEY_ARM_VERSION_CHECK
544#endif
545#if defined(JSON_HEDLEY_ARM_VERSION)
546 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
547#else
548 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
549#endif
550
551#if defined(JSON_HEDLEY_IBM_VERSION)
552 #undef JSON_HEDLEY_IBM_VERSION
553#endif
554#if defined(__ibmxl__)
555 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
556#elif defined(__xlC__) && defined(__xlC_ver__)
557 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
558#elif defined(__xlC__)
559 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
560#endif
561
562#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
563 #undef JSON_HEDLEY_IBM_VERSION_CHECK
564#endif
565#if defined(JSON_HEDLEY_IBM_VERSION)
566 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
567#else
568 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
569#endif
570
571#if defined(JSON_HEDLEY_TI_VERSION)
572 #undef JSON_HEDLEY_TI_VERSION
573#endif
574#if \
575 defined(__TI_COMPILER_VERSION__) && \
576 ( \
577 defined(__TMS470__) || defined(__TI_ARM__) || \
578 defined(__MSP430__) || \
579 defined(__TMS320C2000__) \
580 )
581#if (__TI_COMPILER_VERSION__ >= 16000000)
582 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
583#endif
584#endif
585
586#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
587 #undef JSON_HEDLEY_TI_VERSION_CHECK
588#endif
589#if defined(JSON_HEDLEY_TI_VERSION)
590 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
591#else
592 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
593#endif
594
595#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
596 #undef JSON_HEDLEY_TI_CL2000_VERSION
597#endif
598#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
599 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
600#endif
601
602#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
603 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
604#endif
605#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
606 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
607#else
608 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
609#endif
610
611#if defined(JSON_HEDLEY_TI_CL430_VERSION)
612 #undef JSON_HEDLEY_TI_CL430_VERSION
613#endif
614#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
615 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
616#endif
617
618#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
619 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
620#endif
621#if defined(JSON_HEDLEY_TI_CL430_VERSION)
622 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
623#else
624 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
625#endif
626
627#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
628 #undef JSON_HEDLEY_TI_ARMCL_VERSION
629#endif
630#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
631 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
632#endif
633
634#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
635 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
636#endif
637#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
638 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
639#else
640 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
641#endif
642
643#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
644 #undef JSON_HEDLEY_TI_CL6X_VERSION
645#endif
646#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
647 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
648#endif
649
650#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
651 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
652#endif
653#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
654 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
655#else
656 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
657#endif
658
659#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
660 #undef JSON_HEDLEY_TI_CL7X_VERSION
661#endif
662#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
663 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
664#endif
665
666#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
667 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
668#endif
669#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
670 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
671#else
672 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
673#endif
674
675#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
676 #undef JSON_HEDLEY_TI_CLPRU_VERSION
677#endif
678#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
679 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
680#endif
681
682#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
683 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
684#endif
685#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
686 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
687#else
688 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
689#endif
690
691#if defined(JSON_HEDLEY_CRAY_VERSION)
692 #undef JSON_HEDLEY_CRAY_VERSION
693#endif
694#if defined(_CRAYC)
695 #if defined(_RELEASE_PATCHLEVEL)
696 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
697 #else
698 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
699 #endif
700#endif
701
702#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
703 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
704#endif
705#if defined(JSON_HEDLEY_CRAY_VERSION)
706 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
707#else
708 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
709#endif
710
711#if defined(JSON_HEDLEY_IAR_VERSION)
712 #undef JSON_HEDLEY_IAR_VERSION
713#endif
714#if defined(__IAR_SYSTEMS_ICC__)
715 #if __VER__ > 1000
716 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
717 #else
718 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
719 #endif
720#endif
721
722#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
723 #undef JSON_HEDLEY_IAR_VERSION_CHECK
724#endif
725#if defined(JSON_HEDLEY_IAR_VERSION)
726 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
727#else
728 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
729#endif
730
731#if defined(JSON_HEDLEY_TINYC_VERSION)
732 #undef JSON_HEDLEY_TINYC_VERSION
733#endif
734#if defined(__TINYC__)
735 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
736#endif
737
738#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
739 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
740#endif
741#if defined(JSON_HEDLEY_TINYC_VERSION)
742 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
743#else
744 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
745#endif
746
747#if defined(JSON_HEDLEY_DMC_VERSION)
748 #undef JSON_HEDLEY_DMC_VERSION
749#endif
750#if defined(__DMC__)
751 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
752#endif
753
754#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
755 #undef JSON_HEDLEY_DMC_VERSION_CHECK
756#endif
757#if defined(JSON_HEDLEY_DMC_VERSION)
758 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
759#else
760 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
761#endif
762
763#if defined(JSON_HEDLEY_COMPCERT_VERSION)
764 #undef JSON_HEDLEY_COMPCERT_VERSION
765#endif
766#if defined(__COMPCERT_VERSION__)
767 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
768#endif
769
770#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
771 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
772#endif
773#if defined(JSON_HEDLEY_COMPCERT_VERSION)
774 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
775#else
776 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
777#endif
778
779#if defined(JSON_HEDLEY_PELLES_VERSION)
780 #undef JSON_HEDLEY_PELLES_VERSION
781#endif
782#if defined(__POCC__)
783 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
784#endif
785
786#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
787 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
788#endif
789#if defined(JSON_HEDLEY_PELLES_VERSION)
790 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
791#else
792 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
793#endif
794
795#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
796 #undef JSON_HEDLEY_MCST_LCC_VERSION
797#endif
798#if defined(__LCC__) && defined(__LCC_MINOR__)
799 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
800#endif
801
802#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
803 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
804#endif
805#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
806 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
807#else
808 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
809#endif
810
811#if defined(JSON_HEDLEY_GCC_VERSION)
812 #undef JSON_HEDLEY_GCC_VERSION
813#endif
814#if \
815 defined(JSON_HEDLEY_GNUC_VERSION) && \
816 !defined(__clang__) && \
817 !defined(JSON_HEDLEY_INTEL_VERSION) && \
818 !defined(JSON_HEDLEY_PGI_VERSION) && \
819 !defined(JSON_HEDLEY_ARM_VERSION) && \
820 !defined(JSON_HEDLEY_CRAY_VERSION) && \
821 !defined(JSON_HEDLEY_TI_VERSION) && \
822 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
823 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
824 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
825 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
826 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
827 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
828 !defined(__COMPCERT__) && \
829 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
830 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
831#endif
832
833#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
834 #undef JSON_HEDLEY_GCC_VERSION_CHECK
835#endif
836#if defined(JSON_HEDLEY_GCC_VERSION)
837 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
838#else
839 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
840#endif
841
842#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
843 #undef JSON_HEDLEY_HAS_ATTRIBUTE
844#endif
845#if \
846 defined(__has_attribute) && \
847 ( \
848 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
849 )
850# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
851#else
852# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
853#endif
854
855#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
856 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
857#endif
858#if defined(__has_attribute)
859 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
860#else
861 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
862#endif
863
864#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
865 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
866#endif
867#if defined(__has_attribute)
868 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
869#else
870 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
871#endif
872
873#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
874 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
875#endif
876#if \
877 defined(__has_cpp_attribute) && \
878 defined(__cplusplus) && \
879 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
880 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
881#else
882 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
883#endif
884
885#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
886 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
887#endif
888#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
889 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
890#elif \
891 !defined(JSON_HEDLEY_PGI_VERSION) && \
892 !defined(JSON_HEDLEY_IAR_VERSION) && \
893 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
894 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
895 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
896#else
897 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
898#endif
899
900#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
901 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
902#endif
903#if defined(__has_cpp_attribute) && defined(__cplusplus)
904 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
905#else
906 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
907#endif
908
909#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
910 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
911#endif
912#if defined(__has_cpp_attribute) && defined(__cplusplus)
913 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
914#else
915 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
916#endif
917
918#if defined(JSON_HEDLEY_HAS_BUILTIN)
919 #undef JSON_HEDLEY_HAS_BUILTIN
920#endif
921#if defined(__has_builtin)
922 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
923#else
924 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
925#endif
926
927#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
928 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
929#endif
930#if defined(__has_builtin)
931 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
932#else
933 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
934#endif
935
936#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
937 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
938#endif
939#if defined(__has_builtin)
940 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
941#else
942 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
943#endif
944
945#if defined(JSON_HEDLEY_HAS_FEATURE)
946 #undef JSON_HEDLEY_HAS_FEATURE
947#endif
948#if defined(__has_feature)
949 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
950#else
951 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
952#endif
953
954#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
955 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
956#endif
957#if defined(__has_feature)
958 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
959#else
960 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
961#endif
962
963#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
964 #undef JSON_HEDLEY_GCC_HAS_FEATURE
965#endif
966#if defined(__has_feature)
967 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
968#else
969 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
970#endif
971
972#if defined(JSON_HEDLEY_HAS_EXTENSION)
973 #undef JSON_HEDLEY_HAS_EXTENSION
974#endif
975#if defined(__has_extension)
976 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
977#else
978 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
979#endif
980
981#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
982 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
983#endif
984#if defined(__has_extension)
985 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
986#else
987 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
988#endif
989
990#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
991 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
992#endif
993#if defined(__has_extension)
994 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
995#else
996 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
997#endif
998
999#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
1000 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
1001#endif
1002#if defined(__has_declspec_attribute)
1003 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
1004#else
1005 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
1006#endif
1007
1008#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1009 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1010#endif
1011#if defined(__has_declspec_attribute)
1012 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1013#else
1014 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1015#endif
1016
1017#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1018 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1019#endif
1020#if defined(__has_declspec_attribute)
1021 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1022#else
1023 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1024#endif
1025
1026#if defined(JSON_HEDLEY_HAS_WARNING)
1027 #undef JSON_HEDLEY_HAS_WARNING
1028#endif
1029#if defined(__has_warning)
1030 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1031#else
1032 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1033#endif
1034
1035#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1036 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1037#endif
1038#if defined(__has_warning)
1039 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1040#else
1041 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1042#endif
1043
1044#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1045 #undef JSON_HEDLEY_GCC_HAS_WARNING
1046#endif
1047#if defined(__has_warning)
1048 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1049#else
1050 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1051#endif
1052
1053#if \
1054 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1055 defined(__clang__) || \
1056 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1057 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1058 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1059 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1060 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1061 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1062 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1063 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1064 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1065 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1066 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1067 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1068 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1069 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1070 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1071 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1072 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1073#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1074 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1075#else
1076 #define JSON_HEDLEY_PRAGMA(value)
1077#endif
1078
1079#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1080 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1081#endif
1082#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1083 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1084#endif
1085#if defined(__clang__)
1086 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1087 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1088#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1089 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1090 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1091#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1092 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1093 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1094#elif \
1095 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1096 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1097 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1098 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1099#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1100 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1101 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1102#elif \
1103 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1104 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1105 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1106 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1107 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1108 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1109 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1110 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1111#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1112 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1113 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1114#else
1115 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1116 #define JSON_HEDLEY_DIAGNOSTIC_POP
1117#endif
1118
1119/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1120 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1121#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1122 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1123#endif
1124#if defined(__cplusplus)
1125# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1126# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1127# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1128# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1129 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1130 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1131 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1132 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1133 xpr \
1134 JSON_HEDLEY_DIAGNOSTIC_POP
1135# else
1136# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1137 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1138 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1139 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1140 xpr \
1141 JSON_HEDLEY_DIAGNOSTIC_POP
1142# endif
1143# else
1144# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1145 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1146 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1147 xpr \
1148 JSON_HEDLEY_DIAGNOSTIC_POP
1149# endif
1150# endif
1151#endif
1152#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1153 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1154#endif
1155
1156#if defined(JSON_HEDLEY_CONST_CAST)
1157 #undef JSON_HEDLEY_CONST_CAST
1158#endif
1159#if defined(__cplusplus)
1160# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1161#elif \
1162 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1163 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1164 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1165# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1166 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1167 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1168 ((T) (expr)); \
1169 JSON_HEDLEY_DIAGNOSTIC_POP \
1170 }))
1171#else
1172# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1173#endif
1174
1175#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1176 #undef JSON_HEDLEY_REINTERPRET_CAST
1177#endif
1178#if defined(__cplusplus)
1179 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1180#else
1181 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1182#endif
1183
1184#if defined(JSON_HEDLEY_STATIC_CAST)
1185 #undef JSON_HEDLEY_STATIC_CAST
1186#endif
1187#if defined(__cplusplus)
1188 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1189#else
1190 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1191#endif
1192
1193#if defined(JSON_HEDLEY_CPP_CAST)
1194 #undef JSON_HEDLEY_CPP_CAST
1195#endif
1196#if defined(__cplusplus)
1197# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1198# define JSON_HEDLEY_CPP_CAST(T, expr) \
1199 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1200 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1201 ((T) (expr)) \
1202 JSON_HEDLEY_DIAGNOSTIC_POP
1203# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1204# define JSON_HEDLEY_CPP_CAST(T, expr) \
1205 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1206 _Pragma("diag_suppress=Pe137") \
1207 JSON_HEDLEY_DIAGNOSTIC_POP
1208# else
1209# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1210# endif
1211#else
1212# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1213#endif
1214
1215#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1216 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1217#endif
1218#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1219 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1220#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1221 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1222#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1223 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1224#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1225 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1226#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1227 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1228#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1229 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1230#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1231 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1232#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1233 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1234#elif \
1235 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1236 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1237 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1238 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1239 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1240 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1241 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1242 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1243 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1244 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1245 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1246 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1247#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1248 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1249#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1250 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1251#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1252 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1253#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1254 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1255#else
1256 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1257#endif
1258
1259#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1260 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1261#endif
1262#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1263 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1264#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1265 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1266#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1267 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1268#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1269 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1270#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1271 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1272#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1273 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1274#elif \
1275 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1276 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1277 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1278 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1279 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1280#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1281 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1282#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1283 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1284#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1285 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1286#else
1287 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1288#endif
1289
1290#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1291 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1292#endif
1293#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1294 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1295#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1296 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1297#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1298 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1299#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1300 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1301#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1302 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1303#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1304 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1305#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1306 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1307#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1308 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1309#elif \
1310 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1311 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1312 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1313 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1314#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1315 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1316#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1317 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1318#else
1319 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1320#endif
1321
1322#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1323 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1324#endif
1325#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1326 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1327#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1328 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1329#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1330 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1331#else
1332 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1333#endif
1334
1335#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1336 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1337#endif
1338#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1339 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1340#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1341 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1342#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1343 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1344#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1345 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1346#else
1347 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1348#endif
1349
1350#if defined(JSON_HEDLEY_DEPRECATED)
1351 #undef JSON_HEDLEY_DEPRECATED
1352#endif
1353#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1354 #undef JSON_HEDLEY_DEPRECATED_FOR
1355#endif
1356#if \
1357 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1358 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1359 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1360 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1361#elif \
1362 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1363 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1364 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1365 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1366 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1367 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1368 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1369 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1370 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1371 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1372 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1373 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1374 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1375 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1376#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1377 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1378 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1379#elif \
1380 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1381 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1382 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1383 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1384 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1385 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1386 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1387 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1388 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1389 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1390 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1391 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1392 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1393 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1394 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1395 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1396 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1397 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1398#elif \
1399 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1400 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1401 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1402 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1403 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1404#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1405 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1406 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1407#else
1408 #define JSON_HEDLEY_DEPRECATED(since)
1409 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1410#endif
1411
1412#if defined(JSON_HEDLEY_UNAVAILABLE)
1413 #undef JSON_HEDLEY_UNAVAILABLE
1414#endif
1415#if \
1416 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1417 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1418 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1419 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1420 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1421#else
1422 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1423#endif
1424
1425#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1426 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1427#endif
1428#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1429 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1430#endif
1431#if \
1432 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1433 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1434 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1435 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1436 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1437 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1438 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1439 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1440 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1441 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1442 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1443 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1444 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1445 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1446 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1447 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1448 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1449 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1450 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1451#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1452 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1453 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1454#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1455 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1456 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1457#elif defined(_Check_return_) /* SAL */
1458 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1459 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1460#else
1461 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1462 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1463#endif
1464
1465#if defined(JSON_HEDLEY_SENTINEL)
1466 #undef JSON_HEDLEY_SENTINEL
1467#endif
1468#if \
1469 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1470 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1471 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1472 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1473 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1474 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1475#else
1476 #define JSON_HEDLEY_SENTINEL(position)
1477#endif
1478
1479#if defined(JSON_HEDLEY_NO_RETURN)
1480 #undef JSON_HEDLEY_NO_RETURN
1481#endif
1482#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1483 #define JSON_HEDLEY_NO_RETURN __noreturn
1484#elif \
1485 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1486 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1487 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1488#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1489 #define JSON_HEDLEY_NO_RETURN _Noreturn
1490#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1491 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1492#elif \
1493 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1494 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1495 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1496 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1497 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1498 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1499 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1500 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1501 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1502 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1503 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1504 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1505 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1506 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1507 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1508 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1509 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1510 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1511#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1512 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1513#elif \
1514 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1515 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1516 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1517#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1518 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1519#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1520 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1521#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1522 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1523#else
1524 #define JSON_HEDLEY_NO_RETURN
1525#endif
1526
1527#if defined(JSON_HEDLEY_NO_ESCAPE)
1528 #undef JSON_HEDLEY_NO_ESCAPE
1529#endif
1530#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1531 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1532#else
1533 #define JSON_HEDLEY_NO_ESCAPE
1534#endif
1535
1536#if defined(JSON_HEDLEY_UNREACHABLE)
1537 #undef JSON_HEDLEY_UNREACHABLE
1538#endif
1539#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1540 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1541#endif
1542#if defined(JSON_HEDLEY_ASSUME)
1543 #undef JSON_HEDLEY_ASSUME
1544#endif
1545#if \
1546 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1547 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1548 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1549 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1550#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1551 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1552#elif \
1553 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1554 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1555 #if defined(__cplusplus)
1556 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1557 #else
1558 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1559 #endif
1560#endif
1561#if \
1562 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1563 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1564 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1565 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1566 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1567 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1568 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1569 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1570#elif defined(JSON_HEDLEY_ASSUME)
1571 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1572#endif
1573#if !defined(JSON_HEDLEY_ASSUME)
1574 #if defined(JSON_HEDLEY_UNREACHABLE)
1575 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1576 #else
1577 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1578 #endif
1579#endif
1580#if defined(JSON_HEDLEY_UNREACHABLE)
1581 #if \
1582 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1583 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1584 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1585 #else
1586 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1587 #endif
1588#else
1589 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1590#endif
1591#if !defined(JSON_HEDLEY_UNREACHABLE)
1592 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1593#endif
1594
1596#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1597 #pragma clang diagnostic ignored "-Wpedantic"
1598#endif
1599#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1600 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1601#endif
1602#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1603 #if defined(__clang__)
1604 #pragma clang diagnostic ignored "-Wvariadic-macros"
1605 #elif defined(JSON_HEDLEY_GCC_VERSION)
1606 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1607 #endif
1608#endif
1609#if defined(JSON_HEDLEY_NON_NULL)
1610 #undef JSON_HEDLEY_NON_NULL
1611#endif
1612#if \
1613 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1614 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1615 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1616 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1617 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1618#else
1619 #define JSON_HEDLEY_NON_NULL(...)
1620#endif
1622
1623#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1624 #undef JSON_HEDLEY_PRINTF_FORMAT
1625#endif
1626#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1627 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1628#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1629 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1630#elif \
1631 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1632 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1633 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1634 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1635 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1636 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1637 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1638 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1639 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1640 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1641 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1642 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1643 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1644 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1645 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1646 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1647 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1648 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1649#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1650 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1651#else
1652 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1653#endif
1654
1655#if defined(JSON_HEDLEY_CONSTEXPR)
1656 #undef JSON_HEDLEY_CONSTEXPR
1657#endif
1658#if defined(__cplusplus)
1659 #if __cplusplus >= 201103L
1660 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1661 #endif
1662#endif
1663#if !defined(JSON_HEDLEY_CONSTEXPR)
1664 #define JSON_HEDLEY_CONSTEXPR
1665#endif
1666
1667#if defined(JSON_HEDLEY_PREDICT)
1668 #undef JSON_HEDLEY_PREDICT
1669#endif
1670#if defined(JSON_HEDLEY_LIKELY)
1671 #undef JSON_HEDLEY_LIKELY
1672#endif
1673#if defined(JSON_HEDLEY_UNLIKELY)
1674 #undef JSON_HEDLEY_UNLIKELY
1675#endif
1676#if defined(JSON_HEDLEY_UNPREDICTABLE)
1677 #undef JSON_HEDLEY_UNPREDICTABLE
1678#endif
1679#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1680 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1681#endif
1682#if \
1683 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1684 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1685 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1686# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1687# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1688# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1689# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1690# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1691#elif \
1692 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1693 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1694 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1695 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1696 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1697 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1698 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1699 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1700 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1701 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1702 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1703 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1704 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1705 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1706 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1707 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1708# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1709 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1710# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1711 (__extension__ ({ \
1712 double hedley_probability_ = (probability); \
1713 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1714 }))
1715# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1716 (__extension__ ({ \
1717 double hedley_probability_ = (probability); \
1718 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1719 }))
1720# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1721# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1722#else
1723# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1724# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1725# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1726# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1727# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1728#endif
1729#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1730 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1731#endif
1732
1733#if defined(JSON_HEDLEY_MALLOC)
1734 #undef JSON_HEDLEY_MALLOC
1735#endif
1736#if \
1737 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1738 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1739 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1740 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1741 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1742 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1743 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1744 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1745 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1746 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1747 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1748 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1749 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1750 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1751 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1752 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1753 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1754 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1755 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1756#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1757 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1758#elif \
1759 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1760 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1761 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1762#else
1763 #define JSON_HEDLEY_MALLOC
1764#endif
1765
1766#if defined(JSON_HEDLEY_PURE)
1767 #undef JSON_HEDLEY_PURE
1768#endif
1769#if \
1770 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1771 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1772 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1773 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1774 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1775 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1776 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1777 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1778 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1779 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1780 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1781 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1782 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1783 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1784 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1785 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1786 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1787 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1788 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1789# define JSON_HEDLEY_PURE __attribute__((__pure__))
1790#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1791# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1792#elif defined(__cplusplus) && \
1793 ( \
1794 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1795 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1796 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1797 )
1798# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1799#else
1800# define JSON_HEDLEY_PURE
1801#endif
1802
1803#if defined(JSON_HEDLEY_CONST)
1804 #undef JSON_HEDLEY_CONST
1805#endif
1806#if \
1807 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1808 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1809 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1810 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1811 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1812 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1813 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1814 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1815 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1816 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1817 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1818 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1819 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1820 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1821 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1822 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1823 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1824 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1825 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1826 #define JSON_HEDLEY_CONST __attribute__((__const__))
1827#elif \
1828 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1829 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1830#else
1831 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1832#endif
1833
1834#if defined(JSON_HEDLEY_RESTRICT)
1835 #undef JSON_HEDLEY_RESTRICT
1836#endif
1837#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1838 #define JSON_HEDLEY_RESTRICT restrict
1839#elif \
1840 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1841 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1842 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1843 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1844 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1845 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1846 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1847 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1848 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1849 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1850 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1851 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1852 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1853 defined(__clang__) || \
1854 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1855 #define JSON_HEDLEY_RESTRICT __restrict
1856#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1857 #define JSON_HEDLEY_RESTRICT _Restrict
1858#else
1859 #define JSON_HEDLEY_RESTRICT
1860#endif
1861
1862#if defined(JSON_HEDLEY_INLINE)
1863 #undef JSON_HEDLEY_INLINE
1864#endif
1865#if \
1866 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1867 (defined(__cplusplus) && (__cplusplus >= 199711L))
1868 #define JSON_HEDLEY_INLINE inline
1869#elif \
1870 defined(JSON_HEDLEY_GCC_VERSION) || \
1871 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1872 #define JSON_HEDLEY_INLINE __inline__
1873#elif \
1874 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1875 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1876 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1877 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1878 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1879 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1880 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1881 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1882 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1883 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1884 #define JSON_HEDLEY_INLINE __inline
1885#else
1886 #define JSON_HEDLEY_INLINE
1887#endif
1888
1889#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1890 #undef JSON_HEDLEY_ALWAYS_INLINE
1891#endif
1892#if \
1893 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1894 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1895 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1896 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1897 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1898 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1899 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1900 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1901 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1902 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1903 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1904 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1905 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1906 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1907 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1908 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1909 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1910 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1911 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1912# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1913#elif \
1914 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1915 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1916# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1917#elif defined(__cplusplus) && \
1918 ( \
1919 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1920 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1921 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1922 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1923 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1924 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1925 )
1926# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1927#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1928# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1929#else
1930# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1931#endif
1932
1933#if defined(JSON_HEDLEY_NEVER_INLINE)
1934 #undef JSON_HEDLEY_NEVER_INLINE
1935#endif
1936#if \
1937 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1938 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1939 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1940 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1941 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1942 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1943 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1944 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1945 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1946 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1947 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1948 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1949 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1950 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1951 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1952 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1953 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1954 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1955 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1956 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1957#elif \
1958 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1959 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1960 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1961#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1962 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1963#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1964 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1965#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1966 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1967#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1968 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1969#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1970 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1971#else
1972 #define JSON_HEDLEY_NEVER_INLINE
1973#endif
1974
1975#if defined(JSON_HEDLEY_PRIVATE)
1976 #undef JSON_HEDLEY_PRIVATE
1977#endif
1978#if defined(JSON_HEDLEY_PUBLIC)
1979 #undef JSON_HEDLEY_PUBLIC
1980#endif
1981#if defined(JSON_HEDLEY_IMPORT)
1982 #undef JSON_HEDLEY_IMPORT
1983#endif
1984#if defined(_WIN32) || defined(__CYGWIN__)
1985# define JSON_HEDLEY_PRIVATE
1986# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1987# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1988#else
1989# if \
1990 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1991 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1992 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1993 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1994 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1995 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1996 ( \
1997 defined(__TI_EABI__) && \
1998 ( \
1999 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
2000 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
2001 ) \
2002 ) || \
2003 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2004# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
2005# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
2006# else
2007# define JSON_HEDLEY_PRIVATE
2008# define JSON_HEDLEY_PUBLIC
2009# endif
2010# define JSON_HEDLEY_IMPORT extern
2011#endif
2012
2013#if defined(JSON_HEDLEY_NO_THROW)
2014 #undef JSON_HEDLEY_NO_THROW
2015#endif
2016#if \
2017 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2018 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2019 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2020 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2021 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2022#elif \
2023 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2024 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2025 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2026 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2027#else
2028 #define JSON_HEDLEY_NO_THROW
2029#endif
2030
2031#if defined(JSON_HEDLEY_FALL_THROUGH)
2032 #undef JSON_HEDLEY_FALL_THROUGH
2033#endif
2034#if \
2035 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2036 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2037 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2038 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2039#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2040 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2041#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2042 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2043#elif defined(__fallthrough) /* SAL */
2044 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2045#else
2046 #define JSON_HEDLEY_FALL_THROUGH
2047#endif
2048
2049#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2050 #undef JSON_HEDLEY_RETURNS_NON_NULL
2051#endif
2052#if \
2053 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2054 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2055 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2056 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2057#elif defined(_Ret_notnull_) /* SAL */
2058 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2059#else
2060 #define JSON_HEDLEY_RETURNS_NON_NULL
2061#endif
2062
2063#if defined(JSON_HEDLEY_ARRAY_PARAM)
2064 #undef JSON_HEDLEY_ARRAY_PARAM
2065#endif
2066#if \
2067 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2068 !defined(__STDC_NO_VLA__) && \
2069 !defined(__cplusplus) && \
2070 !defined(JSON_HEDLEY_PGI_VERSION) && \
2071 !defined(JSON_HEDLEY_TINYC_VERSION)
2072 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2073#else
2074 #define JSON_HEDLEY_ARRAY_PARAM(name)
2075#endif
2076
2077#if defined(JSON_HEDLEY_IS_CONSTANT)
2078 #undef JSON_HEDLEY_IS_CONSTANT
2079#endif
2080#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2081 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2082#endif
2083/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2084 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2085#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2086 #undef JSON_HEDLEY_IS_CONSTEXPR_
2087#endif
2088#if \
2089 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2090 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2091 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2092 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2093 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2094 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2095 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2096 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2097 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2098 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2099 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2100#endif
2101#if !defined(__cplusplus)
2102# if \
2103 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2104 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2105 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2106 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2107 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2108 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2109 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2110#if defined(__INTPTR_TYPE__)
2111 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2112#else
2113 #include <stdint.h>
2114 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2115#endif
2116# elif \
2117 ( \
2118 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2119 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2120 !defined(JSON_HEDLEY_PGI_VERSION) && \
2121 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2122 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2123 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2124 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2125 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2126 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2127#if defined(__INTPTR_TYPE__)
2128 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2129#else
2130 #include <stdint.h>
2131 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2132#endif
2133# elif \
2134 defined(JSON_HEDLEY_GCC_VERSION) || \
2135 defined(JSON_HEDLEY_INTEL_VERSION) || \
2136 defined(JSON_HEDLEY_TINYC_VERSION) || \
2137 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2138 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2139 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2140 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2141 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2142 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2143 defined(__clang__)
2144# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2145 sizeof(void) != \
2146 sizeof(*( \
2147 1 ? \
2148 ((void*) ((expr) * 0L) ) : \
2149((struct { char v[sizeof(void) * 2]; } *) 1) \
2150 ) \
2151 ) \
2152 )
2153# endif
2154#endif
2155#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2156 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2157 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2158 #endif
2159 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2160#else
2161 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2162 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2163 #endif
2164 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2165#endif
2166
2167#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2168 #undef JSON_HEDLEY_BEGIN_C_DECLS
2169#endif
2170#if defined(JSON_HEDLEY_END_C_DECLS)
2171 #undef JSON_HEDLEY_END_C_DECLS
2172#endif
2173#if defined(JSON_HEDLEY_C_DECL)
2174 #undef JSON_HEDLEY_C_DECL
2175#endif
2176#if defined(__cplusplus)
2177 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2178 #define JSON_HEDLEY_END_C_DECLS }
2179 #define JSON_HEDLEY_C_DECL extern "C"
2180#else
2181 #define JSON_HEDLEY_BEGIN_C_DECLS
2182 #define JSON_HEDLEY_END_C_DECLS
2183 #define JSON_HEDLEY_C_DECL
2184#endif
2185
2186#if defined(JSON_HEDLEY_STATIC_ASSERT)
2187 #undef JSON_HEDLEY_STATIC_ASSERT
2188#endif
2189#if \
2190 !defined(__cplusplus) && ( \
2191 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2192 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2193 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2194 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2195 defined(_Static_assert) \
2196 )
2197# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2198#elif \
2199 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2200 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2201 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2202# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2203#else
2204# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2205#endif
2206
2207#if defined(JSON_HEDLEY_NULL)
2208 #undef JSON_HEDLEY_NULL
2209#endif
2210#if defined(__cplusplus)
2211 #if __cplusplus >= 201103L
2212 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2213 #elif defined(NULL)
2214 #define JSON_HEDLEY_NULL NULL
2215 #else
2216 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2217 #endif
2218#elif defined(NULL)
2219 #define JSON_HEDLEY_NULL NULL
2220#else
2221 #define JSON_HEDLEY_NULL ((void*) 0)
2222#endif
2223
2224#if defined(JSON_HEDLEY_MESSAGE)
2225 #undef JSON_HEDLEY_MESSAGE
2226#endif
2227#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2228# define JSON_HEDLEY_MESSAGE(msg) \
2229 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2230 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2231 JSON_HEDLEY_PRAGMA(message msg) \
2232 JSON_HEDLEY_DIAGNOSTIC_POP
2233#elif \
2234 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2235 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2236# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2237#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2238# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2239#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2240# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2241#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2242# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2243#else
2244# define JSON_HEDLEY_MESSAGE(msg)
2245#endif
2246
2247#if defined(JSON_HEDLEY_WARNING)
2248 #undef JSON_HEDLEY_WARNING
2249#endif
2250#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2251# define JSON_HEDLEY_WARNING(msg) \
2252 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2253 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2254 JSON_HEDLEY_PRAGMA(clang warning msg) \
2255 JSON_HEDLEY_DIAGNOSTIC_POP
2256#elif \
2257 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2258 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2259 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2260# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2261#elif \
2262 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2263 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2264# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2265#else
2266# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2267#endif
2268
2269#if defined(JSON_HEDLEY_REQUIRE)
2270 #undef JSON_HEDLEY_REQUIRE
2271#endif
2272#if defined(JSON_HEDLEY_REQUIRE_MSG)
2273 #undef JSON_HEDLEY_REQUIRE_MSG
2274#endif
2275#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2276# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2277# define JSON_HEDLEY_REQUIRE(expr) \
2278 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2279 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2280 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2281 JSON_HEDLEY_DIAGNOSTIC_POP
2282# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2283 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2284 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2285 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2286 JSON_HEDLEY_DIAGNOSTIC_POP
2287# else
2288# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2289# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2290# endif
2291#else
2292# define JSON_HEDLEY_REQUIRE(expr)
2293# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2294#endif
2295
2296#if defined(JSON_HEDLEY_FLAGS)
2297 #undef JSON_HEDLEY_FLAGS
2298#endif
2299#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2300 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2301#else
2302 #define JSON_HEDLEY_FLAGS
2303#endif
2304
2305#if defined(JSON_HEDLEY_FLAGS_CAST)
2306 #undef JSON_HEDLEY_FLAGS_CAST
2307#endif
2308#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2309# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2310 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2311 _Pragma("warning(disable:188)") \
2312 ((T) (expr)); \
2313 JSON_HEDLEY_DIAGNOSTIC_POP \
2314 }))
2315#else
2316# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2317#endif
2318
2319#if defined(JSON_HEDLEY_EMPTY_BASES)
2320 #undef JSON_HEDLEY_EMPTY_BASES
2321#endif
2322#if \
2323 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2324 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2325 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2326#else
2327 #define JSON_HEDLEY_EMPTY_BASES
2328#endif
2329
2330/* Remaining macros are deprecated. */
2331
2332#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2333 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2334#endif
2335#if defined(__clang__)
2336 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2337#else
2338 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2339#endif
2340
2341#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2342 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2343#endif
2344#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2345
2346#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2347 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2348#endif
2349#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2350
2351#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2352 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2353#endif
2354#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2355
2356#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2357 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2358#endif
2359#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2360
2361#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2362 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2363#endif
2364#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2365
2366#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2367 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2368#endif
2369#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2370
2371#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2372 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2373#endif
2374#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2375
2376#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2377
2378
2379// This file contains all internal macro definitions (except those affecting ABI)
2380// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2381
2382// #include <nlohmann/detail/abi_macros.hpp>
2383
2384
2385// exclude unsupported compilers
2386#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2387 #if defined(__clang__)
2388 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2389 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2390 #endif
2391 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2392 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2393 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2394 #endif
2395 #endif
2396#endif
2397
2398// C++ language standard detection
2399// if the user manually specified the used C++ version, this is skipped
2400#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)
2401 #if (defined(__cplusplus) && __cplusplus > 202302L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202302L)
2402 #define JSON_HAS_CPP_26
2403 #define JSON_HAS_CPP_23
2404 #define JSON_HAS_CPP_20
2405 #define JSON_HAS_CPP_17
2406 #define JSON_HAS_CPP_14
2407 #elif (defined(__cplusplus) && __cplusplus > 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L)
2408 #define JSON_HAS_CPP_23
2409 #define JSON_HAS_CPP_20
2410 #define JSON_HAS_CPP_17
2411 #define JSON_HAS_CPP_14
2412 #elif (defined(__cplusplus) && __cplusplus > 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L)
2413 #define JSON_HAS_CPP_20
2414 #define JSON_HAS_CPP_17
2415 #define JSON_HAS_CPP_14
2416 #elif (defined(__cplusplus) && __cplusplus > 201402L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2417 #define JSON_HAS_CPP_17
2418 #define JSON_HAS_CPP_14
2419 #elif (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2420 #define JSON_HAS_CPP_14
2421 #endif
2422 // the cpp 11 flag is always specified because it is the minimal required version
2423 #define JSON_HAS_CPP_11
2424#endif
2425
2426#ifdef __has_include
2427 #if __has_include(<version>)
2428 #include <version>
2429 #endif
2430#endif
2431
2432#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2433 #ifdef JSON_HAS_CPP_17
2434 #if defined(__cpp_lib_filesystem)
2435 #define JSON_HAS_FILESYSTEM 1
2436 #elif defined(__cpp_lib_experimental_filesystem)
2437 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2438 #elif !defined(__has_include)
2439 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2440 #elif __has_include(<filesystem>)
2441 #define JSON_HAS_FILESYSTEM 1
2442 #elif __has_include(<experimental/filesystem>)
2443 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2444 #endif
2445
2446 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2447 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2448 #undef JSON_HAS_FILESYSTEM
2449 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2450 #endif
2451
2452 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2453 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2454 #undef JSON_HAS_FILESYSTEM
2455 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2456 #endif
2457
2458 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2459 #if defined(__clang_major__) && __clang_major__ < 7
2460 #undef JSON_HAS_FILESYSTEM
2461 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2462 #endif
2463
2464 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2465 #if defined(_MSC_VER) && _MSC_VER < 1914
2466 #undef JSON_HAS_FILESYSTEM
2467 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2468 #endif
2469
2470 // no filesystem support before iOS 13
2471 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2472 #undef JSON_HAS_FILESYSTEM
2473 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2474 #endif
2475
2476 // no filesystem support before macOS Catalina
2477 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2478 #undef JSON_HAS_FILESYSTEM
2479 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2480 #endif
2481 #endif
2482#endif
2483
2484#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2485 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2486#endif
2487
2488#ifndef JSON_HAS_FILESYSTEM
2489 #define JSON_HAS_FILESYSTEM 0
2490#endif
2491
2492#ifndef JSON_HAS_THREE_WAY_COMPARISON
2493 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2494 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2495 #define JSON_HAS_THREE_WAY_COMPARISON 1
2496 #else
2497 #define JSON_HAS_THREE_WAY_COMPARISON 0
2498 #endif
2499#endif
2500
2501#ifndef JSON_HAS_RANGES
2502 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has a syntax error
2503 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2504 #define JSON_HAS_RANGES 0
2505 #elif defined(__cpp_lib_ranges)
2506 #define JSON_HAS_RANGES 1
2507 #else
2508 #define JSON_HAS_RANGES 0
2509 #endif
2510#endif
2511
2512#ifndef JSON_HAS_STATIC_RTTI
2513 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2514 #define JSON_HAS_STATIC_RTTI 1
2515 #else
2516 #define JSON_HAS_STATIC_RTTI 0
2517 #endif
2518#endif
2519
2520#ifdef JSON_HAS_CPP_17
2521 #define JSON_INLINE_VARIABLE inline
2522#else
2523 #define JSON_INLINE_VARIABLE
2524#endif
2525
2526#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2527 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2528#else
2529 #define JSON_NO_UNIQUE_ADDRESS
2530#endif
2531
2532// disable documentation warnings on clang
2533#if defined(__clang__)
2534 #pragma clang diagnostic push
2535 #pragma clang diagnostic ignored "-Wdocumentation"
2536 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2537#endif
2538
2539// allow disabling exceptions
2540#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2541 #define JSON_THROW(exception) throw exception
2542 #define JSON_TRY try
2543 #define JSON_CATCH(exception) catch(exception)
2544 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2545#else
2546 #include <cstdlib>
2547 #define JSON_THROW(exception) std::abort()
2548 #define JSON_TRY if(true)
2549 #define JSON_CATCH(exception) if(false)
2550 #define JSON_INTERNAL_CATCH(exception) if(false)
2551#endif
2552
2553// override exception macros
2554#if defined(JSON_THROW_USER)
2555 #undef JSON_THROW
2556 #define JSON_THROW JSON_THROW_USER
2557#endif
2558#if defined(JSON_TRY_USER)
2559 #undef JSON_TRY
2560 #define JSON_TRY JSON_TRY_USER
2561#endif
2562#if defined(JSON_CATCH_USER)
2563 #undef JSON_CATCH
2564 #define JSON_CATCH JSON_CATCH_USER
2565 #undef JSON_INTERNAL_CATCH
2566 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2567#endif
2568#if defined(JSON_INTERNAL_CATCH_USER)
2569 #undef JSON_INTERNAL_CATCH
2570 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2571#endif
2572
2573// allow overriding assert
2574#if !defined(JSON_ASSERT)
2575 #include <cassert> // assert
2576 #define JSON_ASSERT(x) assert(x)
2577#endif
2578
2579// allow accessing some private functions (needed by the test suite)
2580#if defined(JSON_TESTS_PRIVATE)
2581 #define JSON_PRIVATE_UNLESS_TESTED public
2582#else
2583 #define JSON_PRIVATE_UNLESS_TESTED private
2584#endif
2585
2586/*!
2587@brief macro to briefly define a mapping between an enum and JSON
2588@def NLOHMANN_JSON_SERIALIZE_ENUM
2589@since version 3.4.0
2590*/
2591#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2592 template<typename BasicJsonType> \
2593 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2594 { \
2595 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2596 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2597 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2598 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2599 auto it = std::find_if(std::begin(m), std::end(m), \
2600 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2601 { \
2602 return ej_pair.first == e; \
2603 }); \
2604 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2605 } \
2606 template<typename BasicJsonType> \
2607 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2608 { \
2609 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2610 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2611 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2612 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2613 auto it = std::find_if(std::begin(m), std::end(m), \
2614 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2615 { \
2616 return ej_pair.second == j; \
2617 }); \
2618 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2619 }
2620
2621// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2622// may be removed in the future once the class is split.
2623
2624#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2625 template<template<typename, typename, typename...> class ObjectType, \
2626 template<typename, typename...> class ArrayType, \
2627 class StringType, class BooleanType, class NumberIntegerType, \
2628 class NumberUnsignedType, class NumberFloatType, \
2629 template<typename> class AllocatorType, \
2630 template<typename, typename = void> class JSONSerializer, \
2631 class BinaryType, \
2632 class CustomBaseClass>
2633
2634#define NLOHMANN_BASIC_JSON_TPL \
2635 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2636 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2637 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2638
2639// Macros to simplify conversion from/to types
2640
2641#define NLOHMANN_JSON_EXPAND( x ) x
2642#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
2643#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2644 NLOHMANN_JSON_PASTE64, \
2645 NLOHMANN_JSON_PASTE63, \
2646 NLOHMANN_JSON_PASTE62, \
2647 NLOHMANN_JSON_PASTE61, \
2648 NLOHMANN_JSON_PASTE60, \
2649 NLOHMANN_JSON_PASTE59, \
2650 NLOHMANN_JSON_PASTE58, \
2651 NLOHMANN_JSON_PASTE57, \
2652 NLOHMANN_JSON_PASTE56, \
2653 NLOHMANN_JSON_PASTE55, \
2654 NLOHMANN_JSON_PASTE54, \
2655 NLOHMANN_JSON_PASTE53, \
2656 NLOHMANN_JSON_PASTE52, \
2657 NLOHMANN_JSON_PASTE51, \
2658 NLOHMANN_JSON_PASTE50, \
2659 NLOHMANN_JSON_PASTE49, \
2660 NLOHMANN_JSON_PASTE48, \
2661 NLOHMANN_JSON_PASTE47, \
2662 NLOHMANN_JSON_PASTE46, \
2663 NLOHMANN_JSON_PASTE45, \
2664 NLOHMANN_JSON_PASTE44, \
2665 NLOHMANN_JSON_PASTE43, \
2666 NLOHMANN_JSON_PASTE42, \
2667 NLOHMANN_JSON_PASTE41, \
2668 NLOHMANN_JSON_PASTE40, \
2669 NLOHMANN_JSON_PASTE39, \
2670 NLOHMANN_JSON_PASTE38, \
2671 NLOHMANN_JSON_PASTE37, \
2672 NLOHMANN_JSON_PASTE36, \
2673 NLOHMANN_JSON_PASTE35, \
2674 NLOHMANN_JSON_PASTE34, \
2675 NLOHMANN_JSON_PASTE33, \
2676 NLOHMANN_JSON_PASTE32, \
2677 NLOHMANN_JSON_PASTE31, \
2678 NLOHMANN_JSON_PASTE30, \
2679 NLOHMANN_JSON_PASTE29, \
2680 NLOHMANN_JSON_PASTE28, \
2681 NLOHMANN_JSON_PASTE27, \
2682 NLOHMANN_JSON_PASTE26, \
2683 NLOHMANN_JSON_PASTE25, \
2684 NLOHMANN_JSON_PASTE24, \
2685 NLOHMANN_JSON_PASTE23, \
2686 NLOHMANN_JSON_PASTE22, \
2687 NLOHMANN_JSON_PASTE21, \
2688 NLOHMANN_JSON_PASTE20, \
2689 NLOHMANN_JSON_PASTE19, \
2690 NLOHMANN_JSON_PASTE18, \
2691 NLOHMANN_JSON_PASTE17, \
2692 NLOHMANN_JSON_PASTE16, \
2693 NLOHMANN_JSON_PASTE15, \
2694 NLOHMANN_JSON_PASTE14, \
2695 NLOHMANN_JSON_PASTE13, \
2696 NLOHMANN_JSON_PASTE12, \
2697 NLOHMANN_JSON_PASTE11, \
2698 NLOHMANN_JSON_PASTE10, \
2699 NLOHMANN_JSON_PASTE9, \
2700 NLOHMANN_JSON_PASTE8, \
2701 NLOHMANN_JSON_PASTE7, \
2702 NLOHMANN_JSON_PASTE6, \
2703 NLOHMANN_JSON_PASTE5, \
2704 NLOHMANN_JSON_PASTE4, \
2705 NLOHMANN_JSON_PASTE3, \
2706 NLOHMANN_JSON_PASTE2, \
2707 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2708#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2709#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2710#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2711#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2712#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2713#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)
2714#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)
2715#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)
2716#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)
2717#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)
2718#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)
2719#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)
2720#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)
2721#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)
2722#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)
2723#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)
2724#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)
2725#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)
2726#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)
2727#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)
2728#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)
2729#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)
2730#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)
2731#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)
2732#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)
2733#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)
2734#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)
2735#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)
2736#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)
2737#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)
2738#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)
2739#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)
2740#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)
2741#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)
2742#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)
2743#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)
2744#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)
2745#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)
2746#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)
2747#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)
2748#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)
2749#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)
2750#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)
2751#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)
2752#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)
2753#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)
2754#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)
2755#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)
2756#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)
2757#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)
2758#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)
2759#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)
2760#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)
2761#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)
2762#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)
2763#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)
2764#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)
2765#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)
2766#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)
2767#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)
2768#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)
2769#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)
2770#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)
2771
2772#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2773#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2774#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;
2775
2776/*!
2777@brief macro
2778@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
2779@since version 3.9.0
2780@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/
2781*/
2782#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2783 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2784 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2785 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2786 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2787
2788/*!
2789@brief macro
2790@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT
2791@since version 3.11.0
2792@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/
2793*/
2794#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2795 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2796 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2797 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2798 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__)) }
2799
2800/*!
2801@brief macro
2802@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE
2803@since version 3.11.3
2804@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/
2805*/
2806#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2807 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2808 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2809
2810/*!
2811@brief macro
2812@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
2813@since version 3.9.0
2814@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/
2815*/
2816#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2817 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2818 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2819 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2820 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2821
2822/*!
2823@brief macro
2824@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT
2825@since version 3.11.0
2826@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/
2827*/
2828#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2829 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2830 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2831 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2832 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__)) }
2833
2834/*!
2835@brief macro
2836@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE
2837@since version 3.11.3
2838@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/
2839*/
2840#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2841 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2842 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2843
2844/*!
2845@brief macro
2846@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE
2847@since version 3.12.0
2848@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
2849*/
2850#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \
2851 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2852 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__)) } \
2853 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2854 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__)) }
2855
2856/*!
2857@brief macro
2858@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT
2859@since version 3.12.0
2860@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
2861*/
2862#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2863 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2864 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__)) } \
2865 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2866 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__)) }
2867
2868/*!
2869@brief macro
2870@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE
2871@since version 3.12.0
2872@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
2873*/
2874#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2875 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2876 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__)) }
2877
2878/*!
2879@brief macro
2880@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE
2881@since version 3.12.0
2882@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
2883*/
2884#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \
2885 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2886 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__)) } \
2887 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2888 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__)) }
2889
2890/*!
2891@brief macro
2892@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT
2893@since version 3.12.0
2894@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
2895*/
2896#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2897 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2898 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__)) } \
2899 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2900 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__)) }
2901
2902/*!
2903@brief macro
2904@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE
2905@since version 3.12.0
2906@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
2907*/
2908#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2909 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2910 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__)) }
2911
2912// inspired from https://stackoverflow.com/a/26745591
2913// allows calling any std function as if (e.g., with begin):
2914// using std::begin; begin(x);
2915//
2916// it allows using the detected idiom to retrieve the return type
2917// of such an expression
2918#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2919 namespace detail { \
2920 using std::std_name; \
2921 \
2922 template<typename... T> \
2923 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2924 } \
2925 \
2926 namespace detail2 { \
2927 struct std_name##_tag \
2928 { \
2929 }; \
2930 \
2931 template<typename... T> \
2932 std_name##_tag std_name(T&&...); \
2933 \
2934 template<typename... T> \
2935 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2936 \
2937 template<typename... T> \
2938 struct would_call_std_##std_name \
2939 { \
2940 static constexpr auto const value = ::nlohmann::detail:: \
2941 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2942 }; \
2943 } /* namespace detail2 */ \
2944 \
2945 template<typename... T> \
2946 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2947 { \
2948 }
2949
2950#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2951 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2952#endif
2953
2954#if JSON_USE_IMPLICIT_CONVERSIONS
2955 #define JSON_EXPLICIT
2956#else
2957 #define JSON_EXPLICIT explicit
2958#endif
2959
2960#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2961 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2962#endif
2963
2964#ifndef JSON_USE_GLOBAL_UDLS
2965 #define JSON_USE_GLOBAL_UDLS 1
2966#endif
2967
2968#if JSON_HAS_THREE_WAY_COMPARISON
2969 #include <compare> // partial_ordering
2970#endif
2971
2973namespace detail
2974{
2975
2976///////////////////////////
2977// JSON type enumeration //
2978///////////////////////////
2979
2980/*!
2981@brief the JSON type enumeration
2982
2983This enumeration collects the different JSON types. It is internally used to
2984distinguish the stored values, and the functions @ref basic_json::is_null(),
2985@ref basic_json::is_object(), @ref basic_json::is_array(),
2986@ref basic_json::is_string(), @ref basic_json::is_boolean(),
2987@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
2988@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
2989@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
2990@ref basic_json::is_structured() rely on it.
2991
2992@note There are three enumeration entries (number_integer, number_unsigned, and
2993number_float), because the library distinguishes these three types for numbers:
2994@ref basic_json::number_unsigned_t is used for unsigned integers,
2995@ref basic_json::number_integer_t is used for signed integers, and
2996@ref basic_json::number_float_t is used for floating-point numbers or to
2997approximate integers which do not fit in the limits of their respective type.
2998
2999@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
3000value with the default value for a given type
3001
3002@since version 1.0.0
3003*/
3004enum class value_t : std::uint8_t
3005{
3006 null, ///< null value
3007 object, ///< object (unordered set of name/value pairs)
3008 array, ///< array (ordered collection of values)
3009 string, ///< string value
3010 boolean, ///< boolean value
3011 number_integer, ///< number value (signed integer)
3012 number_unsigned, ///< number value (unsigned integer)
3013 number_float, ///< number value (floating-point)
3014 binary, ///< binary array (ordered collection of bytes)
3015 discarded ///< discarded by the parser callback function
3016};
3017
3018/*!
3019@brief comparison operator for JSON types
3020
3021Returns an ordering that is similar to Python:
3022- order: null < boolean < number < object < array < string < binary
3023- furthermore, each type is not smaller than itself
3024- discarded values are not comparable
3025- binary is represented as a b"" string in python and directly comparable to a
3026 string; however, making a binary array directly comparable with a string would
3027 be surprising behavior in a JSON file.
3028
3029@since version 1.0.0
3030*/
3031#if JSON_HAS_THREE_WAY_COMPARISON
3032 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
3033#else
3034 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3035#endif
3036{
3037 static constexpr std::array<std::uint8_t, 9> order = {{
3038 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
3039 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
3040 6 /* binary */
3041 }
3042 };
3043
3044 const auto l_index = static_cast<std::size_t>(lhs);
3045 const auto r_index = static_cast<std::size_t>(rhs);
3046#if JSON_HAS_THREE_WAY_COMPARISON
3047 if (l_index < order.size() && r_index < order.size())
3048 {
3049 return order[l_index] <=> order[r_index]; // *NOPAD*
3050 }
3051 return std::partial_ordering::unordered;
3052#else
3053 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
3054#endif
3055}
3056
3057// GCC selects the built-in operator< over an operator rewritten from
3058// a user-defined spaceship operator
3059// Clang, MSVC, and ICC select the rewritten candidate
3060// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
3061#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
3062inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3063{
3064 return std::is_lt(lhs <=> rhs); // *NOPAD*
3065}
3066#endif
3067
3068} // namespace detail
3070
3071// #include <nlohmann/detail/string_escape.hpp>
3072// __ _____ _____ _____
3073// __| | __| | | | JSON for Modern C++
3074// | | |__ | | | | | | version 3.12.0
3075// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3076//
3077// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3078// SPDX-License-Identifier: MIT
3079
3080
3081
3082// #include <nlohmann/detail/abi_macros.hpp>
3083
3084
3086namespace detail
3087{
3088
3089/*!
3090@brief replace all occurrences of a substring by another string
3091
3092@param[in,out] s the string to manipulate; changed so that all
3093 occurrences of @a f are replaced with @a t
3094@param[in] f the substring to replace with @a t
3095@param[in] t the string to replace @a f
3096
3097@pre The search string @a f must not be empty. **This precondition is
3098enforced with an assertion.**
3099
3100@since version 2.0.0
3101*/
3102template<typename StringType>
3103inline void replace_substring(StringType& s, const StringType& f,
3104 const StringType& t)
3105{
3106 JSON_ASSERT(!f.empty());
3107 for (auto pos = s.find(f); // find the first occurrence of f
3108 pos != StringType::npos; // make sure f was found
3109 s.replace(pos, f.size(), t), // replace with t, and
3110 pos = s.find(f, pos + t.size())) // find the next occurrence of f
3111 {}
3112}
3113
3114/*!
3115 * @brief string escaping as described in RFC 6901 (Sect. 4)
3116 * @param[in] s string to escape
3117 * @return escaped string
3118 *
3119 * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
3120 */
3121template<typename StringType>
3122inline StringType escape(StringType s)
3123{
3124 replace_substring(s, StringType{"~"}, StringType{"~0"});
3125 replace_substring(s, StringType{"/"}, StringType{"~1"});
3126 return s;
3127}
3128
3129/*!
3130 * @brief string unescaping as described in RFC 6901 (Sect. 4)
3131 * @param[in] s string to unescape
3132 * @return unescaped string
3133 *
3134 * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
3135 */
3136template<typename StringType>
3137inline void unescape(StringType& s)
3138{
3139 replace_substring(s, StringType{"~1"}, StringType{"/"});
3140 replace_substring(s, StringType{"~0"}, StringType{"~"});
3141}
3142
3143} // namespace detail
3145
3146// #include <nlohmann/detail/input/position_t.hpp>
3147// __ _____ _____ _____
3148// __| | __| | | | JSON for Modern C++
3149// | | |__ | | | | | | version 3.12.0
3150// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3151//
3152// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3153// SPDX-License-Identifier: MIT
3154
3155
3156
3157#include <cstddef> // size_t
3158
3159// #include <nlohmann/detail/abi_macros.hpp>
3160
3161
3163namespace detail
3164{
3165
3166/// struct to capture the start position of the current token
3168{
3169 /// the total number of characters read
3170 std::size_t chars_read_total = 0;
3171 /// the number of characters read in the current line
3173 /// the number of lines read
3174 std::size_t lines_read = 0;
3175
3176 /// conversion to size_t to preserve SAX interface
3177 constexpr operator size_t() const
3178 {
3179 return chars_read_total;
3180 }
3181};
3182
3183} // namespace detail
3185
3186// #include <nlohmann/detail/macro_scope.hpp>
3187
3188// #include <nlohmann/detail/meta/cpp_future.hpp>
3189// __ _____ _____ _____
3190// __| | __| | | | JSON for Modern C++
3191// | | |__ | | | | | | version 3.12.0
3192// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3193//
3194// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3195// SPDX-FileCopyrightText: 2018 The Abseil Authors
3196// SPDX-License-Identifier: MIT
3197
3198
3199
3200#include <array> // array
3201#include <cstddef> // size_t
3202#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3203#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3204
3205// #include <nlohmann/detail/macro_scope.hpp>
3206
3207
3209namespace detail
3210{
3211
3212template<typename T>
3213using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3214
3215#ifdef JSON_HAS_CPP_14
3216
3217// the following utilities are natively available in C++14
3218using std::enable_if_t;
3219using std::index_sequence;
3220using std::make_index_sequence;
3221using std::index_sequence_for;
3222
3223#else
3224
3225// alias templates to reduce boilerplate
3226template<bool B, typename T = void>
3227using enable_if_t = typename std::enable_if<B, T>::type;
3228
3229// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3230// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3231
3232//// START OF CODE FROM GOOGLE ABSEIL
3233
3234// integer_sequence
3235//
3236// Class template representing a compile-time integer sequence. An instantiation
3237// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3238// type through its template arguments (which is a common need when
3239// working with C++11 variadic templates). `absl::integer_sequence` is designed
3240// to be a drop-in replacement for C++14's `std::integer_sequence`.
3241//
3242// Example:
3243//
3244// template< class T, T... Ints >
3245// void user_function(integer_sequence<T, Ints...>);
3246//
3247// int main()
3248// {
3249// // user_function's `T` will be deduced to `int` and `Ints...`
3250// // will be deduced to `0, 1, 2, 3, 4`.
3251// user_function(make_integer_sequence<int, 5>());
3252// }
3253template <typename T, T... Ints>
3255{
3256 using value_type = T;
3257 static constexpr std::size_t size() noexcept
3258 {
3259 return sizeof...(Ints);
3260 }
3261};
3262
3263// index_sequence
3264//
3265// A helper template for an `integer_sequence` of `size_t`,
3266// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3267// `std::index_sequence`.
3268template <size_t... Ints>
3269using index_sequence = integer_sequence<size_t, Ints...>;
3270
3271namespace utility_internal
3272{
3273
3274template <typename Seq, size_t SeqSize, size_t Rem>
3275struct Extend;
3276
3277// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3278template <typename T, T... Ints, size_t SeqSize>
3279struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3280{
3281 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3282};
3283
3284template <typename T, T... Ints, size_t SeqSize>
3285struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3286{
3287 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3288};
3289
3290// Recursion helper for 'make_integer_sequence<T, N>'.
3291// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3292template <typename T, size_t N>
3293struct Gen
3294{
3295 using type =
3296 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3297};
3298
3299template <typename T>
3300struct Gen<T, 0>
3301{
3303};
3304
3305} // namespace utility_internal
3306
3307// Compile-time sequences of integers
3308
3309// make_integer_sequence
3310//
3311// This template alias is equivalent to
3312// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3313// replacement for C++14's `std::make_integer_sequence`.
3314template <typename T, T N>
3316
3317// make_index_sequence
3318//
3319// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3320// and is designed to be a drop-in replacement for C++14's
3321// `std::make_index_sequence`.
3322template <size_t N>
3324
3325// index_sequence_for
3326//
3327// Converts a typename pack into an index sequence of the same length, and
3328// is designed to be a drop-in replacement for C++14's
3329// `std::index_sequence_for()`
3330template <typename... Ts>
3332
3333//// END OF CODE FROM GOOGLE ABSEIL
3334
3335#endif
3336
3337// dispatch utility (taken from ranges-v3)
3338template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3339template<> struct priority_tag<0> {};
3340
3341// taken from ranges-v3
3342template<typename T>
3344{
3345 static JSON_INLINE_VARIABLE constexpr T value{};
3346};
3347
3348#ifndef JSON_HAS_CPP_17
3349 template<typename T>
3350 constexpr T static_const<T>::value;
3351#endif
3352
3353template<typename T, typename... Args>
3354constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3355{
3356 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3357}
3358
3359} // namespace detail
3361
3362// #include <nlohmann/detail/meta/type_traits.hpp>
3363// __ _____ _____ _____
3364// __| | __| | | | JSON for Modern C++
3365// | | |__ | | | | | | version 3.12.0
3366// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3367//
3368// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3369// SPDX-License-Identifier: MIT
3370
3371
3372
3373#include <limits> // numeric_limits
3374#include <string> // char_traits
3375#include <tuple> // tuple
3376#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3377#include <utility> // declval
3378#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3379 #include <cstddef> // byte
3380#endif
3381// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3382// __ _____ _____ _____
3383// __| | __| | | | JSON for Modern C++
3384// | | |__ | | | | | | version 3.12.0
3385// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3386//
3387// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3388// SPDX-License-Identifier: MIT
3389
3390
3391
3392#include <iterator> // random_access_iterator_tag
3393
3394// #include <nlohmann/detail/abi_macros.hpp>
3395
3396// #include <nlohmann/detail/meta/void_t.hpp>
3397
3398// #include <nlohmann/detail/meta/cpp_future.hpp>
3399
3400
3402namespace detail
3403{
3404
3405template<typename It, typename = void>
3407
3408template<typename It>
3410 It,
3411 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3412 typename It::reference, typename It::iterator_category >>
3413{
3414 using difference_type = typename It::difference_type;
3415 using value_type = typename It::value_type;
3416 using pointer = typename It::pointer;
3417 using reference = typename It::reference;
3418 using iterator_category = typename It::iterator_category;
3419};
3420
3421// This is required as some compilers implement std::iterator_traits in a way that
3422// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3423template<typename T, typename = void>
3425{
3426};
3427
3428template<typename T>
3429struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3430 : iterator_types<T>
3431{
3432};
3433
3434template<typename T>
3436{
3437 using iterator_category = std::random_access_iterator_tag;
3438 using value_type = T;
3439 using difference_type = ptrdiff_t;
3440 using pointer = T*;
3441 using reference = T&;
3442};
3443
3444} // namespace detail
3446
3447// #include <nlohmann/detail/macro_scope.hpp>
3448
3449// #include <nlohmann/detail/meta/call_std/begin.hpp>
3450// __ _____ _____ _____
3451// __| | __| | | | JSON for Modern C++
3452// | | |__ | | | | | | version 3.12.0
3453// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3454//
3455// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3456// SPDX-License-Identifier: MIT
3457
3458
3459
3460// #include <nlohmann/detail/macro_scope.hpp>
3461
3462
3464
3466
3468
3469// #include <nlohmann/detail/meta/call_std/end.hpp>
3470// __ _____ _____ _____
3471// __| | __| | | | JSON for Modern C++
3472// | | |__ | | | | | | version 3.12.0
3473// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3474//
3475// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3476// SPDX-License-Identifier: MIT
3477
3478
3479
3480// #include <nlohmann/detail/macro_scope.hpp>
3481
3482
3484
3486
3488
3489// #include <nlohmann/detail/meta/cpp_future.hpp>
3490
3491// #include <nlohmann/detail/meta/detected.hpp>
3492
3493// #include <nlohmann/json_fwd.hpp>
3494// __ _____ _____ _____
3495// __| | __| | | | JSON for Modern C++
3496// | | |__ | | | | | | version 3.12.0
3497// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3498//
3499// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3500// SPDX-License-Identifier: MIT
3501
3502#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3503 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3504
3505 #include <cstdint> // int64_t, uint64_t
3506 #include <map> // map
3507 #include <memory> // allocator
3508 #include <string> // string
3509 #include <vector> // vector
3510
3511 // #include <nlohmann/detail/abi_macros.hpp>
3512
3513
3514 /*!
3515 @brief namespace for Niels Lohmann
3516 @see https://github.com/nlohmann
3517 @since version 1.0.0
3518 */
3520
3521 /*!
3522 @brief default JSONSerializer template argument
3523
3524 This serializer ignores the template arguments and uses ADL
3525 ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
3526 for serialization.
3527 */
3528 template<typename T = void, typename SFINAE = void>
3529 struct adl_serializer;
3530
3531 /// a class to store JSON values
3532 /// @sa https://json.nlohmann.me/api/basic_json/
3533 template<template<typename U, typename V, typename... Args> class ObjectType =
3534 std::map,
3535 template<typename U, typename... Args> class ArrayType = std::vector,
3536 class StringType = std::string, class BooleanType = bool,
3537 class NumberIntegerType = std::int64_t,
3538 class NumberUnsignedType = std::uint64_t,
3539 class NumberFloatType = double,
3540 template<typename U> class AllocatorType = std::allocator,
3541 template<typename T, typename SFINAE = void> class JSONSerializer =
3543 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3544 class CustomBaseClass = void>
3545 class basic_json;
3546
3547 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
3548 /// @sa https://json.nlohmann.me/api/json_pointer/
3549 template<typename RefStringType>
3550 class json_pointer;
3551
3552 /*!
3553 @brief default specialization
3554 @sa https://json.nlohmann.me/api/json/
3555 */
3557
3558 /// @brief a minimal map-like container that preserves insertion order
3559 /// @sa https://json.nlohmann.me/api/ordered_map/
3560 template<class Key, class T, class IgnoredLess, class Allocator>
3561 struct ordered_map;
3562
3563 /// @brief specialization that maintains the insertion order of object keys
3564 /// @sa https://json.nlohmann.me/api/ordered_json/
3566
3568
3569#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3570
3571
3573/*!
3574@brief detail namespace with internal helper functions
3575
3576This namespace collects functions that should not be exposed,
3577implementations of some @ref basic_json methods, and meta-programming helpers.
3578
3579@since version 2.1.0
3580*/
3581namespace detail
3582{
3583
3584/////////////
3585// helpers //
3586/////////////
3587
3588// Note to maintainers:
3589//
3590// Every trait in this file expects a non-CV-qualified type.
3591// The only exceptions are in the 'aliases for detected' section
3592// (i.e., those of the form: decltype(T::member_function(std::declval<T>())))
3593//
3594// In this case, T has to be properly CV-qualified to constraint the function arguments
3595// (e.g., to_json(BasicJsonType&, const T&))
3596
3597template<typename> struct is_basic_json : std::false_type {};
3598
3600struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3601
3602// used by exceptions create() member functions
3603// true_type for the pointer to possibly cv-qualified basic_json or std::nullptr_t
3604// false_type otherwise
3605template<typename BasicJsonContext>
3607 std::integral_constant < bool,
3608 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3609 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3610{};
3611
3612//////////////////////
3613// json_ref helpers //
3614//////////////////////
3615
3616template<typename>
3617class json_ref;
3618
3619template<typename>
3620struct is_json_ref : std::false_type {};
3621
3622template<typename T>
3623struct is_json_ref<json_ref<T>> : std::true_type {};
3624
3625//////////////////////////
3626// aliases for detected //
3627//////////////////////////
3628
3629template<typename T>
3630using mapped_type_t = typename T::mapped_type;
3631
3632template<typename T>
3633using key_type_t = typename T::key_type;
3634
3635template<typename T>
3636using value_type_t = typename T::value_type;
3637
3638template<typename T>
3639using difference_type_t = typename T::difference_type;
3640
3641template<typename T>
3642using pointer_t = typename T::pointer;
3643
3644template<typename T>
3645using reference_t = typename T::reference;
3646
3647template<typename T>
3648using iterator_category_t = typename T::iterator_category;
3649
3650template<typename T, typename... Args>
3651using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3652
3653template<typename T, typename... Args>
3654using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3655
3656template<typename T, typename U>
3657using get_template_function = decltype(std::declval<T>().template get<U>());
3658
3659// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3660template<typename BasicJsonType, typename T, typename = void>
3661struct has_from_json : std::false_type {};
3662
3663// trait checking if j.get<T> is valid
3664// use this trait instead of std::is_constructible or std::is_convertible,
3665// both rely on, or make use of implicit conversions, and thus fail when T
3666// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3667template <typename BasicJsonType, typename T>
3672
3673template<typename BasicJsonType, typename T>
3674struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3675{
3676 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3677
3678 static constexpr bool value =
3680 const BasicJsonType&, T&>::value;
3681};
3682
3683// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3684// this overload is used for non-default-constructible user-defined-types
3685template<typename BasicJsonType, typename T, typename = void>
3686struct has_non_default_from_json : std::false_type {};
3687
3688template<typename BasicJsonType, typename T>
3689struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3690{
3691 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3692
3693 static constexpr bool value =
3695 const BasicJsonType&>::value;
3696};
3697
3698// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3699// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3700template<typename BasicJsonType, typename T, typename = void>
3701struct has_to_json : std::false_type {};
3702
3703template<typename BasicJsonType, typename T>
3704struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3705{
3706 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3707
3708 static constexpr bool value =
3709 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3710 T>::value;
3711};
3712
3713template<typename T>
3714using detect_key_compare = typename T::key_compare;
3715
3716template<typename T>
3717struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3718
3719// obtains the actual object key comparator
3720template<typename BasicJsonType>
3722{
3723 using object_t = typename BasicJsonType::object_t;
3724 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3725 using type = typename std::conditional < has_key_compare<object_t>::value,
3726 typename object_t::key_compare, object_comparator_t>::type;
3727};
3728
3729template<typename BasicJsonType>
3731
3732/////////////////
3733// char_traits //
3734/////////////////
3735
3736// Primary template of char_traits calls std char_traits
3737template<typename T>
3738struct char_traits : std::char_traits<T>
3739{};
3740
3741// Explicitly define char traits for unsigned char since it is not standard
3742template<>
3743struct char_traits<unsigned char> : std::char_traits<char>
3744{
3745 using char_type = unsigned char;
3746 using int_type = uint64_t;
3747
3748 // Redefine to_int_type function
3749 static int_type to_int_type(char_type c) noexcept
3750 {
3751 return static_cast<int_type>(c);
3752 }
3753
3755 {
3756 return static_cast<char_type>(i);
3757 }
3758
3759 static constexpr int_type eof() noexcept
3760 {
3761 return static_cast<int_type>(std::char_traits<char>::eof());
3762 }
3763};
3764
3765// Explicitly define char traits for signed char since it is not standard
3766template<>
3767struct char_traits<signed char> : std::char_traits<char>
3768{
3769 using char_type = signed char;
3770 using int_type = uint64_t;
3771
3772 // Redefine to_int_type function
3773 static int_type to_int_type(char_type c) noexcept
3774 {
3775 return static_cast<int_type>(c);
3776 }
3777
3779 {
3780 return static_cast<char_type>(i);
3781 }
3782
3783 static constexpr int_type eof() noexcept
3784 {
3785 return static_cast<int_type>(std::char_traits<char>::eof());
3786 }
3787};
3788
3789#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3790template<>
3791struct char_traits<std::byte> : std::char_traits<char>
3792{
3793 using char_type = std::byte;
3794 using int_type = uint64_t;
3795
3796 static int_type to_int_type(char_type c) noexcept
3797 {
3798 return static_cast<int_type>(std::to_integer<unsigned char>(c));
3799 }
3800
3801 static char_type to_char_type(int_type i) noexcept
3802 {
3803 return std::byte(static_cast<unsigned char>(i));
3804 }
3805
3806 static constexpr int_type eof() noexcept
3807 {
3808 return static_cast<int_type>(std::char_traits<char>::eof());
3809 }
3810};
3811#endif
3812
3813///////////////////
3814// is_ functions //
3815///////////////////
3816
3817// https://en.cppreference.com/w/cpp/types/conjunction
3818template<class...> struct conjunction : std::true_type { };
3819template<class B> struct conjunction<B> : B { };
3820template<class B, class... Bn>
3821struct conjunction<B, Bn...>
3822: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3823
3824// https://en.cppreference.com/w/cpp/types/negation
3825template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3826
3827// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3828// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3829// This causes compile errors in e.g., Clang 3.5 or GCC 4.9.
3830template <typename T>
3831struct is_default_constructible : std::is_default_constructible<T> {};
3832
3833template <typename T1, typename T2>
3834struct is_default_constructible<std::pair<T1, T2>>
3835 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3836
3837template <typename T1, typename T2>
3838struct is_default_constructible<const std::pair<T1, T2>>
3839 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3840
3841template <typename... Ts>
3842struct is_default_constructible<std::tuple<Ts...>>
3843 : conjunction<is_default_constructible<Ts>...> {};
3844
3845template <typename... Ts>
3846struct is_default_constructible<const std::tuple<Ts...>>
3847 : conjunction<is_default_constructible<Ts>...> {};
3848
3849template <typename T, typename... Args>
3850struct is_constructible : std::is_constructible<T, Args...> {};
3851
3852template <typename T1, typename T2>
3853struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3854
3855template <typename T1, typename T2>
3856struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3857
3858template <typename... Ts>
3859struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3860
3861template <typename... Ts>
3862struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3863
3864template<typename T, typename = void>
3865struct is_iterator_traits : std::false_type {};
3866
3867template<typename T>
3881
3882template<typename T>
3884{
3885 private:
3886 using t_ref = typename std::add_lvalue_reference<T>::type;
3887
3890
3891 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3892 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3893 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3894 static constexpr auto is_iterator_begin =
3896
3897 public:
3898 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3899};
3900
3901template<typename R>
3902using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3903
3904template<typename T>
3906
3907// The following implementation of is_complete_type is taken from
3908// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3909// and is written by Xiang Fan who agreed to use it in this library.
3910
3911template<typename T, typename = void>
3912struct is_complete_type : std::false_type {};
3913
3914template<typename T>
3915struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3916
3917template<typename BasicJsonType, typename CompatibleObjectType,
3918 typename = void>
3919struct is_compatible_object_type_impl : std::false_type {};
3920
3921template<typename BasicJsonType, typename CompatibleObjectType>
3923 BasicJsonType, CompatibleObjectType,
3924 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3925 is_detected<key_type_t, CompatibleObjectType>::value >>
3926{
3927 using object_t = typename BasicJsonType::object_t;
3928
3929 // macOS's is_constructible does not play well with nonesuch...
3930 static constexpr bool value =
3931 is_constructible<typename object_t::key_type,
3932 typename CompatibleObjectType::key_type>::value &&
3933 is_constructible<typename object_t::mapped_type,
3934 typename CompatibleObjectType::mapped_type>::value;
3935};
3936
3937template<typename BasicJsonType, typename CompatibleObjectType>
3939 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3940
3941template<typename BasicJsonType, typename ConstructibleObjectType,
3942 typename = void>
3943struct is_constructible_object_type_impl : std::false_type {};
3944
3945template<typename BasicJsonType, typename ConstructibleObjectType>
3947 BasicJsonType, ConstructibleObjectType,
3948 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3949 is_detected<key_type_t, ConstructibleObjectType>::value >>
3950{
3951 using object_t = typename BasicJsonType::object_t;
3952
3953 static constexpr bool value =
3955 (std::is_move_assignable<ConstructibleObjectType>::value ||
3956 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3957 (is_constructible<typename ConstructibleObjectType::key_type,
3958 typename object_t::key_type>::value &&
3959 std::is_same <
3960 typename object_t::mapped_type,
3961 typename ConstructibleObjectType::mapped_type >::value)) ||
3962 (has_from_json<BasicJsonType,
3963 typename ConstructibleObjectType::mapped_type>::value ||
3965 BasicJsonType,
3966 typename ConstructibleObjectType::mapped_type >::value);
3967};
3968
3969template<typename BasicJsonType, typename ConstructibleObjectType>
3971 : is_constructible_object_type_impl<BasicJsonType,
3972 ConstructibleObjectType> {};
3973
3974template<typename BasicJsonType, typename CompatibleStringType>
3980
3981template<typename BasicJsonType, typename ConstructibleStringType>
3983{
3984 // launder type through decltype() to fix compilation failure on ICPC
3985#ifdef __INTEL_COMPILER
3986 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3987#else
3988 using laundered_type = ConstructibleStringType;
3989#endif
3990
3991 static constexpr auto value =
3992 conjunction <
3994 is_detected_exact<typename BasicJsonType::string_t::value_type,
3996};
3997
3998template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3999struct is_compatible_array_type_impl : std::false_type {};
4000
4001template<typename BasicJsonType, typename CompatibleArrayType>
4003 BasicJsonType, CompatibleArrayType,
4004 enable_if_t <
4005 is_detected<iterator_t, CompatibleArrayType>::value&&
4006 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
4007// special case for types like std::filesystem::path whose iterator's value_type are themselves
4008// c.f. https://github.com/nlohmann/json/pull/3073
4009 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
4010{
4011 static constexpr bool value =
4012 is_constructible<BasicJsonType,
4014};
4015
4016template<typename BasicJsonType, typename CompatibleArrayType>
4018 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
4019
4020template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
4021struct is_constructible_array_type_impl : std::false_type {};
4022
4023template<typename BasicJsonType, typename ConstructibleArrayType>
4025 BasicJsonType, ConstructibleArrayType,
4026 enable_if_t<std::is_same<ConstructibleArrayType,
4027 typename BasicJsonType::value_type>::value >>
4028 : std::true_type {};
4029
4030template<typename BasicJsonType, typename ConstructibleArrayType>
4032 BasicJsonType, ConstructibleArrayType,
4033 enable_if_t < !std::is_same<ConstructibleArrayType,
4034 typename BasicJsonType::value_type>::value&&
4035 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4036 is_default_constructible<ConstructibleArrayType>::value&&
4037(std::is_move_assignable<ConstructibleArrayType>::value ||
4038 std::is_copy_assignable<ConstructibleArrayType>::value)&&
4039is_detected<iterator_t, ConstructibleArrayType>::value&&
4040is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
4041is_detected<range_value_t, ConstructibleArrayType>::value&&
4042// special case for types like std::filesystem::path whose iterator's value_type are themselves
4043// c.f. https://github.com/nlohmann/json/pull/3073
4044!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
4046detected_t<range_value_t, ConstructibleArrayType >>::value >>
4047{
4049
4050 static constexpr bool value =
4051 std::is_same<value_type,
4052 typename BasicJsonType::array_t::value_type>::value ||
4053 has_from_json<BasicJsonType,
4056 BasicJsonType,
4058};
4059
4060template<typename BasicJsonType, typename ConstructibleArrayType>
4062 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
4063
4064template<typename RealIntegerType, typename CompatibleNumberIntegerType,
4065 typename = void>
4066struct is_compatible_integer_type_impl : std::false_type {};
4067
4068template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4070 RealIntegerType, CompatibleNumberIntegerType,
4071 enable_if_t < std::is_integral<RealIntegerType>::value&&
4072 std::is_integral<CompatibleNumberIntegerType>::value&&
4073 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
4074{
4075 // is there an assert somewhere on overflows?
4076 using RealLimits = std::numeric_limits<RealIntegerType>;
4077 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
4078
4079 static constexpr auto value =
4080 is_constructible<RealIntegerType,
4081 CompatibleNumberIntegerType>::value &&
4082 CompatibleLimits::is_integer &&
4083 RealLimits::is_signed == CompatibleLimits::is_signed;
4084};
4085
4086template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4088 : is_compatible_integer_type_impl<RealIntegerType,
4089 CompatibleNumberIntegerType> {};
4090
4091template<typename BasicJsonType, typename CompatibleType, typename = void>
4092struct is_compatible_type_impl: std::false_type {};
4093
4094template<typename BasicJsonType, typename CompatibleType>
4096 BasicJsonType, CompatibleType,
4097 enable_if_t<is_complete_type<CompatibleType>::value >>
4098{
4099 static constexpr bool value =
4101};
4102
4103template<typename BasicJsonType, typename CompatibleType>
4105 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
4106
4107template<typename T1, typename T2>
4108struct is_constructible_tuple : std::false_type {};
4109
4110template<typename T1, typename... Args>
4111struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
4112
4113template<typename BasicJsonType, typename T>
4114struct is_json_iterator_of : std::false_type {};
4115
4116template<typename BasicJsonType>
4117struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
4118
4119template<typename BasicJsonType>
4120struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
4121{};
4122
4123// checks if a given type T is a template specialization of Primary
4124template<template <typename...> class Primary, typename T>
4125struct is_specialization_of : std::false_type {};
4126
4127template<template <typename...> class Primary, typename... Args>
4128struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
4129
4130template<typename T>
4132
4133// checks if A and B are comparable using Compare functor
4134template<typename Compare, typename A, typename B, typename = void>
4135struct is_comparable : std::false_type {};
4136
4137template<typename Compare, typename A, typename B>
4138struct is_comparable<Compare, A, B, void_t<
4139decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
4140decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
4141>> : std::true_type {};
4142
4143template<typename T>
4144using detect_is_transparent = typename T::is_transparent;
4145
4146// type trait to check if KeyType can be used as an object key (without a BasicJsonType)
4147// see is_usable_as_basic_json_key_type below
4148template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4149 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4150using is_usable_as_key_type = typename std::conditional <
4152 && !(ExcludeObjectKeyType && std::is_same<KeyType,
4153 ObjectKeyType>::value)
4154 && (!RequireTransparentComparator
4155 || is_detected <detect_is_transparent, Comparator>::value)
4157 std::true_type,
4158 std::false_type >::type;
4159
4160// type trait to check if KeyType can be used as an object key
4161// true if:
4162// - KeyType is comparable with BasicJsonType::object_t::key_type
4163// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4164// - the comparator is transparent or RequireTransparentComparator is false
4165// - KeyType is not a JSON iterator or json_pointer
4166template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4167 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4168using is_usable_as_basic_json_key_type = typename std::conditional <
4169 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4170 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4171 RequireTransparentComparator, ExcludeObjectKeyType>::value
4173 std::true_type,
4174 std::false_type >::type;
4175
4176template<typename ObjectType, typename KeyType>
4177using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4178
4179// type trait to check if object_t has an erase() member functions accepting KeyType
4180template<typename BasicJsonType, typename KeyType>
4181using has_erase_with_key_type = typename std::conditional <
4182 is_detected <
4184 typename BasicJsonType::object_t, KeyType >::value,
4185 std::true_type,
4186 std::false_type >::type;
4187
4188// a naive helper to check if a type is an ordered_map (exploits the fact that
4189// ordered_map inherits capacity() from std::vector)
4190template <typename T>
4192{
4193 using one = char;
4194
4195 struct two
4196 {
4197 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4198 };
4199
4200 template <typename C> static one test( decltype(&C::capacity) ) ;
4201 template <typename C> static two test(...);
4202
4203 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4204};
4205
4206// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4207template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4209{
4210 return static_cast<T>(value);
4211}
4212
4213template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4215{
4216 return value;
4217}
4218
4219template<typename... Types>
4221
4222template<typename... Types>
4224
4225template<typename... Types>
4227
4228// there's a disjunction trait in another PR; replace when merged
4229template<typename... Types>
4230using same_sign = std::integral_constant < bool,
4231 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4232
4233template<typename OfType, typename T>
4234using never_out_of_range = std::integral_constant < bool,
4235 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4236 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4237
4238template<typename OfType, typename T,
4239 bool OfTypeSigned = std::is_signed<OfType>::value,
4240 bool TSigned = std::is_signed<T>::value>
4242
4243template<typename OfType, typename T>
4244struct value_in_range_of_impl2<OfType, T, false, false>
4245{
4246 static constexpr bool test(T val)
4247 {
4248 using CommonType = typename std::common_type<OfType, T>::type;
4249 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4250 }
4251};
4252
4253template<typename OfType, typename T>
4254struct value_in_range_of_impl2<OfType, T, true, false>
4255{
4256 static constexpr bool test(T val)
4257 {
4258 using CommonType = typename std::common_type<OfType, T>::type;
4259 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4260 }
4261};
4262
4263template<typename OfType, typename T>
4264struct value_in_range_of_impl2<OfType, T, false, true>
4265{
4266 static constexpr bool test(T val)
4267 {
4268 using CommonType = typename std::common_type<OfType, T>::type;
4269 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4270 }
4271};
4272
4273template<typename OfType, typename T>
4274struct value_in_range_of_impl2<OfType, T, true, true>
4275{
4276 static constexpr bool test(T val)
4277 {
4278 using CommonType = typename std::common_type<OfType, T>::type;
4279 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4280 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4281 }
4282};
4283
4284template<typename OfType, typename T,
4285 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4288
4289template<typename OfType, typename T>
4290struct value_in_range_of_impl1<OfType, T, false>
4291{
4292 static constexpr bool test(T val)
4293 {
4295 }
4296};
4297
4298template<typename OfType, typename T>
4299struct value_in_range_of_impl1<OfType, T, true>
4300{
4301 static constexpr bool test(T /*val*/)
4302 {
4303 return true;
4304 }
4305};
4306
4307template<typename OfType, typename T>
4308constexpr bool value_in_range_of(T val)
4309{
4311}
4312
4313template<bool Value>
4314using bool_constant = std::integral_constant<bool, Value>;
4315
4316///////////////////////////////////////////////////////////////////////////////
4317// is_c_string
4318///////////////////////////////////////////////////////////////////////////////
4319
4320namespace impl
4321{
4322
4323template<typename T>
4324constexpr bool is_c_string()
4325{
4326 using TUnExt = typename std::remove_extent<T>::type;
4327 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4328 using TUnPtr = typename std::remove_pointer<T>::type;
4329 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4330 return
4331 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4332 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4333}
4334
4335} // namespace impl
4336
4337// checks whether T is a [cv] char */[cv] char[] C string
4338template<typename T>
4339struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4340
4341template<typename T>
4343
4344///////////////////////////////////////////////////////////////////////////////
4345// is_transparent
4346///////////////////////////////////////////////////////////////////////////////
4347
4348namespace impl
4349{
4350
4351template<typename T>
4352constexpr bool is_transparent()
4353{
4355}
4356
4357} // namespace impl
4358
4359// checks whether T has a member named is_transparent
4360template<typename T>
4361struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4362
4363///////////////////////////////////////////////////////////////////////////////
4364
4365} // namespace detail
4367
4368// #include <nlohmann/detail/string_concat.hpp>
4369// __ _____ _____ _____
4370// __| | __| | | | JSON for Modern C++
4371// | | |__ | | | | | | version 3.12.0
4372// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4373//
4374// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4375// SPDX-License-Identifier: MIT
4376
4377
4378
4379#include <cstring> // strlen
4380#include <string> // string
4381#include <utility> // forward
4382
4383// #include <nlohmann/detail/meta/cpp_future.hpp>
4384
4385// #include <nlohmann/detail/meta/detected.hpp>
4386
4387
4389namespace detail
4390{
4391
4392inline std::size_t concat_length()
4393{
4394 return 0;
4395}
4396
4397template<typename... Args>
4398inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4399
4400template<typename StringType, typename... Args>
4401inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4402
4403template<typename... Args>
4404inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4405{
4406 return 1 + concat_length(rest...);
4407}
4408
4409template<typename... Args>
4410inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4411{
4412 // cppcheck-suppress ignoredReturnValue
4413 return ::strlen(cstr) + concat_length(rest...);
4414}
4415
4416template<typename StringType, typename... Args>
4417inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4418{
4419 return str.size() + concat_length(rest...);
4420}
4421
4422template<typename OutStringType>
4423inline void concat_into(OutStringType& /*out*/)
4424{}
4425
4426template<typename StringType, typename Arg>
4427using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4428
4429template<typename StringType, typename Arg>
4431
4432template<typename StringType, typename Arg>
4433using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4434
4435template<typename StringType, typename Arg>
4437
4438template<typename StringType, typename Arg>
4439using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4440
4441template<typename StringType, typename Arg>
4443
4444template<typename StringType, typename Arg>
4445using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4446
4447template<typename StringType, typename Arg>
4449
4450template < typename OutStringType, typename Arg, typename... Args,
4451 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4453inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4454
4455template < typename OutStringType, typename Arg, typename... Args,
4456 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4459inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4460
4461template < typename OutStringType, typename Arg, typename... Args,
4462 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4466inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4467
4468template<typename OutStringType, typename Arg, typename... Args,
4470inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4471{
4472 out.append(std::forward<Arg>(arg));
4473 concat_into(out, std::forward<Args>(rest)...);
4474}
4475
4476template < typename OutStringType, typename Arg, typename... Args,
4477 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4478 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4479inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4480{
4481 out += std::forward<Arg>(arg);
4482 concat_into(out, std::forward<Args>(rest)...);
4483}
4484
4485template < typename OutStringType, typename Arg, typename... Args,
4486 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4487 && !detect_string_can_append_op<OutStringType, Arg>::value
4488 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4489inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4490{
4491 out.append(arg.begin(), arg.end());
4492 concat_into(out, std::forward<Args>(rest)...);
4493}
4494
4495template < typename OutStringType, typename Arg, typename... Args,
4496 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4497 && !detect_string_can_append_op<OutStringType, Arg>::value
4498 && !detect_string_can_append_iter<OutStringType, Arg>::value
4499 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4500inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4501{
4502 out.append(arg.data(), arg.size());
4503 concat_into(out, std::forward<Args>(rest)...);
4504}
4505
4506template<typename OutStringType = std::string, typename... Args>
4507inline OutStringType concat(Args && ... args)
4508{
4509 OutStringType str;
4510 str.reserve(concat_length(args...));
4511 concat_into(str, std::forward<Args>(args)...);
4512 return str;
4513}
4514
4515} // namespace detail
4517
4518
4519// With -Wweak-vtables, Clang will complain about the exception classes as they
4520// have no out-of-line virtual method definitions and their vtable will be
4521// emitted in every translation unit. This issue cannot be fixed with a
4522// header-only library as there is no implementation file to move these
4523// functions to. As a result, we suppress this warning here to avoid client
4524// code stumbling over this. See https://github.com/nlohmann/json/issues/4087
4525// for a discussion.
4526#if defined(__clang__)
4527 #pragma clang diagnostic push
4528 #pragma clang diagnostic ignored "-Wweak-vtables"
4529#endif
4530
4532namespace detail
4533{
4534
4535////////////////
4536// exceptions //
4537////////////////
4538
4539/// @brief general exception of the @ref basic_json class
4540/// @sa https://json.nlohmann.me/api/basic_json/exception/
4541class exception : public std::exception
4542{
4543 public:
4544 /// returns the explanatory string
4545 const char* what() const noexcept override
4546 {
4547 return m.what();
4548 }
4549
4550 /// the id of the exception
4551 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4552
4553 protected:
4555 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4556
4557 static std::string name(const std::string& ename, int id_)
4558 {
4559 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4560 }
4561
4562 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4563 {
4564 return "";
4565 }
4566
4567 template<typename BasicJsonType>
4568 static std::string diagnostics(const BasicJsonType* leaf_element)
4569 {
4570#if JSON_DIAGNOSTICS
4571 std::vector<std::string> tokens;
4572 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4573 {
4574 switch (current->m_parent->type())
4575 {
4576 case value_t::array:
4577 {
4578 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4579 {
4580 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4581 {
4582 tokens.emplace_back(std::to_string(i));
4583 break;
4584 }
4585 }
4586 break;
4587 }
4588
4589 case value_t::object:
4590 {
4591 for (const auto& element : *current->m_parent->m_data.m_value.object)
4592 {
4593 if (&element.second == current)
4594 {
4595 tokens.emplace_back(element.first.c_str());
4596 break;
4597 }
4598 }
4599 break;
4600 }
4601
4602 case value_t::null: // LCOV_EXCL_LINE
4603 case value_t::string: // LCOV_EXCL_LINE
4604 case value_t::boolean: // LCOV_EXCL_LINE
4605 case value_t::number_integer: // LCOV_EXCL_LINE
4606 case value_t::number_unsigned: // LCOV_EXCL_LINE
4607 case value_t::number_float: // LCOV_EXCL_LINE
4608 case value_t::binary: // LCOV_EXCL_LINE
4609 case value_t::discarded: // LCOV_EXCL_LINE
4610 default: // LCOV_EXCL_LINE
4611 break; // LCOV_EXCL_LINE
4612 }
4613 }
4614
4615 if (tokens.empty())
4616 {
4617 return "";
4618 }
4619
4620 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4621 [](const std::string & a, const std::string & b)
4622 {
4623 return concat(a, '/', detail::escape(b));
4624 });
4625
4626 return concat('(', str, ") ", get_byte_positions(leaf_element));
4627#else
4628 return get_byte_positions(leaf_element);
4629#endif
4630 }
4631
4632 private:
4633 /// an exception object as storage for error messages
4634 std::runtime_error m;
4635#if JSON_DIAGNOSTIC_POSITIONS
4636 template<typename BasicJsonType>
4637 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4638 {
4639 if ((leaf_element->start_pos() != std::string::npos) && (leaf_element->end_pos() != std::string::npos))
4640 {
4641 return concat("(bytes ", std::to_string(leaf_element->start_pos()), "-", std::to_string(leaf_element->end_pos()), ") ");
4642 }
4643 return "";
4644 }
4645#else
4646 template<typename BasicJsonType>
4647 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4648 {
4649 static_cast<void>(leaf_element);
4650 return "";
4651 }
4652#endif
4653};
4654
4655/// @brief exception indicating a parse error
4656/// @sa https://json.nlohmann.me/api/basic_json/parse_error/
4658{
4659 public:
4660 /*!
4661 @brief create a parse error exception
4662 @param[in] id_ the id of the exception
4663 @param[in] pos the position where the error occurred (or with
4664 chars_read_total=0 if the position cannot be
4665 determined)
4666 @param[in] what_arg the explanatory string
4667 @return parse_error object
4668 */
4669 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4670 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4671 {
4672 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4673 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4674 return {id_, pos.chars_read_total, w.c_str()};
4675 }
4676
4677 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4678 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4679 {
4680 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4681 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4682 ": ", exception::diagnostics(context), what_arg);
4683 return {id_, byte_, w.c_str()};
4684 }
4685
4686 /*!
4687 @brief byte index of the parse error
4688
4689 The byte index of the last read character in the input file.
4690
4691 @note For an input with n bytes, 1 is the index of the first character and
4692 n+1 is the index of the terminating null byte or the end of file.
4693 This also holds true when reading a byte vector (CBOR or MessagePack).
4694 */
4695 const std::size_t byte;
4696
4697 private:
4698 parse_error(int id_, std::size_t byte_, const char* what_arg)
4699 : exception(id_, what_arg), byte(byte_) {}
4700
4701 static std::string position_string(const position_t& pos)
4702 {
4703 return concat(" at line ", std::to_string(pos.lines_read + 1),
4704 ", column ", std::to_string(pos.chars_read_current_line));
4705 }
4706};
4707
4708/// @brief exception indicating errors with iterators
4709/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
4711{
4712 public:
4713 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4714 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4715 {
4716 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4717 return {id_, w.c_str()};
4718 }
4719
4720 private:
4722 invalid_iterator(int id_, const char* what_arg)
4723 : exception(id_, what_arg) {}
4724};
4725
4726/// @brief exception indicating executing a member function with a wrong type
4727/// @sa https://json.nlohmann.me/api/basic_json/type_error/
4728class type_error : public exception
4729{
4730 public:
4731 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4732 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4733 {
4734 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4735 return {id_, w.c_str()};
4736 }
4737
4738 private:
4740 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4741};
4742
4743/// @brief exception indicating access out of the defined range
4744/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
4746{
4747 public:
4748 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4749 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4750 {
4751 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4752 return {id_, w.c_str()};
4753 }
4754
4755 private:
4757 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4758};
4759
4760/// @brief exception indicating other library errors
4761/// @sa https://json.nlohmann.me/api/basic_json/other_error/
4763{
4764 public:
4765 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4766 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4767 {
4768 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4769 return {id_, w.c_str()};
4770 }
4771
4772 private:
4774 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4775};
4776
4777} // namespace detail
4779
4780#if defined(__clang__)
4781 #pragma clang diagnostic pop
4782#endif
4783
4784// #include <nlohmann/detail/macro_scope.hpp>
4785
4786// #include <nlohmann/detail/meta/cpp_future.hpp>
4787
4788// #include <nlohmann/detail/meta/identity_tag.hpp>
4789// __ _____ _____ _____
4790// __| | __| | | | JSON for Modern C++
4791// | | |__ | | | | | | version 3.12.0
4792// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4793//
4794// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4795// SPDX-License-Identifier: MIT
4796
4797
4798
4799// #include <nlohmann/detail/abi_macros.hpp>
4800
4801
4803namespace detail
4804{
4805
4806// dispatching helper struct
4807template <class T> struct identity_tag {};
4808
4809} // namespace detail
4811
4812// #include <nlohmann/detail/meta/std_fs.hpp>
4813// __ _____ _____ _____
4814// __| | __| | | | JSON for Modern C++
4815// | | |__ | | | | | | version 3.12.0
4816// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4817//
4818// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4819// SPDX-License-Identifier: MIT
4820
4821
4822
4823// #include <nlohmann/detail/macro_scope.hpp>
4824
4825
4826#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4827#include <experimental/filesystem>
4829namespace detail
4830{
4831namespace std_fs = std::experimental::filesystem;
4832} // namespace detail
4834#elif JSON_HAS_FILESYSTEM
4835#include <filesystem> // NOLINT(build/c++17)
4837namespace detail
4838{
4839namespace std_fs = std::filesystem;
4840} // namespace detail
4842#endif
4843
4844// #include <nlohmann/detail/meta/type_traits.hpp>
4845
4846// #include <nlohmann/detail/string_concat.hpp>
4847
4848// #include <nlohmann/detail/value_t.hpp>
4849
4850
4851// include after macro_scope.hpp
4852#ifdef JSON_HAS_CPP_17
4853 #include <optional> // optional
4854#endif
4855
4856#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4857 #include <string_view> // u8string_view
4858#endif
4859
4861namespace detail
4862{
4863
4864template<typename BasicJsonType>
4865inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4866{
4867 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4868 {
4869 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4870 }
4871 n = nullptr;
4872}
4873
4874#ifdef JSON_HAS_CPP_17
4875template<typename BasicJsonType, typename T>
4876void from_json(const BasicJsonType& j, std::optional<T>& opt)
4877{
4878 if (j.is_null())
4879 {
4880 opt = std::nullopt;
4881 }
4882 else
4883 {
4884 opt.emplace(j.template get<T>());
4885 }
4886}
4887#endif // JSON_HAS_CPP_17
4888
4889// overloads for basic_json template parameters
4890template < typename BasicJsonType, typename ArithmeticType,
4891 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4892 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4893 int > = 0 >
4894void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4895{
4896 switch (static_cast<value_t>(j))
4897 {
4899 {
4900 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4901 break;
4902 }
4904 {
4905 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4906 break;
4907 }
4909 {
4910 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4911 break;
4912 }
4913
4914 case value_t::null:
4915 case value_t::object:
4916 case value_t::array:
4917 case value_t::string:
4918 case value_t::boolean:
4919 case value_t::binary:
4920 case value_t::discarded:
4921 default:
4922 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4923 }
4924}
4925
4926template<typename BasicJsonType>
4927inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4928{
4929 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4930 {
4931 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4932 }
4933 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4934}
4935
4936template<typename BasicJsonType>
4937inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4938{
4939 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4940 {
4941 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4942 }
4943 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4944}
4945
4946template <
4947 typename BasicJsonType, typename StringType,
4948 enable_if_t <
4949 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4950 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4951 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4952 && !is_json_ref<StringType>::value, int > = 0 >
4953inline void from_json(const BasicJsonType& j, StringType& s)
4954{
4955 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4956 {
4957 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4958 }
4959
4960 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4961}
4962
4963template<typename BasicJsonType>
4964inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4965{
4966 get_arithmetic_value(j, val);
4967}
4968
4969template<typename BasicJsonType>
4970inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4971{
4972 get_arithmetic_value(j, val);
4973}
4974
4975template<typename BasicJsonType>
4976inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4977{
4978 get_arithmetic_value(j, val);
4979}
4980
4981#if !JSON_DISABLE_ENUM_SERIALIZATION
4982template<typename BasicJsonType, typename EnumType,
4983 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4984inline void from_json(const BasicJsonType& j, EnumType& e)
4985{
4986 typename std::underlying_type<EnumType>::type val;
4987 get_arithmetic_value(j, val);
4988 e = static_cast<EnumType>(val);
4989}
4990#endif // JSON_DISABLE_ENUM_SERIALIZATION
4991
4992// forward_list doesn't have an insert method
4993template<typename BasicJsonType, typename T, typename Allocator,
4994 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4995inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4996{
4997 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4998 {
4999 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5000 }
5001 l.clear();
5002 std::transform(j.rbegin(), j.rend(),
5003 std::front_inserter(l), [](const BasicJsonType & i)
5004 {
5005 return i.template get<T>();
5006 });
5007}
5008
5009// valarray doesn't have an insert method
5010template<typename BasicJsonType, typename T,
5011 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
5012inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
5013{
5014 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5015 {
5016 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5017 }
5018 l.resize(j.size());
5019 std::transform(j.begin(), j.end(), std::begin(l),
5020 [](const BasicJsonType & elem)
5021 {
5022 return elem.template get<T>();
5023 });
5024}
5025
5026template<typename BasicJsonType, typename T, std::size_t N>
5027auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5028-> decltype(j.template get<T>(), void())
5029{
5030 for (std::size_t i = 0; i < N; ++i)
5031 {
5032 arr[i] = j.at(i).template get<T>();
5033 }
5034}
5035
5036template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2>
5037auto from_json(const BasicJsonType& j, T (&arr)[N1][N2]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5038-> decltype(j.template get<T>(), void())
5039{
5040 for (std::size_t i1 = 0; i1 < N1; ++i1)
5041 {
5042 for (std::size_t i2 = 0; i2 < N2; ++i2)
5043 {
5044 arr[i1][i2] = j.at(i1).at(i2).template get<T>();
5045 }
5046 }
5047}
5048
5049template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3>
5050auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5051-> decltype(j.template get<T>(), void())
5052{
5053 for (std::size_t i1 = 0; i1 < N1; ++i1)
5054 {
5055 for (std::size_t i2 = 0; i2 < N2; ++i2)
5056 {
5057 for (std::size_t i3 = 0; i3 < N3; ++i3)
5058 {
5059 arr[i1][i2][i3] = j.at(i1).at(i2).at(i3).template get<T>();
5060 }
5061 }
5062 }
5063}
5064
5065template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3, std::size_t N4>
5066auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3][N4]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5067-> decltype(j.template get<T>(), void())
5068{
5069 for (std::size_t i1 = 0; i1 < N1; ++i1)
5070 {
5071 for (std::size_t i2 = 0; i2 < N2; ++i2)
5072 {
5073 for (std::size_t i3 = 0; i3 < N3; ++i3)
5074 {
5075 for (std::size_t i4 = 0; i4 < N4; ++i4)
5076 {
5077 arr[i1][i2][i3][i4] = j.at(i1).at(i2).at(i3).at(i4).template get<T>();
5078 }
5079 }
5080 }
5081 }
5082}
5083
5084template<typename BasicJsonType>
5085inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
5086{
5087 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
5088}
5089
5090template<typename BasicJsonType, typename T, std::size_t N>
5091auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
5092 priority_tag<2> /*unused*/)
5093-> decltype(j.template get<T>(), void())
5094{
5095 for (std::size_t i = 0; i < N; ++i)
5096 {
5097 arr[i] = j.at(i).template get<T>();
5098 }
5099}
5100
5101template<typename BasicJsonType, typename ConstructibleArrayType,
5103 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5104 int> = 0>
5105auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
5106-> decltype(
5107 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
5108 j.template get<typename ConstructibleArrayType::value_type>(),
5109 void())
5110{
5111 using std::end;
5112
5113 ConstructibleArrayType ret;
5114 ret.reserve(j.size());
5115 std::transform(j.begin(), j.end(),
5116 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
5117 {
5118 // get<BasicJsonType>() returns *this, this won't call a from_json
5119 // method when value_type is BasicJsonType
5120 return i.template get<typename ConstructibleArrayType::value_type>();
5121 });
5122 arr = std::move(ret);
5123}
5124
5125template<typename BasicJsonType, typename ConstructibleArrayType,
5127 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5128 int> = 0>
5129inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
5130 priority_tag<0> /*unused*/)
5131{
5132 using std::end;
5133
5134 ConstructibleArrayType ret;
5135 std::transform(
5136 j.begin(), j.end(), std::inserter(ret, end(ret)),
5137 [](const BasicJsonType & i)
5138 {
5139 // get<BasicJsonType>() returns *this, this won't call a from_json
5140 // method when value_type is BasicJsonType
5141 return i.template get<typename ConstructibleArrayType::value_type>();
5142 });
5143 arr = std::move(ret);
5144}
5145
5146template < typename BasicJsonType, typename ConstructibleArrayType,
5147 enable_if_t <
5148 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
5149 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
5151 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
5152 !is_basic_json<ConstructibleArrayType>::value,
5153 int > = 0 >
5154auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
5155-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
5156j.template get<typename ConstructibleArrayType::value_type>(),
5157void())
5158{
5159 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5160 {
5161 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5162 }
5163
5164 from_json_array_impl(j, arr, priority_tag<3> {});
5165}
5166
5167template < typename BasicJsonType, typename T, std::size_t... Idx >
5168std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
5169 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
5170{
5171 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
5172}
5173
5174template < typename BasicJsonType, typename T, std::size_t N >
5175auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
5176-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
5177{
5178 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5179 {
5180 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5181 }
5182
5183 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
5184}
5185
5186template<typename BasicJsonType>
5187inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
5188{
5189 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
5190 {
5191 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
5192 }
5193
5194 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
5195}
5196
5197template<typename BasicJsonType, typename ConstructibleObjectType,
5198 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
5199inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
5200{
5201 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
5202 {
5203 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
5204 }
5205
5206 ConstructibleObjectType ret;
5207 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
5208 using value_type = typename ConstructibleObjectType::value_type;
5209 std::transform(
5210 inner_object->begin(), inner_object->end(),
5211 std::inserter(ret, ret.begin()),
5212 [](typename BasicJsonType::object_t::value_type const & p)
5213 {
5214 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
5215 });
5216 obj = std::move(ret);
5217}
5218
5219// overload for arithmetic types, not chosen for basic_json template arguments
5220// (BooleanType, etc.); note: Is it really necessary to provide explicit
5221// overloads for boolean_t etc. in case of a custom BooleanType which is not
5222// an arithmetic type?
5223template < typename BasicJsonType, typename ArithmeticType,
5224 enable_if_t <
5225 std::is_arithmetic<ArithmeticType>::value&&
5226 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
5227 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
5228 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
5229 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
5230 int > = 0 >
5231inline void from_json(const BasicJsonType& j, ArithmeticType& val)
5232{
5233 switch (static_cast<value_t>(j))
5234 {
5236 {
5237 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
5238 break;
5239 }
5241 {
5242 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5243 break;
5244 }
5246 {
5247 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5248 break;
5249 }
5250 case value_t::boolean:
5251 {
5252 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5253 break;
5254 }
5255
5256 case value_t::null:
5257 case value_t::object:
5258 case value_t::array:
5259 case value_t::string:
5260 case value_t::binary:
5261 case value_t::discarded:
5262 default:
5263 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5264 }
5265}
5266
5267template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5268std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5269{
5270 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5271}
5272
5273template<typename BasicJsonType>
5274std::tuple<> from_json_tuple_impl_base(BasicJsonType& /*unused*/, index_sequence<> /*unused*/)
5275{
5276 return {};
5277}
5278
5279template < typename BasicJsonType, class A1, class A2 >
5280std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5281{
5282 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5283 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5284}
5285
5286template<typename BasicJsonType, typename A1, typename A2>
5287inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5288{
5289 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5290}
5291
5292template<typename BasicJsonType, typename... Args>
5293std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5294{
5295 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5296}
5297
5298template<typename BasicJsonType, typename... Args>
5299inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5300{
5301 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5302}
5303
5304template<typename BasicJsonType, typename TupleRelated>
5305auto from_json(BasicJsonType&& j, TupleRelated&& t)
5306-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5307{
5308 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5309 {
5310 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5311 }
5312
5313 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5314}
5315
5316template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5317 typename = enable_if_t < !std::is_constructible <
5318 typename BasicJsonType::string_t, Key >::value >>
5319inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5320{
5321 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5322 {
5323 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5324 }
5325 m.clear();
5326 for (const auto& p : j)
5327 {
5328 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5329 {
5330 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5331 }
5332 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5333 }
5334}
5335
5336template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5337 typename = enable_if_t < !std::is_constructible <
5338 typename BasicJsonType::string_t, Key >::value >>
5339inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5340{
5341 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5342 {
5343 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5344 }
5345 m.clear();
5346 for (const auto& p : j)
5347 {
5348 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5349 {
5350 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5351 }
5352 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5353 }
5354}
5355
5356#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5357template<typename BasicJsonType>
5358inline void from_json(const BasicJsonType& j, std_fs::path& p)
5359{
5360 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5361 {
5362 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5363 }
5364 const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5365 // Checking for C++20 standard or later can be insufficient in case the
5366 // library support for char8_t is either incomplete or was disabled
5367 // altogether. Use the __cpp_lib_char8_t feature test instead.
5368#if defined(__cpp_lib_char8_t) && (__cpp_lib_char8_t >= 201907L)
5369 p = std_fs::path(std::u8string_view(reinterpret_cast<const char8_t*>(s.data()), s.size()));
5370#else
5371 p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20
5372#endif
5373}
5374#endif
5375
5377{
5378 template<typename BasicJsonType, typename T>
5379 auto operator()(const BasicJsonType& j, T&& val) const
5380 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5381 -> decltype(from_json(j, std::forward<T>(val)))
5382 {
5383 return from_json(j, std::forward<T>(val));
5384 }
5385};
5386
5387} // namespace detail
5388
5389#ifndef JSON_HAS_CPP_17
5390/// namespace to hold default `from_json` function
5391/// to see why this is required:
5392/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
5393namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5394{
5395#endif
5396JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5398#ifndef JSON_HAS_CPP_17
5399} // namespace
5400#endif
5401
5403
5404// #include <nlohmann/detail/conversions/to_json.hpp>
5405// __ _____ _____ _____
5406// __| | __| | | | JSON for Modern C++
5407// | | |__ | | | | | | version 3.12.0
5408// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5409//
5410// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5411// SPDX-License-Identifier: MIT
5412
5413
5414
5415// #include <nlohmann/detail/macro_scope.hpp>
5416// JSON_HAS_CPP_17
5417#ifdef JSON_HAS_CPP_17
5418 #include <optional> // optional
5419#endif
5420
5421#include <algorithm> // copy
5422#include <iterator> // begin, end
5423#include <memory> // allocator_traits
5424#include <string> // basic_string, char_traits
5425#include <tuple> // tuple, get
5426#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5427#include <utility> // move, forward, declval, pair
5428#include <valarray> // valarray
5429#include <vector> // vector
5430
5431// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5432// __ _____ _____ _____
5433// __| | __| | | | JSON for Modern C++
5434// | | |__ | | | | | | version 3.12.0
5435// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5436//
5437// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5438// SPDX-License-Identifier: MIT
5439
5440
5441
5442#include <cstddef> // size_t
5443#include <iterator> // forward_iterator_tag
5444#include <tuple> // tuple_size, get, tuple_element
5445#include <utility> // move
5446
5447#if JSON_HAS_RANGES
5448 #include <ranges> // enable_borrowed_range
5449#endif
5450
5451// #include <nlohmann/detail/abi_macros.hpp>
5452
5453// #include <nlohmann/detail/meta/type_traits.hpp>
5454
5455// #include <nlohmann/detail/string_utils.hpp>
5456// __ _____ _____ _____
5457// __| | __| | | | JSON for Modern C++
5458// | | |__ | | | | | | version 3.12.0
5459// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5460//
5461// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5462// SPDX-License-Identifier: MIT
5463
5464
5465
5466#include <cstddef> // size_t
5467#include <string> // string, to_string
5468
5469// #include <nlohmann/detail/abi_macros.hpp>
5470
5471
5473namespace detail
5474{
5475
5476template<typename StringType>
5477void int_to_string(StringType& target, std::size_t value)
5478{
5479 // For ADL
5480 using std::to_string;
5481 target = to_string(value);
5482}
5483
5484template<typename StringType>
5485StringType to_string(std::size_t value)
5486{
5487 StringType result;
5488 int_to_string(result, value);
5489 return result;
5490}
5491
5492} // namespace detail
5494
5495// #include <nlohmann/detail/value_t.hpp>
5496
5497
5499namespace detail
5500{
5501
5502template<typename IteratorType> class iteration_proxy_value
5503{
5504 public:
5505 using difference_type = std::ptrdiff_t;
5509 using iterator_category = std::forward_iterator_tag;
5510 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5511
5512 private:
5513 /// the iterator
5514 IteratorType anchor{};
5515 /// an index for arrays (used to create key names)
5516 std::size_t array_index = 0;
5517 /// last stringified array index
5518 mutable std::size_t array_index_last = 0;
5519 /// a string representation of the array index
5521 /// an empty string (to return a reference for primitive values)
5523
5524 public:
5525 explicit iteration_proxy_value() = default;
5526 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5527 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5528 && std::is_nothrow_default_constructible<string_type>::value)
5529 : anchor(std::move(it))
5530 , array_index(array_index_)
5531 {}
5532
5535 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5537 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5538 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5540 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5541 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5543
5544 /// dereference operator (needed for range-based for)
5545 const iteration_proxy_value& operator*() const
5546 {
5547 return *this;
5548 }
5549
5550 /// increment operator (needed for range-based for)
5552 {
5553 ++anchor;
5554 ++array_index;
5555
5556 return *this;
5557 }
5558
5559 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5560 {
5562 ++anchor;
5563 ++array_index;
5564 return tmp;
5565 }
5566
5567 /// equality operator (needed for InputIterator)
5569 {
5570 return anchor == o.anchor;
5571 }
5572
5573 /// inequality operator (needed for range-based for)
5575 {
5576 return anchor != o.anchor;
5577 }
5578
5579 /// return key of the iterator
5580 const string_type& key() const
5581 {
5582 JSON_ASSERT(anchor.m_object != nullptr);
5583
5584 switch (anchor.m_object->type())
5585 {
5586 // use integer array index as key
5587 case value_t::array:
5588 {
5590 {
5593 }
5594 return array_index_str;
5595 }
5596
5597 // use key from the object
5598 case value_t::object:
5599 return anchor.key();
5600
5601 // use an empty key for all primitive types
5602 case value_t::null:
5603 case value_t::string:
5604 case value_t::boolean:
5608 case value_t::binary:
5609 case value_t::discarded:
5610 default:
5611 return empty_str;
5612 }
5613 }
5614
5615 /// return value of the iterator
5616 typename IteratorType::reference value() const
5617 {
5618 return anchor.value();
5619 }
5620};
5621
5622/// proxy class for the items() function
5623template<typename IteratorType> class iteration_proxy
5624{
5625 private:
5626 /// the container to iterate
5627 typename IteratorType::pointer container = nullptr;
5628
5629 public:
5630 explicit iteration_proxy() = default;
5631
5632 /// construct iteration proxy from a container
5633 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5634 : container(&cont) {}
5635
5638 iteration_proxy(iteration_proxy&&) noexcept = default;
5639 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5640 ~iteration_proxy() = default;
5641
5642 /// return iterator begin (needed for range-based for)
5643 iteration_proxy_value<IteratorType> begin() const noexcept
5644 {
5646 }
5647
5648 /// return iterator end (needed for range-based for)
5653};
5654
5655// Structured Bindings Support
5656// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5657// And see https://github.com/nlohmann/json/pull/1391
5658template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5659auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5660{
5661 return i.key();
5662}
5663// Structured Bindings Support
5664// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5665// And see https://github.com/nlohmann/json/pull/1391
5666template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5667auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5668{
5669 return i.value();
5670}
5671
5672} // namespace detail
5674
5675// The Addition to the STD Namespace is required to add
5676// Structured Bindings Support to the iteration_proxy_value class
5677// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5678// And see https://github.com/nlohmann/json/pull/1391
5679namespace std
5680{
5681
5682#if defined(__clang__)
5683 // Fix: https://github.com/nlohmann/json/issues/1401
5684 #pragma clang diagnostic push
5685 #pragma clang diagnostic ignored "-Wmismatched-tags"
5686#endif
5687template<typename IteratorType>
5688class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5689 : public std::integral_constant<std::size_t, 2> {};
5690
5691template<std::size_t N, typename IteratorType>
5692class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5693{
5694 public:
5695 using type = decltype(
5696 get<N>(std::declval <
5697 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5698};
5699#if defined(__clang__)
5700 #pragma clang diagnostic pop
5701#endif
5702
5703} // namespace std
5704
5705#if JSON_HAS_RANGES
5706 template <typename IteratorType>
5707 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5708#endif
5709
5710// #include <nlohmann/detail/meta/cpp_future.hpp>
5711
5712// #include <nlohmann/detail/meta/std_fs.hpp>
5713
5714// #include <nlohmann/detail/meta/type_traits.hpp>
5715
5716// #include <nlohmann/detail/value_t.hpp>
5717
5718
5720namespace detail
5721{
5722
5723//////////////////
5724// constructors //
5725//////////////////
5726
5727/*
5728 * Note all external_constructor<>::construct functions need to call
5729 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5730 * allocated value (e.g., a string). See bug issue
5731 * https://github.com/nlohmann/json/issues/2865 for more information.
5732 */
5733
5734template<value_t> struct external_constructor;
5735
5736template<>
5738{
5739 template<typename BasicJsonType>
5740 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5741 {
5742 j.m_data.m_value.destroy(j.m_data.m_type);
5743 j.m_data.m_type = value_t::boolean;
5744 j.m_data.m_value = b;
5745 j.assert_invariant();
5746 }
5747};
5748
5749template<>
5751{
5752 template<typename BasicJsonType>
5753 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5754 {
5755 j.m_data.m_value.destroy(j.m_data.m_type);
5756 j.m_data.m_type = value_t::string;
5757 j.m_data.m_value = s;
5758 j.assert_invariant();
5759 }
5760
5761 template<typename BasicJsonType>
5762 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5763 {
5764 j.m_data.m_value.destroy(j.m_data.m_type);
5765 j.m_data.m_type = value_t::string;
5766 j.m_data.m_value = std::move(s);
5767 j.assert_invariant();
5768 }
5769
5770 template < typename BasicJsonType, typename CompatibleStringType,
5771 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5772 int > = 0 >
5773 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5774 {
5775 j.m_data.m_value.destroy(j.m_data.m_type);
5776 j.m_data.m_type = value_t::string;
5777 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5778 j.assert_invariant();
5779 }
5780};
5781
5782template<>
5784{
5785 template<typename BasicJsonType>
5786 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5787 {
5788 j.m_data.m_value.destroy(j.m_data.m_type);
5789 j.m_data.m_type = value_t::binary;
5790 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5791 j.assert_invariant();
5792 }
5793
5794 template<typename BasicJsonType>
5795 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5796 {
5797 j.m_data.m_value.destroy(j.m_data.m_type);
5798 j.m_data.m_type = value_t::binary;
5799 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5800 j.assert_invariant();
5801 }
5802};
5803
5804template<>
5806{
5807 template<typename BasicJsonType>
5808 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5809 {
5810 j.m_data.m_value.destroy(j.m_data.m_type);
5811 j.m_data.m_type = value_t::number_float;
5812 j.m_data.m_value = val;
5813 j.assert_invariant();
5814 }
5815};
5816
5817template<>
5819{
5820 template<typename BasicJsonType>
5821 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5822 {
5823 j.m_data.m_value.destroy(j.m_data.m_type);
5824 j.m_data.m_type = value_t::number_unsigned;
5825 j.m_data.m_value = val;
5826 j.assert_invariant();
5827 }
5828};
5829
5830template<>
5832{
5833 template<typename BasicJsonType>
5834 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5835 {
5836 j.m_data.m_value.destroy(j.m_data.m_type);
5837 j.m_data.m_type = value_t::number_integer;
5838 j.m_data.m_value = val;
5839 j.assert_invariant();
5840 }
5841};
5842
5843template<>
5845{
5846 template<typename BasicJsonType>
5847 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5848 {
5849 j.m_data.m_value.destroy(j.m_data.m_type);
5850 j.m_data.m_type = value_t::array;
5851 j.m_data.m_value = arr;
5852 j.set_parents();
5853 j.assert_invariant();
5854 }
5855
5856 template<typename BasicJsonType>
5857 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5858 {
5859 j.m_data.m_value.destroy(j.m_data.m_type);
5860 j.m_data.m_type = value_t::array;
5861 j.m_data.m_value = std::move(arr);
5862 j.set_parents();
5863 j.assert_invariant();
5864 }
5865
5866 template < typename BasicJsonType, typename CompatibleArrayType,
5867 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5868 int > = 0 >
5869 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5870 {
5871 using std::begin;
5872 using std::end;
5873
5874 j.m_data.m_value.destroy(j.m_data.m_type);
5875 j.m_data.m_type = value_t::array;
5876 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5877 j.set_parents();
5878 j.assert_invariant();
5879 }
5880
5881 template<typename BasicJsonType>
5882 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5883 {
5884 j.m_data.m_value.destroy(j.m_data.m_type);
5885 j.m_data.m_type = value_t::array;
5886 j.m_data.m_value = value_t::array;
5887 j.m_data.m_value.array->reserve(arr.size());
5888 for (const bool x : arr)
5889 {
5890 j.m_data.m_value.array->push_back(x);
5891 j.set_parent(j.m_data.m_value.array->back());
5892 }
5893 j.assert_invariant();
5894 }
5895
5896 template<typename BasicJsonType, typename T,
5898 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5899 {
5900 j.m_data.m_value.destroy(j.m_data.m_type);
5901 j.m_data.m_type = value_t::array;
5902 j.m_data.m_value = value_t::array;
5903 j.m_data.m_value.array->resize(arr.size());
5904 if (arr.size() > 0)
5905 {
5906 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5907 }
5908 j.set_parents();
5909 j.assert_invariant();
5910 }
5911};
5912
5913template<>
5915{
5916 template<typename BasicJsonType>
5917 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5918 {
5919 j.m_data.m_value.destroy(j.m_data.m_type);
5920 j.m_data.m_type = value_t::object;
5921 j.m_data.m_value = obj;
5922 j.set_parents();
5923 j.assert_invariant();
5924 }
5925
5926 template<typename BasicJsonType>
5927 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5928 {
5929 j.m_data.m_value.destroy(j.m_data.m_type);
5930 j.m_data.m_type = value_t::object;
5931 j.m_data.m_value = std::move(obj);
5932 j.set_parents();
5933 j.assert_invariant();
5934 }
5935
5936 template < typename BasicJsonType, typename CompatibleObjectType,
5937 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5938 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5939 {
5940 using std::begin;
5941 using std::end;
5942
5943 j.m_data.m_value.destroy(j.m_data.m_type);
5944 j.m_data.m_type = value_t::object;
5945 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5946 j.set_parents();
5947 j.assert_invariant();
5948 }
5949};
5950
5951/////////////
5952// to_json //
5953/////////////
5954
5955#ifdef JSON_HAS_CPP_17
5956template<typename BasicJsonType, typename T,
5957 enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
5958void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept
5959{
5960 if (opt.has_value())
5961 {
5962 j = *opt;
5963 }
5964 else
5965 {
5966 j = nullptr;
5967 }
5968}
5969#endif
5970
5971template<typename BasicJsonType, typename T,
5972 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5973inline void to_json(BasicJsonType& j, T b) noexcept
5974{
5976}
5977
5978template < typename BasicJsonType, typename BoolRef,
5979 enable_if_t <
5980 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5981 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5982 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5983 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5984 typename BasicJsonType::boolean_t >::value))
5985 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5986inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5987{
5988 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5989}
5990
5991template<typename BasicJsonType, typename CompatibleString,
5992 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5993inline void to_json(BasicJsonType& j, const CompatibleString& s)
5994{
5996}
5997
5998template<typename BasicJsonType>
5999inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
6000{
6002}
6003
6004template<typename BasicJsonType, typename FloatType,
6005 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
6006inline void to_json(BasicJsonType& j, FloatType val) noexcept
6007{
6008 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
6009}
6010
6011template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
6012 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
6013inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
6014{
6015 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
6016}
6017
6018template<typename BasicJsonType, typename CompatibleNumberIntegerType,
6019 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
6020inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
6021{
6022 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
6023}
6024
6025#if !JSON_DISABLE_ENUM_SERIALIZATION
6026template<typename BasicJsonType, typename EnumType,
6027 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
6028inline void to_json(BasicJsonType& j, EnumType e) noexcept
6029{
6030 using underlying_type = typename std::underlying_type<EnumType>::type;
6031 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
6032 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
6033}
6034#endif // JSON_DISABLE_ENUM_SERIALIZATION
6035
6036template<typename BasicJsonType>
6037inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
6038{
6040}
6041
6042template < typename BasicJsonType, typename CompatibleArrayType,
6043 enable_if_t < is_compatible_array_type<BasicJsonType,
6044 CompatibleArrayType>::value&&
6045 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
6047 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
6048 !is_basic_json<CompatibleArrayType>::value,
6049 int > = 0 >
6050inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
6051{
6053}
6054
6055template<typename BasicJsonType>
6056inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
6057{
6059}
6060
6061template<typename BasicJsonType, typename T,
6062 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
6063inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
6064{
6066}
6067
6068template<typename BasicJsonType>
6069inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
6070{
6072}
6073
6074template < typename BasicJsonType, typename CompatibleObjectType,
6075 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
6076inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
6077{
6079}
6080
6081template<typename BasicJsonType>
6082inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
6083{
6085}
6086
6087template <
6088 typename BasicJsonType, typename T, std::size_t N,
6089 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
6090 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6091 int > = 0 >
6092inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6093{
6095}
6096
6097template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
6098inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
6099{
6100 j = { p.first, p.second };
6101}
6102
6103// for https://github.com/nlohmann/json/pull/1134
6104template<typename BasicJsonType, typename T,
6105 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
6106inline void to_json(BasicJsonType& j, const T& b)
6107{
6108 j = { {b.key(), b.value()} };
6109}
6110
6111template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
6112inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
6113{
6114 j = { std::get<Idx>(t)... };
6115}
6116
6117template<typename BasicJsonType, typename Tuple>
6118inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& /*unused*/, index_sequence<> /*unused*/)
6119{
6120 using array_t = typename BasicJsonType::array_t;
6121 j = array_t();
6122}
6123
6124template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
6125inline void to_json(BasicJsonType& j, const T& t)
6126{
6127 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
6128}
6129
6130#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
6131#if defined(__cpp_lib_char8_t)
6132template<typename BasicJsonType, typename Tr, typename Allocator>
6133inline void to_json(BasicJsonType& j, const std::basic_string<char8_t, Tr, Allocator>& s)
6134{
6135 using OtherAllocator = typename std::allocator_traits<Allocator>::template rebind_alloc<char>;
6136 j = std::basic_string<char, std::char_traits<char>, OtherAllocator>(s.begin(), s.end(), s.get_allocator());
6137}
6138#endif
6139
6140template<typename BasicJsonType>
6141inline void to_json(BasicJsonType& j, const std_fs::path& p)
6142{
6143 // Returns either a std::string or a std::u8string depending whether library
6144 // support for char8_t is enabled.
6145 j = p.u8string();
6146}
6147#endif
6148
6150{
6151 template<typename BasicJsonType, typename T>
6152 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
6153 -> decltype(to_json(j, std::forward<T>(val)), void())
6154 {
6155 return to_json(j, std::forward<T>(val));
6156 }
6157};
6158} // namespace detail
6159
6160#ifndef JSON_HAS_CPP_17
6161/// namespace to hold default `to_json` function
6162/// to see why this is required:
6163/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
6164namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
6165{
6166#endif
6167JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
6169#ifndef JSON_HAS_CPP_17
6170} // namespace
6171#endif
6172
6174
6175// #include <nlohmann/detail/meta/identity_tag.hpp>
6176
6177
6179
6180/// @sa https://json.nlohmann.me/api/adl_serializer/
6181template<typename ValueType, typename>
6183{
6184 /// @brief convert a JSON value to any value type
6185 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
6186 template<typename BasicJsonType, typename TargetType = ValueType>
6187 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
6188 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
6189 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
6190 {
6191 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
6192 }
6193
6194 /// @brief convert a JSON value to any value type
6195 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
6196 template<typename BasicJsonType, typename TargetType = ValueType>
6197 static auto from_json(BasicJsonType && j) noexcept(
6198 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
6199 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
6200 {
6201 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
6202 }
6203
6204 /// @brief convert any value type to a JSON value
6205 /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
6206 template<typename BasicJsonType, typename TargetType = ValueType>
6207 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
6208 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
6209 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
6210 {
6211 ::nlohmann::to_json(j, std::forward<TargetType>(val));
6212 }
6213};
6214
6216
6217// #include <nlohmann/byte_container_with_subtype.hpp>
6218// __ _____ _____ _____
6219// __| | __| | | | JSON for Modern C++
6220// | | |__ | | | | | | version 3.12.0
6221// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6222//
6223// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6224// SPDX-License-Identifier: MIT
6225
6226
6227
6228#include <cstdint> // uint8_t, uint64_t
6229#include <tuple> // tie
6230#include <utility> // move
6231
6232// #include <nlohmann/detail/abi_macros.hpp>
6233
6234
6236
6237/// @brief an internal type for a backed binary type
6238/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
6239template<typename BinaryType>
6241{
6242 public:
6244 using subtype_type = std::uint64_t;
6245
6246 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
6248 : container_type()
6249 {}
6250
6251 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
6253 : container_type(b)
6254 {}
6255
6256 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
6257 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
6258 : container_type(std::move(b))
6259 {}
6260
6261 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
6263 : container_type(b)
6264 , m_subtype(subtype_)
6265 , m_has_subtype(true)
6266 {}
6267
6268 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
6269 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
6270 : container_type(std::move(b))
6271 , m_subtype(subtype_)
6272 , m_has_subtype(true)
6273 {}
6274
6276 {
6277 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
6278 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
6279 }
6280
6282 {
6283 return !(rhs == *this);
6284 }
6285
6286 /// @brief sets the binary subtype
6287 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
6288 void set_subtype(subtype_type subtype_) noexcept
6289 {
6290 m_subtype = subtype_;
6291 m_has_subtype = true;
6292 }
6293
6294 /// @brief return the binary subtype
6295 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
6296 constexpr subtype_type subtype() const noexcept
6297 {
6298 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
6299 }
6300
6301 /// @brief return whether the value has a subtype
6302 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
6303 constexpr bool has_subtype() const noexcept
6304 {
6305 return m_has_subtype;
6306 }
6307
6308 /// @brief clears the binary subtype
6309 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
6310 void clear_subtype() noexcept
6311 {
6312 m_subtype = 0;
6313 m_has_subtype = false;
6314 }
6315
6316 private:
6318 bool m_has_subtype = false;
6319};
6320
6322
6323// #include <nlohmann/detail/conversions/from_json.hpp>
6324
6325// #include <nlohmann/detail/conversions/to_json.hpp>
6326
6327// #include <nlohmann/detail/exceptions.hpp>
6328
6329// #include <nlohmann/detail/hash.hpp>
6330// __ _____ _____ _____
6331// __| | __| | | | JSON for Modern C++
6332// | | |__ | | | | | | version 3.12.0
6333// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6334//
6335// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6336// SPDX-License-Identifier: MIT
6337
6338
6339
6340#include <cstdint> // uint8_t
6341#include <cstddef> // size_t
6342#include <functional> // hash
6343
6344// #include <nlohmann/detail/abi_macros.hpp>
6345
6346// #include <nlohmann/detail/value_t.hpp>
6347
6348
6350namespace detail
6351{
6352
6353// boost::hash_combine
6354inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6355{
6356 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6357 return seed;
6358}
6359
6360/*!
6361@brief hash a JSON value
6362
6363The hash function tries to rely on std::hash where possible. Furthermore, the
6364type of the JSON value is taken into account to have different hash values for
6365null, 0, 0U, and false, etc.
6366
6367@tparam BasicJsonType basic_json specialization
6368@param j JSON value to hash
6369@return hash value of j
6370*/
6371template<typename BasicJsonType>
6372std::size_t hash(const BasicJsonType& j)
6373{
6374 using string_t = typename BasicJsonType::string_t;
6375 using number_integer_t = typename BasicJsonType::number_integer_t;
6376 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6377 using number_float_t = typename BasicJsonType::number_float_t;
6378
6379 const auto type = static_cast<std::size_t>(j.type());
6380 switch (j.type())
6381 {
6382 case BasicJsonType::value_t::null:
6383 case BasicJsonType::value_t::discarded:
6384 {
6385 return combine(type, 0);
6386 }
6387
6388 case BasicJsonType::value_t::object:
6389 {
6390 auto seed = combine(type, j.size());
6391 for (const auto& element : j.items())
6392 {
6393 const auto h = std::hash<string_t> {}(element.key());
6394 seed = combine(seed, h);
6395 seed = combine(seed, hash(element.value()));
6396 }
6397 return seed;
6398 }
6399
6400 case BasicJsonType::value_t::array:
6401 {
6402 auto seed = combine(type, j.size());
6403 for (const auto& element : j)
6404 {
6405 seed = combine(seed, hash(element));
6406 }
6407 return seed;
6408 }
6409
6410 case BasicJsonType::value_t::string:
6411 {
6412 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6413 return combine(type, h);
6414 }
6415
6416 case BasicJsonType::value_t::boolean:
6417 {
6418 const auto h = std::hash<bool> {}(j.template get<bool>());
6419 return combine(type, h);
6420 }
6421
6422 case BasicJsonType::value_t::number_integer:
6423 {
6424 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6425 return combine(type, h);
6426 }
6427
6428 case BasicJsonType::value_t::number_unsigned:
6429 {
6430 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6431 return combine(type, h);
6432 }
6433
6434 case BasicJsonType::value_t::number_float:
6435 {
6436 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6437 return combine(type, h);
6438 }
6439
6440 case BasicJsonType::value_t::binary:
6441 {
6442 auto seed = combine(type, j.get_binary().size());
6443 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6444 seed = combine(seed, h);
6445 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6446 for (const auto byte : j.get_binary())
6447 {
6448 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6449 }
6450 return seed;
6451 }
6452
6453 default: // LCOV_EXCL_LINE
6454 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6455 return 0; // LCOV_EXCL_LINE
6456 }
6457}
6458
6459} // namespace detail
6461
6462// #include <nlohmann/detail/input/binary_reader.hpp>
6463// __ _____ _____ _____
6464// __| | __| | | | JSON for Modern C++
6465// | | |__ | | | | | | version 3.12.0
6466// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6467//
6468// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6469// SPDX-License-Identifier: MIT
6470
6471
6472
6473#include <algorithm> // generate_n
6474#include <array> // array
6475#include <cmath> // ldexp
6476#include <cstddef> // size_t
6477#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6478#include <cstdio> // snprintf
6479#include <cstring> // memcpy
6480#include <iterator> // back_inserter
6481#include <limits> // numeric_limits
6482#include <string> // char_traits, string
6483#include <utility> // make_pair, move
6484#include <vector> // vector
6485#ifdef __cpp_lib_byteswap
6486 #include <bit> //byteswap
6487#endif
6488
6489// #include <nlohmann/detail/exceptions.hpp>
6490
6491// #include <nlohmann/detail/input/input_adapters.hpp>
6492// __ _____ _____ _____
6493// __| | __| | | | JSON for Modern C++
6494// | | |__ | | | | | | version 3.12.0
6495// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6496//
6497// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6498// SPDX-License-Identifier: MIT
6499
6500
6501
6502#include <array> // array
6503#include <cstddef> // size_t
6504#include <cstring> // strlen
6505#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6506#include <memory> // shared_ptr, make_shared, addressof
6507#include <numeric> // accumulate
6508#include <streambuf> // streambuf
6509#include <string> // string, char_traits
6510#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6511#include <utility> // pair, declval
6512
6513#ifndef JSON_NO_IO
6514 #include <cstdio> // FILE *
6515 #include <istream> // istream
6516#endif // JSON_NO_IO
6517
6518// #include <nlohmann/detail/exceptions.hpp>
6519
6520// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6521
6522// #include <nlohmann/detail/macro_scope.hpp>
6523
6524// #include <nlohmann/detail/meta/type_traits.hpp>
6525
6526
6528namespace detail
6529{
6530
6531/// the supported input formats
6533
6534////////////////////
6535// input adapters //
6536////////////////////
6537
6538#ifndef JSON_NO_IO
6539/*!
6540Input adapter for stdio file access. This adapter read only 1 byte and do not use any
6541 buffer. This adapter is a very low level adapter.
6542*/
6544{
6545 public:
6546 using char_type = char;
6547
6549 explicit file_input_adapter(std::FILE* f) noexcept
6550 : m_file(f)
6551 {
6552 JSON_ASSERT(m_file != nullptr);
6553 }
6554
6555 // make class move-only
6561
6562 std::char_traits<char>::int_type get_character() noexcept
6563 {
6564 return std::fgetc(m_file);
6565 }
6566
6567 // returns the number of characters successfully read
6568 template<class T>
6569 std::size_t get_elements(T* dest, std::size_t count = 1)
6570 {
6571 return fread(dest, 1, sizeof(T) * count, m_file);
6572 }
6573
6574 private:
6575 /// the file pointer to read from
6576 std::FILE* m_file;
6577};
6578
6579/*!
6580Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
6581beginning of input. Does not support changing the underlying std::streambuf
6582in mid-input. Maintains underlying std::istream and std::streambuf to support
6583subsequent use of standard std::istream operations to process any input
6584characters following those used in parsing the JSON input. Clears the
6585std::istream flags; any input errors (e.g., EOF) will be detected by the first
6586subsequent call for input from the std::istream.
6587*/
6589{
6590 public:
6591 using char_type = char;
6592
6594 {
6595 // clear stream flags; we use underlying streambuf I/O, do not
6596 // maintain ifstream flags, except eof
6597 if (is != nullptr)
6598 {
6599 is->clear(is->rdstate() & std::ios::eofbit);
6600 }
6601 }
6602
6603 explicit input_stream_adapter(std::istream& i)
6604 : is(&i), sb(i.rdbuf())
6605 {}
6606
6607 // deleted because of pointer members
6611
6613 : is(rhs.is), sb(rhs.sb)
6614 {
6615 rhs.is = nullptr;
6616 rhs.sb = nullptr;
6617 }
6618
6619 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6620 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6621 // end up as the same value, e.g., 0xFFFFFFFF.
6622 std::char_traits<char>::int_type get_character()
6623 {
6624 auto res = sb->sbumpc();
6625 // set eof manually, as we don't use the istream interface.
6626 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6627 {
6628 is->clear(is->rdstate() | std::ios::eofbit);
6629 }
6630 return res;
6631 }
6632
6633 template<class T>
6634 std::size_t get_elements(T* dest, std::size_t count = 1)
6635 {
6636 auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
6637 if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T)))
6638 {
6639 is->clear(is->rdstate() | std::ios::eofbit);
6640 }
6641 return res;
6642 }
6643
6644 private:
6645 /// the associated input stream
6646 std::istream* is = nullptr;
6647 std::streambuf* sb = nullptr;
6648};
6649#endif // JSON_NO_IO
6650
6651// General-purpose iterator-based adapter. It might not be as fast as
6652// theoretically possible for some containers, but it is extremely versatile.
6653template<typename IteratorType>
6655{
6656 public:
6657 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6658
6659 iterator_input_adapter(IteratorType first, IteratorType last)
6660 : current(std::move(first)), end(std::move(last))
6661 {}
6662
6664 {
6666 {
6668 std::advance(current, 1);
6669 return result;
6670 }
6671
6673 }
6674
6675 // for general iterators, we cannot really do something better than falling back to processing the range one-by-one
6676 template<class T>
6677 std::size_t get_elements(T* dest, std::size_t count = 1)
6678 {
6679 auto* ptr = reinterpret_cast<char*>(dest);
6680 for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index)
6681 {
6683 {
6684 ptr[read_index] = static_cast<char>(*current);
6685 std::advance(current, 1);
6686 }
6687 else
6688 {
6689 return read_index;
6690 }
6691 }
6692 return count * sizeof(T);
6693 }
6694
6695 private:
6696 IteratorType current;
6697 IteratorType end;
6698
6699 template<typename BaseInputAdapter, size_t T>
6701
6702 bool empty() const
6703 {
6704 return current == end;
6705 }
6706};
6707
6708template<typename BaseInputAdapter, size_t T>
6710
6711template<typename BaseInputAdapter>
6712struct wide_string_input_helper<BaseInputAdapter, 4>
6713{
6714 // UTF-32
6715 static void fill_buffer(BaseInputAdapter& input,
6716 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6717 size_t& utf8_bytes_index,
6718 size_t& utf8_bytes_filled)
6719 {
6720 utf8_bytes_index = 0;
6721
6722 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6723 {
6724 utf8_bytes[0] = std::char_traits<char>::eof();
6725 utf8_bytes_filled = 1;
6726 }
6727 else
6728 {
6729 // get the current character
6730 const auto wc = input.get_character();
6731
6732 // UTF-32 to UTF-8 encoding
6733 if (wc < 0x80)
6734 {
6735 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6736 utf8_bytes_filled = 1;
6737 }
6738 else if (wc <= 0x7FF)
6739 {
6740 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6741 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6742 utf8_bytes_filled = 2;
6743 }
6744 else if (wc <= 0xFFFF)
6745 {
6746 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6747 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6748 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6749 utf8_bytes_filled = 3;
6750 }
6751 else if (wc <= 0x10FFFF)
6752 {
6753 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6754 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6755 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6756 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6757 utf8_bytes_filled = 4;
6758 }
6759 else
6760 {
6761 // unknown character
6762 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6763 utf8_bytes_filled = 1;
6764 }
6765 }
6766 }
6767};
6768
6769template<typename BaseInputAdapter>
6770struct wide_string_input_helper<BaseInputAdapter, 2>
6771{
6772 // UTF-16
6773 static void fill_buffer(BaseInputAdapter& input,
6774 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6775 size_t& utf8_bytes_index,
6776 size_t& utf8_bytes_filled)
6777 {
6778 utf8_bytes_index = 0;
6779
6780 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6781 {
6782 utf8_bytes[0] = std::char_traits<char>::eof();
6783 utf8_bytes_filled = 1;
6784 }
6785 else
6786 {
6787 // get the current character
6788 const auto wc = input.get_character();
6789
6790 // UTF-16 to UTF-8 encoding
6791 if (wc < 0x80)
6792 {
6793 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6794 utf8_bytes_filled = 1;
6795 }
6796 else if (wc <= 0x7FF)
6797 {
6798 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6799 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6800 utf8_bytes_filled = 2;
6801 }
6802 else if (0xD800 > wc || wc >= 0xE000)
6803 {
6804 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6805 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6806 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6807 utf8_bytes_filled = 3;
6808 }
6809 else
6810 {
6811 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6812 {
6813 const auto wc2 = static_cast<unsigned int>(input.get_character());
6814 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6815 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6816 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6817 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6818 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6819 utf8_bytes_filled = 4;
6820 }
6821 else
6822 {
6823 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6824 utf8_bytes_filled = 1;
6825 }
6826 }
6827 }
6828 }
6829};
6830
6831// Wraps another input adapter to convert wide character types into individual bytes.
6832template<typename BaseInputAdapter, typename WideCharType>
6834{
6835 public:
6836 using char_type = char;
6837
6838 wide_string_input_adapter(BaseInputAdapter base)
6839 : base_adapter(base) {}
6840
6841 typename std::char_traits<char>::int_type get_character() noexcept
6842 {
6843 // check if the buffer needs to be filled
6845 {
6846 fill_buffer<sizeof(WideCharType)>();
6847
6850 }
6851
6852 // use buffer
6855 return utf8_bytes[utf8_bytes_index++];
6856 }
6857
6858 // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
6859 template<class T>
6860 std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
6861 {
6862 JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
6863 }
6864
6865 private:
6866 BaseInputAdapter base_adapter;
6867
6868 template<size_t T>
6873
6874 /// a buffer for UTF-8 bytes
6875 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6876
6877 /// index to the utf8_codes array for the next valid byte
6878 std::size_t utf8_bytes_index = 0;
6879 /// number of valid bytes in the utf8_codes array
6880 std::size_t utf8_bytes_filled = 0;
6881};
6882
6883template<typename IteratorType, typename Enable = void>
6885{
6886 using iterator_type = IteratorType;
6887 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6889
6890 static adapter_type create(IteratorType first, IteratorType last)
6891 {
6892 return adapter_type(std::move(first), std::move(last));
6893 }
6894};
6895
6896template<typename T>
6898{
6899 using value_type = typename std::iterator_traits<T>::value_type;
6900 enum
6901 {
6902 value = sizeof(value_type) > 1
6903 };
6904};
6905
6906template<typename IteratorType>
6908{
6909 using iterator_type = IteratorType;
6910 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6913
6914 static adapter_type create(IteratorType first, IteratorType last)
6915 {
6916 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6917 }
6918};
6919
6920// General purpose iterator-based input
6921template<typename IteratorType>
6923{
6925 return factory_type::create(first, last);
6926}
6927
6928// Convenience shorthand from container to iterator
6929// Enables ADL on begin(container) and end(container)
6930// Encloses the using declarations in namespace for not to leak them to outside scope
6931
6932namespace container_input_adapter_factory_impl
6933{
6934
6935using std::begin;
6936using std::end;
6937
6938template<typename ContainerType, typename Enable = void>
6940
6941template<typename ContainerType>
6943 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6944 {
6945 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6946
6947 static adapter_type create(const ContainerType& container)
6948{
6949 return input_adapter(begin(container), end(container));
6950}
6951 };
6952
6953} // namespace container_input_adapter_factory_impl
6954
6955template<typename ContainerType>
6960
6961// specialization for std::string
6962using string_input_adapter_type = decltype(input_adapter(std::declval<std::string>()));
6963
6964#ifndef JSON_NO_IO
6965// Special cases with fast paths
6966inline file_input_adapter input_adapter(std::FILE* file)
6967{
6968 if (file == nullptr)
6969 {
6970 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));
6971 }
6972 return file_input_adapter(file);
6973}
6974
6975inline input_stream_adapter input_adapter(std::istream& stream)
6976{
6977 return input_stream_adapter(stream);
6978}
6979
6980inline input_stream_adapter input_adapter(std::istream&& stream)
6981{
6982 return input_stream_adapter(stream);
6983}
6984#endif // JSON_NO_IO
6985
6986using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6987
6988// Null-delimited strings, and the like.
6989template < typename CharT,
6990 typename std::enable_if <
6991 std::is_pointer<CharT>::value&&
6992 !std::is_array<CharT>::value&&
6993 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6994 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6995 int >::type = 0 >
6997{
6998 if (b == nullptr)
6999 {
7000 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));
7001 }
7002 auto length = std::strlen(reinterpret_cast<const char*>(b));
7003 const auto* ptr = reinterpret_cast<const char*>(b);
7004 return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck]
7005}
7006
7007template<typename T, std::size_t N>
7008auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
7009{
7010 return input_adapter(array, array + N);
7011}
7012
7013// This class only handles inputs of input_buffer_adapter type.
7014// It's required so that expressions like {ptr, len} can be implicitly cast
7015// to the correct adapter.
7017{
7018 public:
7019 template < typename CharT,
7020 typename std::enable_if <
7021 std::is_pointer<CharT>::value&&
7022 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
7023 sizeof(typename std::remove_pointer<CharT>::type) == 1,
7024 int >::type = 0 >
7025 span_input_adapter(CharT b, std::size_t l)
7026 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
7027
7028 template<class IteratorType,
7029 typename std::enable_if<
7030 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
7031 int>::type = 0>
7032 span_input_adapter(IteratorType first, IteratorType last)
7033 : ia(input_adapter(first, last)) {}
7034
7036 {
7037 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
7038 }
7039
7040 private:
7042};
7043
7044} // namespace detail
7046
7047// #include <nlohmann/detail/input/json_sax.hpp>
7048// __ _____ _____ _____
7049// __| | __| | | | JSON for Modern C++
7050// | | |__ | | | | | | version 3.12.0
7051// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7052//
7053// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7054// SPDX-License-Identifier: MIT
7055
7056
7057
7058#include <cstddef>
7059#include <string> // string
7060#include <type_traits> // enable_if_t
7061#include <utility> // move
7062#include <vector> // vector
7063
7064// #include <nlohmann/detail/exceptions.hpp>
7065
7066// #include <nlohmann/detail/input/lexer.hpp>
7067// __ _____ _____ _____
7068// __| | __| | | | JSON for Modern C++
7069// | | |__ | | | | | | version 3.12.0
7070// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7071//
7072// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7073// SPDX-License-Identifier: MIT
7074
7075
7076
7077#include <array> // array
7078#include <clocale> // localeconv
7079#include <cstddef> // size_t
7080#include <cstdio> // snprintf
7081#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7082#include <initializer_list> // initializer_list
7083#include <string> // char_traits, string
7084#include <utility> // move
7085#include <vector> // vector
7086
7087// #include <nlohmann/detail/input/input_adapters.hpp>
7088
7089// #include <nlohmann/detail/input/position_t.hpp>
7090
7091// #include <nlohmann/detail/macro_scope.hpp>
7092
7093// #include <nlohmann/detail/meta/type_traits.hpp>
7094
7095
7097namespace detail
7098{
7099
7100///////////
7101// lexer //
7102///////////
7103
7104template<typename BasicJsonType>
7106{
7107 public:
7108 /// token types for the parser
7109 enum class token_type
7110 {
7111 uninitialized, ///< indicating the scanner is uninitialized
7112 literal_true, ///< the `true` literal
7113 literal_false, ///< the `false` literal
7114 literal_null, ///< the `null` literal
7115 value_string, ///< a string -- use get_string() for actual value
7116 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
7117 value_integer, ///< a signed integer -- use get_number_integer() for actual value
7118 value_float, ///< an floating point number -- use get_number_float() for actual value
7119 begin_array, ///< the character for array begin `[`
7120 begin_object, ///< the character for object begin `{`
7121 end_array, ///< the character for array end `]`
7122 end_object, ///< the character for object end `}`
7123 name_separator, ///< the name separator `:`
7124 value_separator, ///< the value separator `,`
7125 parse_error, ///< indicating a parse error
7126 end_of_input, ///< indicating the end of the input buffer
7127 literal_or_value ///< a literal or the begin of a value (only for diagnostics)
7128 };
7129
7130 /// return name of values of type token_type (only used for errors)
7133 static const char* token_type_name(const token_type t) noexcept
7134 {
7135 switch (t)
7136 {
7138 return "<uninitialized>";
7140 return "true literal";
7142 return "false literal";
7144 return "null literal";
7146 return "string literal";
7150 return "number literal";
7152 return "'['";
7154 return "'{'";
7156 return "']'";
7158 return "'}'";
7160 return "':'";
7162 return "','";
7164 return "<parse error>";
7166 return "end of input";
7168 return "'[', '{', or a literal";
7169 // LCOV_EXCL_START
7170 default: // catch non-enum values
7171 return "unknown token";
7172 // LCOV_EXCL_STOP
7173 }
7174 }
7175};
7176/*!
7177@brief lexical analysis
7178
7179This class organizes the lexical analysis during JSON deserialization.
7180*/
7181template<typename BasicJsonType, typename InputAdapterType>
7182class lexer : public lexer_base<BasicJsonType>
7183{
7184 using number_integer_t = typename BasicJsonType::number_integer_t;
7185 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7186 using number_float_t = typename BasicJsonType::number_float_t;
7187 using string_t = typename BasicJsonType::string_t;
7188 using char_type = typename InputAdapterType::char_type;
7190
7191 public:
7193
7194 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7195 : ia(std::move(adapter))
7196 , ignore_comments(ignore_comments_)
7198 {}
7199
7200 // deleted because of pointer members
7201 lexer(const lexer&) = delete;
7202 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7203 lexer& operator=(lexer&) = delete;
7204 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7205 ~lexer() = default;
7206
7207 private:
7208 /////////////////////
7209 // locales
7210 /////////////////////
7211
7212 /// return the locale-dependent decimal point
7214 static char get_decimal_point() noexcept
7215 {
7216 const auto* loc = localeconv();
7217 JSON_ASSERT(loc != nullptr);
7218 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7219 }
7220
7221 /////////////////////
7222 // scan functions
7223 /////////////////////
7224
7225 /*!
7226 @brief get codepoint from 4 hex characters following `\u`
7227
7228 For input "\u c1 c2 c3 c4" the codepoint is:
7229 (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
7230 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
7231
7232 Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
7233 must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
7234 conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
7235 between the ASCII value of the character and the desired integer value.
7236
7237 @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
7238 non-hex character)
7239 */
7241 {
7242 // this function only makes sense after reading `\u`
7243 JSON_ASSERT(current == 'u');
7244 int codepoint = 0;
7245
7246 const auto factors = { 12u, 8u, 4u, 0u };
7247 for (const auto factor : factors)
7248 {
7249 get();
7250
7251 if (current >= '0' && current <= '9')
7252 {
7253 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7254 }
7255 else if (current >= 'A' && current <= 'F')
7256 {
7257 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7258 }
7259 else if (current >= 'a' && current <= 'f')
7260 {
7261 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7262 }
7263 else
7264 {
7265 return -1;
7266 }
7267 }
7268
7269 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7270 return codepoint;
7271 }
7272
7273 /*!
7274 @brief check if the next byte(s) are inside a given range
7275
7276 Adds the current byte and, for each passed range, reads a new byte and
7277 checks if it is inside the range. If a violation was detected, set up an
7278 error message and return false. Otherwise, return true.
7279
7280 @param[in] ranges list of integers; interpreted as list of pairs of
7281 inclusive lower and upper bound, respectively
7282
7283 @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
7284 1, 2, or 3 pairs. This precondition is enforced by an assertion.
7285
7286 @return true if and only if no range violation was detected
7287 */
7288 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7289 {
7290 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7291 add(current);
7292
7293 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7294 {
7295 get();
7296 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7297 {
7298 add(current);
7299 }
7300 else
7301 {
7302 error_message = "invalid string: ill-formed UTF-8 byte";
7303 return false;
7304 }
7305 }
7306
7307 return true;
7308 }
7309
7310 /*!
7311 @brief scan a string literal
7312
7313 This function scans a string according to Sect. 7 of RFC 8259. While
7314 scanning, bytes are escaped and copied into buffer token_buffer. Then the
7315 function returns successfully, token_buffer is *not* null-terminated (as it
7316 may contain \0 bytes), and token_buffer.size() is the number of bytes in the
7317 string.
7318
7319 @return token_type::value_string if string could be successfully scanned,
7320 token_type::parse_error otherwise
7321
7322 @note In case of errors, variable error_message contains a textual
7323 description.
7324 */
7326 {
7327 // reset token_buffer (ignore opening quote)
7328 reset();
7329
7330 // we entered the function by reading an open quote
7331 JSON_ASSERT(current == '\"');
7332
7333 while (true)
7334 {
7335 // get the next character
7336 switch (get())
7337 {
7338 // end of file while parsing the string
7340 {
7341 error_message = "invalid string: missing closing quote";
7342 return token_type::parse_error;
7343 }
7344
7345 // closing quote
7346 case '\"':
7347 {
7348 return token_type::value_string;
7349 }
7350
7351 // escapes
7352 case '\\':
7353 {
7354 switch (get())
7355 {
7356 // quotation mark
7357 case '\"':
7358 add('\"');
7359 break;
7360 // reverse solidus
7361 case '\\':
7362 add('\\');
7363 break;
7364 // solidus
7365 case '/':
7366 add('/');
7367 break;
7368 // backspace
7369 case 'b':
7370 add('\b');
7371 break;
7372 // form feed
7373 case 'f':
7374 add('\f');
7375 break;
7376 // line feed
7377 case 'n':
7378 add('\n');
7379 break;
7380 // carriage return
7381 case 'r':
7382 add('\r');
7383 break;
7384 // tab
7385 case 't':
7386 add('\t');
7387 break;
7388
7389 // unicode escapes
7390 case 'u':
7391 {
7392 const int codepoint1 = get_codepoint();
7393 int codepoint = codepoint1; // start with codepoint1
7394
7395 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7396 {
7397 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7398 return token_type::parse_error;
7399 }
7400
7401 // check if code point is a high surrogate
7402 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7403 {
7404 // expect next \uxxxx entry
7405 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7406 {
7407 const int codepoint2 = get_codepoint();
7408
7409 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7410 {
7411 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7412 return token_type::parse_error;
7413 }
7414
7415 // check if codepoint2 is a low surrogate
7416 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7417 {
7418 // overwrite codepoint
7419 codepoint = static_cast<int>(
7420 // high surrogate occupies the most significant 22 bits
7421 (static_cast<unsigned int>(codepoint1) << 10u)
7422 // low surrogate occupies the least significant 15 bits
7423 + static_cast<unsigned int>(codepoint2)
7424 // there is still the 0xD800, 0xDC00, and 0x10000 noise
7425 // in the result, so we have to subtract with:
7426 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7427 - 0x35FDC00u);
7428 }
7429 else
7430 {
7431 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7432 return token_type::parse_error;
7433 }
7434 }
7435 else
7436 {
7437 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7438 return token_type::parse_error;
7439 }
7440 }
7441 else
7442 {
7443 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7444 {
7445 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7446 return token_type::parse_error;
7447 }
7448 }
7449
7450 // the result of the above calculation yields a proper codepoint
7451 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7452
7453 // translate codepoint into bytes
7454 if (codepoint < 0x80)
7455 {
7456 // 1-byte characters: 0xxxxxxx (ASCII)
7457 add(static_cast<char_int_type>(codepoint));
7458 }
7459 else if (codepoint <= 0x7FF)
7460 {
7461 // 2-byte characters: 110xxxxx 10xxxxxx
7462 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7463 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7464 }
7465 else if (codepoint <= 0xFFFF)
7466 {
7467 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7468 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7469 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7470 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7471 }
7472 else
7473 {
7474 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7475 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7476 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7477 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7478 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7479 }
7480
7481 break;
7482 }
7483
7484 // other characters after escape
7485 default:
7486 error_message = "invalid string: forbidden character after backslash";
7487 return token_type::parse_error;
7488 }
7489
7490 break;
7491 }
7492
7493 // invalid control characters
7494 case 0x00:
7495 {
7496 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7497 return token_type::parse_error;
7498 }
7499
7500 case 0x01:
7501 {
7502 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7503 return token_type::parse_error;
7504 }
7505
7506 case 0x02:
7507 {
7508 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7509 return token_type::parse_error;
7510 }
7511
7512 case 0x03:
7513 {
7514 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7515 return token_type::parse_error;
7516 }
7517
7518 case 0x04:
7519 {
7520 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7521 return token_type::parse_error;
7522 }
7523
7524 case 0x05:
7525 {
7526 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7527 return token_type::parse_error;
7528 }
7529
7530 case 0x06:
7531 {
7532 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7533 return token_type::parse_error;
7534 }
7535
7536 case 0x07:
7537 {
7538 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7539 return token_type::parse_error;
7540 }
7541
7542 case 0x08:
7543 {
7544 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7545 return token_type::parse_error;
7546 }
7547
7548 case 0x09:
7549 {
7550 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7551 return token_type::parse_error;
7552 }
7553
7554 case 0x0A:
7555 {
7556 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7557 return token_type::parse_error;
7558 }
7559
7560 case 0x0B:
7561 {
7562 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7563 return token_type::parse_error;
7564 }
7565
7566 case 0x0C:
7567 {
7568 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7569 return token_type::parse_error;
7570 }
7571
7572 case 0x0D:
7573 {
7574 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7575 return token_type::parse_error;
7576 }
7577
7578 case 0x0E:
7579 {
7580 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7581 return token_type::parse_error;
7582 }
7583
7584 case 0x0F:
7585 {
7586 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7587 return token_type::parse_error;
7588 }
7589
7590 case 0x10:
7591 {
7592 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7593 return token_type::parse_error;
7594 }
7595
7596 case 0x11:
7597 {
7598 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7599 return token_type::parse_error;
7600 }
7601
7602 case 0x12:
7603 {
7604 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7605 return token_type::parse_error;
7606 }
7607
7608 case 0x13:
7609 {
7610 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7611 return token_type::parse_error;
7612 }
7613
7614 case 0x14:
7615 {
7616 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7617 return token_type::parse_error;
7618 }
7619
7620 case 0x15:
7621 {
7622 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7623 return token_type::parse_error;
7624 }
7625
7626 case 0x16:
7627 {
7628 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7629 return token_type::parse_error;
7630 }
7631
7632 case 0x17:
7633 {
7634 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7635 return token_type::parse_error;
7636 }
7637
7638 case 0x18:
7639 {
7640 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7641 return token_type::parse_error;
7642 }
7643
7644 case 0x19:
7645 {
7646 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7647 return token_type::parse_error;
7648 }
7649
7650 case 0x1A:
7651 {
7652 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7653 return token_type::parse_error;
7654 }
7655
7656 case 0x1B:
7657 {
7658 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7659 return token_type::parse_error;
7660 }
7661
7662 case 0x1C:
7663 {
7664 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7665 return token_type::parse_error;
7666 }
7667
7668 case 0x1D:
7669 {
7670 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7671 return token_type::parse_error;
7672 }
7673
7674 case 0x1E:
7675 {
7676 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7677 return token_type::parse_error;
7678 }
7679
7680 case 0x1F:
7681 {
7682 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7683 return token_type::parse_error;
7684 }
7685
7686 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7687 case 0x20:
7688 case 0x21:
7689 case 0x23:
7690 case 0x24:
7691 case 0x25:
7692 case 0x26:
7693 case 0x27:
7694 case 0x28:
7695 case 0x29:
7696 case 0x2A:
7697 case 0x2B:
7698 case 0x2C:
7699 case 0x2D:
7700 case 0x2E:
7701 case 0x2F:
7702 case 0x30:
7703 case 0x31:
7704 case 0x32:
7705 case 0x33:
7706 case 0x34:
7707 case 0x35:
7708 case 0x36:
7709 case 0x37:
7710 case 0x38:
7711 case 0x39:
7712 case 0x3A:
7713 case 0x3B:
7714 case 0x3C:
7715 case 0x3D:
7716 case 0x3E:
7717 case 0x3F:
7718 case 0x40:
7719 case 0x41:
7720 case 0x42:
7721 case 0x43:
7722 case 0x44:
7723 case 0x45:
7724 case 0x46:
7725 case 0x47:
7726 case 0x48:
7727 case 0x49:
7728 case 0x4A:
7729 case 0x4B:
7730 case 0x4C:
7731 case 0x4D:
7732 case 0x4E:
7733 case 0x4F:
7734 case 0x50:
7735 case 0x51:
7736 case 0x52:
7737 case 0x53:
7738 case 0x54:
7739 case 0x55:
7740 case 0x56:
7741 case 0x57:
7742 case 0x58:
7743 case 0x59:
7744 case 0x5A:
7745 case 0x5B:
7746 case 0x5D:
7747 case 0x5E:
7748 case 0x5F:
7749 case 0x60:
7750 case 0x61:
7751 case 0x62:
7752 case 0x63:
7753 case 0x64:
7754 case 0x65:
7755 case 0x66:
7756 case 0x67:
7757 case 0x68:
7758 case 0x69:
7759 case 0x6A:
7760 case 0x6B:
7761 case 0x6C:
7762 case 0x6D:
7763 case 0x6E:
7764 case 0x6F:
7765 case 0x70:
7766 case 0x71:
7767 case 0x72:
7768 case 0x73:
7769 case 0x74:
7770 case 0x75:
7771 case 0x76:
7772 case 0x77:
7773 case 0x78:
7774 case 0x79:
7775 case 0x7A:
7776 case 0x7B:
7777 case 0x7C:
7778 case 0x7D:
7779 case 0x7E:
7780 case 0x7F:
7781 {
7782 add(current);
7783 break;
7784 }
7785
7786 // U+0080..U+07FF: bytes C2..DF 80..BF
7787 case 0xC2:
7788 case 0xC3:
7789 case 0xC4:
7790 case 0xC5:
7791 case 0xC6:
7792 case 0xC7:
7793 case 0xC8:
7794 case 0xC9:
7795 case 0xCA:
7796 case 0xCB:
7797 case 0xCC:
7798 case 0xCD:
7799 case 0xCE:
7800 case 0xCF:
7801 case 0xD0:
7802 case 0xD1:
7803 case 0xD2:
7804 case 0xD3:
7805 case 0xD4:
7806 case 0xD5:
7807 case 0xD6:
7808 case 0xD7:
7809 case 0xD8:
7810 case 0xD9:
7811 case 0xDA:
7812 case 0xDB:
7813 case 0xDC:
7814 case 0xDD:
7815 case 0xDE:
7816 case 0xDF:
7817 {
7818 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7819 {
7820 return token_type::parse_error;
7821 }
7822 break;
7823 }
7824
7825 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7826 case 0xE0:
7827 {
7828 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7829 {
7830 return token_type::parse_error;
7831 }
7832 break;
7833 }
7834
7835 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7836 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7837 case 0xE1:
7838 case 0xE2:
7839 case 0xE3:
7840 case 0xE4:
7841 case 0xE5:
7842 case 0xE6:
7843 case 0xE7:
7844 case 0xE8:
7845 case 0xE9:
7846 case 0xEA:
7847 case 0xEB:
7848 case 0xEC:
7849 case 0xEE:
7850 case 0xEF:
7851 {
7852 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7853 {
7854 return token_type::parse_error;
7855 }
7856 break;
7857 }
7858
7859 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7860 case 0xED:
7861 {
7862 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7863 {
7864 return token_type::parse_error;
7865 }
7866 break;
7867 }
7868
7869 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7870 case 0xF0:
7871 {
7872 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7873 {
7874 return token_type::parse_error;
7875 }
7876 break;
7877 }
7878
7879 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7880 case 0xF1:
7881 case 0xF2:
7882 case 0xF3:
7883 {
7884 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7885 {
7886 return token_type::parse_error;
7887 }
7888 break;
7889 }
7890
7891 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7892 case 0xF4:
7893 {
7894 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7895 {
7896 return token_type::parse_error;
7897 }
7898 break;
7899 }
7900
7901 // the remaining bytes (80..C1 and F5..FF) are ill-formed
7902 default:
7903 {
7904 error_message = "invalid string: ill-formed UTF-8 byte";
7905 return token_type::parse_error;
7906 }
7907 }
7908 }
7909 }
7910
7911 /*!
7912 * @brief scan a comment
7913 * @return whether comment could be scanned successfully
7914 */
7916 {
7917 switch (get())
7918 {
7919 // single-line comments skip input until a newline or EOF is read
7920 case '/':
7921 {
7922 while (true)
7923 {
7924 switch (get())
7925 {
7926 case '\n':
7927 case '\r':
7929 case '\0':
7930 return true;
7931
7932 default:
7933 break;
7934 }
7935 }
7936 }
7937
7938 // multi-line comments skip input until */ is read
7939 case '*':
7940 {
7941 while (true)
7942 {
7943 switch (get())
7944 {
7946 case '\0':
7947 {
7948 error_message = "invalid comment; missing closing '*/'";
7949 return false;
7950 }
7951
7952 case '*':
7953 {
7954 switch (get())
7955 {
7956 case '/':
7957 return true;
7958
7959 default:
7960 {
7961 unget();
7962 continue;
7963 }
7964 }
7965 }
7966
7967 default:
7968 continue;
7969 }
7970 }
7971 }
7972
7973 // unexpected character after reading '/'
7974 default:
7975 {
7976 error_message = "invalid comment; expecting '/' or '*' after '/'";
7977 return false;
7978 }
7979 }
7980 }
7981
7983 static void strtof(float& f, const char* str, char** endptr) noexcept
7984 {
7985 f = std::strtof(str, endptr);
7986 }
7987
7989 static void strtof(double& f, const char* str, char** endptr) noexcept
7990 {
7991 f = std::strtod(str, endptr);
7992 }
7993
7995 static void strtof(long double& f, const char* str, char** endptr) noexcept
7996 {
7997 f = std::strtold(str, endptr);
7998 }
7999
8000 /*!
8001 @brief scan a number literal
8002
8003 This function scans a string according to Sect. 6 of RFC 8259.
8004
8005 The function is realized with a deterministic finite state machine derived
8006 from the grammar described in RFC 8259. Starting in state "init", the
8007 input is read and used to determined the next state. Only state "done"
8008 accepts the number. State "error" is a trap state to model errors. In the
8009 table below, "anything" means any character but the ones listed before.
8010
8011 state | 0 | 1-9 | e E | + | - | . | anything
8012 ---------|----------|----------|----------|---------|---------|----------|-----------
8013 init | zero | any1 | [error] | [error] | minus | [error] | [error]
8014 minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
8015 zero | done | done | exponent | done | done | decimal1 | done
8016 any1 | any1 | any1 | exponent | done | done | decimal1 | done
8017 decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error]
8018 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
8019 exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
8020 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
8021 any2 | any2 | any2 | done | done | done | done | done
8022
8023 The state machine is realized with one label per state (prefixed with
8024 "scan_number_") and `goto` statements between them. The state machine
8025 contains cycles, but any cycle can be left when EOF is read. Therefore,
8026 the function is guaranteed to terminate.
8027
8028 During scanning, the read bytes are stored in token_buffer. This string is
8029 then converted to a signed integer, an unsigned integer, or a
8030 floating-point number.
8031
8032 @return token_type::value_unsigned, token_type::value_integer, or
8033 token_type::value_float if number could be successfully scanned,
8034 token_type::parse_error otherwise
8035
8036 @note The scanner is independent of the current locale. Internally, the
8037 locale's decimal point is used instead of `.` to work with the
8038 locale-dependent converters.
8039 */
8040 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.
8041 {
8042 // reset token_buffer to store the number's bytes
8043 reset();
8044
8045 // the type of the parsed number; initially set to unsigned; will be
8046 // changed if minus sign, decimal point, or exponent is read
8047 token_type number_type = token_type::value_unsigned;
8048
8049 // state (init): we just found out we need to scan a number
8050 switch (current)
8051 {
8052 case '-':
8053 {
8054 add(current);
8055 goto scan_number_minus;
8056 }
8057
8058 case '0':
8059 {
8060 add(current);
8061 goto scan_number_zero;
8062 }
8063
8064 case '1':
8065 case '2':
8066 case '3':
8067 case '4':
8068 case '5':
8069 case '6':
8070 case '7':
8071 case '8':
8072 case '9':
8073 {
8074 add(current);
8075 goto scan_number_any1;
8076 }
8077
8078 // all other characters are rejected outside scan_number()
8079 default: // LCOV_EXCL_LINE
8080 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8081 }
8082
8083scan_number_minus:
8084 // state: we just parsed a leading minus sign
8085 number_type = token_type::value_integer;
8086 switch (get())
8087 {
8088 case '0':
8089 {
8090 add(current);
8091 goto scan_number_zero;
8092 }
8093
8094 case '1':
8095 case '2':
8096 case '3':
8097 case '4':
8098 case '5':
8099 case '6':
8100 case '7':
8101 case '8':
8102 case '9':
8103 {
8104 add(current);
8105 goto scan_number_any1;
8106 }
8107
8108 default:
8109 {
8110 error_message = "invalid number; expected digit after '-'";
8111 return token_type::parse_error;
8112 }
8113 }
8114
8115scan_number_zero:
8116 // state: we just parse a zero (maybe with a leading minus sign)
8117 switch (get())
8118 {
8119 case '.':
8120 {
8123 goto scan_number_decimal1;
8124 }
8125
8126 case 'e':
8127 case 'E':
8128 {
8129 add(current);
8130 goto scan_number_exponent;
8131 }
8132
8133 default:
8134 goto scan_number_done;
8135 }
8136
8137scan_number_any1:
8138 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8139 switch (get())
8140 {
8141 case '0':
8142 case '1':
8143 case '2':
8144 case '3':
8145 case '4':
8146 case '5':
8147 case '6':
8148 case '7':
8149 case '8':
8150 case '9':
8151 {
8152 add(current);
8153 goto scan_number_any1;
8154 }
8155
8156 case '.':
8157 {
8160 goto scan_number_decimal1;
8161 }
8162
8163 case 'e':
8164 case 'E':
8165 {
8166 add(current);
8167 goto scan_number_exponent;
8168 }
8169
8170 default:
8171 goto scan_number_done;
8172 }
8173
8174scan_number_decimal1:
8175 // state: we just parsed a decimal point
8176 number_type = token_type::value_float;
8177 switch (get())
8178 {
8179 case '0':
8180 case '1':
8181 case '2':
8182 case '3':
8183 case '4':
8184 case '5':
8185 case '6':
8186 case '7':
8187 case '8':
8188 case '9':
8189 {
8190 add(current);
8191 goto scan_number_decimal2;
8192 }
8193
8194 default:
8195 {
8196 error_message = "invalid number; expected digit after '.'";
8197 return token_type::parse_error;
8198 }
8199 }
8200
8201scan_number_decimal2:
8202 // we just parsed at least one number after a decimal point
8203 switch (get())
8204 {
8205 case '0':
8206 case '1':
8207 case '2':
8208 case '3':
8209 case '4':
8210 case '5':
8211 case '6':
8212 case '7':
8213 case '8':
8214 case '9':
8215 {
8216 add(current);
8217 goto scan_number_decimal2;
8218 }
8219
8220 case 'e':
8221 case 'E':
8222 {
8223 add(current);
8224 goto scan_number_exponent;
8225 }
8226
8227 default:
8228 goto scan_number_done;
8229 }
8230
8231scan_number_exponent:
8232 // we just parsed an exponent
8233 number_type = token_type::value_float;
8234 switch (get())
8235 {
8236 case '+':
8237 case '-':
8238 {
8239 add(current);
8240 goto scan_number_sign;
8241 }
8242
8243 case '0':
8244 case '1':
8245 case '2':
8246 case '3':
8247 case '4':
8248 case '5':
8249 case '6':
8250 case '7':
8251 case '8':
8252 case '9':
8253 {
8254 add(current);
8255 goto scan_number_any2;
8256 }
8257
8258 default:
8259 {
8261 "invalid number; expected '+', '-', or digit after exponent";
8262 return token_type::parse_error;
8263 }
8264 }
8265
8266scan_number_sign:
8267 // we just parsed an exponent sign
8268 switch (get())
8269 {
8270 case '0':
8271 case '1':
8272 case '2':
8273 case '3':
8274 case '4':
8275 case '5':
8276 case '6':
8277 case '7':
8278 case '8':
8279 case '9':
8280 {
8281 add(current);
8282 goto scan_number_any2;
8283 }
8284
8285 default:
8286 {
8287 error_message = "invalid number; expected digit after exponent sign";
8288 return token_type::parse_error;
8289 }
8290 }
8291
8292scan_number_any2:
8293 // we just parsed a number after the exponent or exponent sign
8294 switch (get())
8295 {
8296 case '0':
8297 case '1':
8298 case '2':
8299 case '3':
8300 case '4':
8301 case '5':
8302 case '6':
8303 case '7':
8304 case '8':
8305 case '9':
8306 {
8307 add(current);
8308 goto scan_number_any2;
8309 }
8310
8311 default:
8312 goto scan_number_done;
8313 }
8314
8315scan_number_done:
8316 // unget the character after the number (we only read it to know that
8317 // we are done scanning a number)
8318 unget();
8319
8320 char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8321 errno = 0;
8322
8323 // try to parse integers first and fall back to floats
8324 if (number_type == token_type::value_unsigned)
8325 {
8326 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8327
8328 // we checked the number format before
8329 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8330
8331 if (errno != ERANGE)
8332 {
8333 value_unsigned = static_cast<number_unsigned_t>(x);
8334 if (value_unsigned == x)
8335 {
8336 return token_type::value_unsigned;
8337 }
8338 }
8339 }
8340 else if (number_type == token_type::value_integer)
8341 {
8342 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8343
8344 // we checked the number format before
8345 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8346
8347 if (errno != ERANGE)
8348 {
8349 value_integer = static_cast<number_integer_t>(x);
8350 if (value_integer == x)
8351 {
8352 return token_type::value_integer;
8353 }
8354 }
8355 }
8356
8357 // this code is reached if we parse a floating-point number or if an
8358 // integer conversion above failed
8359 strtof(value_float, token_buffer.data(), &endptr);
8360
8361 // we checked the number format before
8362 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8363
8364 return token_type::value_float;
8365 }
8366
8367 /*!
8368 @param[in] literal_text the literal text to expect
8369 @param[in] length the length of the passed literal text
8370 @param[in] return_type the token type to return on success
8371 */
8373 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8374 token_type return_type)
8375 {
8377 for (std::size_t i = 1; i < length; ++i)
8378 {
8380 {
8381 error_message = "invalid literal";
8382 return token_type::parse_error;
8383 }
8384 }
8385 return return_type;
8386 }
8387
8388 /////////////////////
8389 // input management
8390 /////////////////////
8391
8392 /// reset token_buffer; current character is beginning of token
8393 void reset() noexcept
8394 {
8395 token_buffer.clear();
8396 token_string.clear();
8397 decimal_point_position = std::string::npos;
8399 }
8400
8401 /*
8402 @brief get next character from the input
8403
8404 This function provides the interface to the used input adapter. It does
8405 not throw in case the input reached EOF, but returns a
8406 `char_traits<char>::eof()` in that case. Stores the scanned characters
8407 for use in error messages.
8408
8409 @return character read from the input
8410 */
8412 {
8415
8416 if (next_unget)
8417 {
8418 // only reset the next_unget variable and work with current
8419 next_unget = false;
8420 }
8421 else
8422 {
8423 current = ia.get_character();
8424 }
8425
8427 {
8429 }
8430
8431 if (current == '\n')
8432 {
8435 }
8436
8437 return current;
8438 }
8439
8440 /*!
8441 @brief unget current character (read it again on next get)
8442
8443 We implement unget by setting variable next_unget to true. The input is not
8444 changed - we just simulate ungetting by modifying chars_read_total,
8445 chars_read_current_line, and token_string. The next call to get() will
8446 behave as if the unget character is read again.
8447 */
8448 void unget()
8449 {
8450 next_unget = true;
8451
8453
8454 // in case we "unget" a newline, we have to also decrement the lines_read
8456 {
8457 if (position.lines_read > 0)
8458 {
8460 }
8461 }
8462 else
8463 {
8465 }
8466
8468 {
8469 JSON_ASSERT(!token_string.empty());
8470 token_string.pop_back();
8471 }
8472 }
8473
8474 /// add a character to token_buffer
8476 {
8477 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8478 }
8479
8480 public:
8481 /////////////////////
8482 // value getters
8483 /////////////////////
8484
8485 /// return integer value
8486 constexpr number_integer_t get_number_integer() const noexcept
8487 {
8488 return value_integer;
8489 }
8490
8491 /// return unsigned integer value
8492 constexpr number_unsigned_t get_number_unsigned() const noexcept
8493 {
8494 return value_unsigned;
8495 }
8496
8497 /// return floating-point value
8498 constexpr number_float_t get_number_float() const noexcept
8499 {
8500 return value_float;
8501 }
8502
8503 /// return current string value (implicitly resets the token; useful only once)
8505 {
8506 // translate decimal points from locale back to '.' (#4084)
8507 if (decimal_point_char != '.' && decimal_point_position != std::string::npos)
8508 {
8510 }
8511 return token_buffer;
8512 }
8513
8514 /////////////////////
8515 // diagnostics
8516 /////////////////////
8517
8518 /// return position of last read token
8519 constexpr position_t get_position() const noexcept
8520 {
8521 return position;
8522 }
8523
8524 /// return the last read token (for errors only). Will never contain EOF
8525 /// (an arbitrary value that is not a valid char value, often -1), because
8526 /// 255 may legitimately occur. May contain NUL, which should be escaped.
8527 std::string get_token_string() const
8528 {
8529 // escape control characters
8530 std::string result;
8531 for (const auto c : token_string)
8532 {
8533 if (static_cast<unsigned char>(c) <= '\x1F')
8534 {
8535 // escape control characters
8536 std::array<char, 9> cs{{}};
8537 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8538 result += cs.data();
8539 }
8540 else
8541 {
8542 // add character as is
8543 result.push_back(static_cast<std::string::value_type>(c));
8544 }
8545 }
8546
8547 return result;
8548 }
8549
8550 /// return syntax error message
8552 constexpr const char* get_error_message() const noexcept
8553 {
8554 return error_message;
8555 }
8556
8557 /////////////////////
8558 // actual scanner
8559 /////////////////////
8560
8561 /*!
8562 @brief skip the UTF-8 byte order mark
8563 @return true iff there is no BOM or the correct BOM has been skipped
8564 */
8566 {
8567 if (get() == 0xEF)
8568 {
8569 // check if we completely parse the BOM
8570 return get() == 0xBB && get() == 0xBF;
8571 }
8572
8573 // the first character is not the beginning of the BOM; unget it to
8574 // process is later
8575 unget();
8576 return true;
8577 }
8578
8580 {
8581 do
8582 {
8583 get();
8584 }
8585 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8586 }
8587
8589 {
8590 // initially, skip the BOM
8591 if (position.chars_read_total == 0 && !skip_bom())
8592 {
8593 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8594 return token_type::parse_error;
8595 }
8596
8597 // read the next character and ignore whitespace
8599
8600 // ignore comments
8601 while (ignore_comments && current == '/')
8602 {
8603 if (!scan_comment())
8604 {
8605 return token_type::parse_error;
8606 }
8607
8608 // skip following whitespace
8610 }
8611
8612 switch (current)
8613 {
8614 // structural characters
8615 case '[':
8616 return token_type::begin_array;
8617 case ']':
8618 return token_type::end_array;
8619 case '{':
8620 return token_type::begin_object;
8621 case '}':
8622 return token_type::end_object;
8623 case ':':
8624 return token_type::name_separator;
8625 case ',':
8626 return token_type::value_separator;
8627
8628 // literals
8629 case 't':
8630 {
8631 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')}};
8632 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8633 }
8634 case 'f':
8635 {
8636 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')}};
8637 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8638 }
8639 case 'n':
8640 {
8641 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')}};
8642 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8643 }
8644
8645 // string
8646 case '\"':
8647 return scan_string();
8648
8649 // number
8650 case '-':
8651 case '0':
8652 case '1':
8653 case '2':
8654 case '3':
8655 case '4':
8656 case '5':
8657 case '6':
8658 case '7':
8659 case '8':
8660 case '9':
8661 return scan_number();
8662
8663 // end of input (the null byte is needed when parsing from
8664 // string literals)
8665 case '\0':
8667 return token_type::end_of_input;
8668
8669 // error
8670 default:
8671 error_message = "invalid literal";
8672 return token_type::parse_error;
8673 }
8674 }
8675
8676 private:
8677 /// input adapter
8678 InputAdapterType ia;
8679
8680 /// whether comments should be ignored (true) or signaled as errors (false)
8681 const bool ignore_comments = false;
8682
8683 /// the current character
8685
8686 /// whether the next get() call should just return current
8687 bool next_unget = false;
8688
8689 /// the start position of the current token
8691
8692 /// raw input token string (for error messages)
8693 std::vector<char_type> token_string {};
8694
8695 /// buffer for variable-length tokens (numbers, strings)
8697
8698 /// a description of occurred lexer errors
8699 const char* error_message = "";
8700
8701 // number values
8705
8706 /// the decimal point
8708 /// the position of the decimal point in the input
8709 std::size_t decimal_point_position = std::string::npos;
8710};
8711
8712} // namespace detail
8714
8715// #include <nlohmann/detail/macro_scope.hpp>
8716
8717// #include <nlohmann/detail/string_concat.hpp>
8718
8720
8721/*!
8722@brief SAX interface
8723
8724This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
8725Each function is called in different situations while the input is parsed. The
8726boolean return value informs the parser whether to continue processing the
8727input.
8728*/
8729template<typename BasicJsonType>
8731{
8732 using number_integer_t = typename BasicJsonType::number_integer_t;
8733 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8734 using number_float_t = typename BasicJsonType::number_float_t;
8735 using string_t = typename BasicJsonType::string_t;
8736 using binary_t = typename BasicJsonType::binary_t;
8737
8738 /*!
8739 @brief a null value was read
8740 @return whether parsing should proceed
8741 */
8742 virtual bool null() = 0;
8743
8744 /*!
8745 @brief a boolean value was read
8746 @param[in] val boolean value
8747 @return whether parsing should proceed
8748 */
8749 virtual bool boolean(bool val) = 0;
8750
8751 /*!
8752 @brief an integer number was read
8753 @param[in] val integer value
8754 @return whether parsing should proceed
8755 */
8756 virtual bool number_integer(number_integer_t val) = 0;
8757
8758 /*!
8759 @brief an unsigned integer number was read
8760 @param[in] val unsigned integer value
8761 @return whether parsing should proceed
8762 */
8763 virtual bool number_unsigned(number_unsigned_t val) = 0;
8764
8765 /*!
8766 @brief a floating-point number was read
8767 @param[in] val floating-point value
8768 @param[in] s raw token value
8769 @return whether parsing should proceed
8770 */
8771 virtual bool number_float(number_float_t val, const string_t& s) = 0;
8772
8773 /*!
8774 @brief a string value was read
8775 @param[in] val string value
8776 @return whether parsing should proceed
8777 @note It is safe to move the passed string value.
8778 */
8779 virtual bool string(string_t& val) = 0;
8780
8781 /*!
8782 @brief a binary value was read
8783 @param[in] val binary value
8784 @return whether parsing should proceed
8785 @note It is safe to move the passed binary value.
8786 */
8787 virtual bool binary(binary_t& val) = 0;
8788
8789 /*!
8790 @brief the beginning of an object was read
8791 @param[in] elements number of object elements or -1 if unknown
8792 @return whether parsing should proceed
8793 @note binary formats may report the number of elements
8794 */
8795 virtual bool start_object(std::size_t elements) = 0;
8796
8797 /*!
8798 @brief an object key was read
8799 @param[in] val object key
8800 @return whether parsing should proceed
8801 @note It is safe to move the passed string.
8802 */
8803 virtual bool key(string_t& val) = 0;
8804
8805 /*!
8806 @brief the end of an object was read
8807 @return whether parsing should proceed
8808 */
8809 virtual bool end_object() = 0;
8810
8811 /*!
8812 @brief the beginning of an array was read
8813 @param[in] elements number of array elements or -1 if unknown
8814 @return whether parsing should proceed
8815 @note binary formats may report the number of elements
8816 */
8817 virtual bool start_array(std::size_t elements) = 0;
8818
8819 /*!
8820 @brief the end of an array was read
8821 @return whether parsing should proceed
8822 */
8823 virtual bool end_array() = 0;
8824
8825 /*!
8826 @brief a parse error occurred
8827 @param[in] position the position in the input where the error occurs
8828 @param[in] last_token the last read token
8829 @param[in] ex an exception object describing the error
8830 @return whether parsing should proceed (must return false)
8831 */
8832 virtual bool parse_error(std::size_t position,
8833 const std::string& last_token,
8834 const detail::exception& ex) = 0;
8835
8836 json_sax() = default;
8837 json_sax(const json_sax&) = default;
8838 json_sax(json_sax&&) noexcept = default;
8839 json_sax& operator=(const json_sax&) = default;
8840 json_sax& operator=(json_sax&&) noexcept = default;
8841 virtual ~json_sax() = default;
8842};
8843
8844namespace detail
8845{
8846constexpr std::size_t unknown_size()
8847{
8848 return (std::numeric_limits<std::size_t>::max)();
8849}
8850
8851/*!
8852@brief SAX implementation to create a JSON value from SAX events
8853
8854This class implements the @ref json_sax interface and processes the SAX events
8855to create a JSON value which makes it basically a DOM parser. The structure or
8856hierarchy of the JSON value is managed by the stack `ref_stack` which contains
8857a pointer to the respective array or object for each recursion depth.
8858
8859After successful parsing, the value that is passed by reference to the
8860constructor contains the parsed value.
8861
8862@tparam BasicJsonType the JSON type
8863*/
8864template<typename BasicJsonType, typename InputAdapterType>
8866{
8867 public:
8868 using number_integer_t = typename BasicJsonType::number_integer_t;
8869 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8870 using number_float_t = typename BasicJsonType::number_float_t;
8871 using string_t = typename BasicJsonType::string_t;
8872 using binary_t = typename BasicJsonType::binary_t;
8874
8875 /*!
8876 @param[in,out] r reference to a JSON value that is manipulated while
8877 parsing
8878 @param[in] allow_exceptions_ whether parse errors yield exceptions
8879 */
8880 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr)
8881 : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
8882 {}
8883
8884 // make class move-only
8886 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8888 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8890
8891 bool null()
8892 {
8893 handle_value(nullptr);
8894 return true;
8895 }
8896
8897 bool boolean(bool val)
8898 {
8899 handle_value(val);
8900 return true;
8901 }
8902
8904 {
8905 handle_value(val);
8906 return true;
8907 }
8908
8910 {
8911 handle_value(val);
8912 return true;
8913 }
8914
8915 bool number_float(number_float_t val, const string_t& /*unused*/)
8916 {
8917 handle_value(val);
8918 return true;
8919 }
8920
8921 bool string(string_t& val)
8922 {
8923 handle_value(val);
8924 return true;
8925 }
8926
8927 bool binary(binary_t& val)
8928 {
8929 handle_value(std::move(val));
8930 return true;
8931 }
8932
8933 bool start_object(std::size_t len)
8934 {
8935 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
8936
8937#if JSON_DIAGNOSTIC_POSITIONS
8938 // Manually set the start position of the object here.
8939 // Ensure this is after the call to handle_value to ensure correct start position.
8940 if (m_lexer_ref)
8941 {
8942 // Lexer has read the first character of the object, so
8943 // subtract 1 from the position to get the correct start position.
8944 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8945 }
8946#endif
8947
8948 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
8949 {
8950 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
8951 }
8952
8953 return true;
8954 }
8955
8956 bool key(string_t& val)
8957 {
8958 JSON_ASSERT(!ref_stack.empty());
8959 JSON_ASSERT(ref_stack.back()->is_object());
8960
8961 // add null at the given key and store the reference for later
8962 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
8963 return true;
8964 }
8965
8967 {
8968 JSON_ASSERT(!ref_stack.empty());
8969 JSON_ASSERT(ref_stack.back()->is_object());
8970
8971#if JSON_DIAGNOSTIC_POSITIONS
8972 if (m_lexer_ref)
8973 {
8974 // Lexer's position is past the closing brace, so set that as the end position.
8975 ref_stack.back()->end_position = m_lexer_ref->get_position();
8976 }
8977#endif
8978
8979 ref_stack.back()->set_parents();
8980 ref_stack.pop_back();
8981 return true;
8982 }
8983
8984 bool start_array(std::size_t len)
8985 {
8986 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
8987
8988#if JSON_DIAGNOSTIC_POSITIONS
8989 // Manually set the start position of the array here.
8990 // Ensure this is after the call to handle_value to ensure correct start position.
8991 if (m_lexer_ref)
8992 {
8993 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8994 }
8995#endif
8996
8997 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
8998 {
8999 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
9000 }
9001
9002 return true;
9003 }
9004
9006 {
9007 JSON_ASSERT(!ref_stack.empty());
9008 JSON_ASSERT(ref_stack.back()->is_array());
9009
9010#if JSON_DIAGNOSTIC_POSITIONS
9011 if (m_lexer_ref)
9012 {
9013 // Lexer's position is past the closing bracket, so set that as the end position.
9014 ref_stack.back()->end_position = m_lexer_ref->get_position();
9015 }
9016#endif
9017
9018 ref_stack.back()->set_parents();
9019 ref_stack.pop_back();
9020 return true;
9021 }
9022
9023 template<class Exception>
9024 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9025 const Exception& ex)
9026 {
9027 errored = true;
9028 static_cast<void>(ex);
9029 if (allow_exceptions)
9030 {
9031 JSON_THROW(ex);
9032 }
9033 return false;
9034 }
9035
9036 constexpr bool is_errored() const
9037 {
9038 return errored;
9039 }
9040
9041 private:
9042
9043#if JSON_DIAGNOSTIC_POSITIONS
9044 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9045 {
9046 if (m_lexer_ref)
9047 {
9048 // Lexer has read past the current field value, so set the end position to the current position.
9049 // The start position will be set below based on the length of the string representation
9050 // of the value.
9051 v.end_position = m_lexer_ref->get_position();
9052
9053 switch (v.type())
9054 {
9055 case value_t::boolean:
9056 {
9057 // 4 and 5 are the string length of "true" and "false"
9058 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9059 break;
9060 }
9061
9062 case value_t::null:
9063 {
9064 // 4 is the string length of "null"
9065 v.start_position = v.end_position - 4;
9066 break;
9067 }
9068
9069 case value_t::string:
9070 {
9071 // include the length of the quotes, which is 2
9072 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9073 break;
9074 }
9075
9076 // As we handle the start and end positions for values created during parsing,
9077 // we do not expect the following value type to be called. Regardless, set the positions
9078 // in case this is created manually or through a different constructor. Exclude from lcov
9079 // since the exact condition of this switch is esoteric.
9080 // LCOV_EXCL_START
9081 case value_t::discarded:
9082 {
9083 v.end_position = std::string::npos;
9084 v.start_position = v.end_position;
9085 break;
9086 }
9087 // LCOV_EXCL_STOP
9088 case value_t::binary:
9089 case value_t::number_integer:
9090 case value_t::number_unsigned:
9091 case value_t::number_float:
9092 {
9093 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9094 break;
9095 }
9096 case value_t::object:
9097 case value_t::array:
9098 {
9099 // object and array are handled in start_object() and start_array() handlers
9100 // skip setting the values here.
9101 break;
9102 }
9103 default: // LCOV_EXCL_LINE
9104 // Handle all possible types discretely, default handler should never be reached.
9105 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9106 }
9107 }
9108 }
9109#endif
9110
9111 /*!
9112 @invariant If the ref stack is empty, then the passed value will be the new
9113 root.
9114 @invariant If the ref stack contains a value, then it is an array or an
9115 object to which we can add elements
9116 */
9117 template<typename Value>
9119 BasicJsonType* handle_value(Value&& v)
9120 {
9121 if (ref_stack.empty())
9122 {
9123 root = BasicJsonType(std::forward<Value>(v));
9124
9125#if JSON_DIAGNOSTIC_POSITIONS
9126 handle_diagnostic_positions_for_json_value(root);
9127#endif
9128
9129 return &root;
9130 }
9131
9132 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9133
9134 if (ref_stack.back()->is_array())
9135 {
9136 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
9137
9138#if JSON_DIAGNOSTIC_POSITIONS
9139 handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back());
9140#endif
9141
9142 return &(ref_stack.back()->m_data.m_value.array->back());
9143 }
9144
9145 JSON_ASSERT(ref_stack.back()->is_object());
9146 JSON_ASSERT(object_element);
9147 *object_element = BasicJsonType(std::forward<Value>(v));
9148
9149#if JSON_DIAGNOSTIC_POSITIONS
9150 handle_diagnostic_positions_for_json_value(*object_element);
9151#endif
9152
9153 return object_element;
9154 }
9155
9156 /// the parsed JSON value
9157 BasicJsonType& root;
9158 /// stack to model hierarchy of values
9159 std::vector<BasicJsonType*> ref_stack {};
9160 /// helper to hold the reference for the next object element
9161 BasicJsonType* object_element = nullptr;
9162 /// whether a syntax error occurred
9163 bool errored = false;
9164 /// whether to throw exceptions in case of errors
9165 const bool allow_exceptions = true;
9166 /// the lexer reference to obtain the current position
9167 lexer_t* m_lexer_ref = nullptr;
9168};
9169
9170template<typename BasicJsonType, typename InputAdapterType>
9172{
9173 public:
9174 using number_integer_t = typename BasicJsonType::number_integer_t;
9175 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9176 using number_float_t = typename BasicJsonType::number_float_t;
9177 using string_t = typename BasicJsonType::string_t;
9178 using binary_t = typename BasicJsonType::binary_t;
9179 using parser_callback_t = typename BasicJsonType::parser_callback_t;
9180 using parse_event_t = typename BasicJsonType::parse_event_t;
9182
9185 const bool allow_exceptions_ = true,
9186 lexer_t* lexer_ = nullptr)
9187 : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
9188 {
9189 keep_stack.push_back(true);
9190 }
9191
9192 // make class move-only
9194 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9196 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9198
9199 bool null()
9200 {
9201 handle_value(nullptr);
9202 return true;
9203 }
9204
9205 bool boolean(bool val)
9206 {
9207 handle_value(val);
9208 return true;
9209 }
9210
9212 {
9213 handle_value(val);
9214 return true;
9215 }
9216
9218 {
9219 handle_value(val);
9220 return true;
9221 }
9222
9223 bool number_float(number_float_t val, const string_t& /*unused*/)
9224 {
9225 handle_value(val);
9226 return true;
9227 }
9228
9229 bool string(string_t& val)
9230 {
9231 handle_value(val);
9232 return true;
9233 }
9234
9235 bool binary(binary_t& val)
9236 {
9237 handle_value(std::move(val));
9238 return true;
9239 }
9240
9241 bool start_object(std::size_t len)
9242 {
9243 // check callback for object start
9244 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
9245 keep_stack.push_back(keep);
9246
9247 auto val = handle_value(BasicJsonType::value_t::object, true);
9248 ref_stack.push_back(val.second);
9249
9250 if (ref_stack.back())
9251 {
9252
9253#if JSON_DIAGNOSTIC_POSITIONS
9254 // Manually set the start position of the object here.
9255 // Ensure this is after the call to handle_value to ensure correct start position.
9256 if (m_lexer_ref)
9257 {
9258 // Lexer has read the first character of the object, so
9259 // subtract 1 from the position to get the correct start position.
9260 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9261 }
9262#endif
9263
9264 // check object limit
9265 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9266 {
9267 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
9268 }
9269 }
9270 return true;
9271 }
9272
9273 bool key(string_t& val)
9274 {
9275 BasicJsonType k = BasicJsonType(val);
9276
9277 // check callback for the key
9278 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
9279 key_keep_stack.push_back(keep);
9280
9281 // add discarded value at the given key and store the reference for later
9282 if (keep && ref_stack.back())
9283 {
9284 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
9285 }
9286
9287 return true;
9288 }
9289
9291 {
9292 if (ref_stack.back())
9293 {
9294 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
9295 {
9296 // discard object
9297 *ref_stack.back() = discarded;
9298
9299#if JSON_DIAGNOSTIC_POSITIONS
9300 // Set start/end positions for discarded object.
9301 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9302#endif
9303 }
9304 else
9305 {
9306
9307#if JSON_DIAGNOSTIC_POSITIONS
9308 if (m_lexer_ref)
9309 {
9310 // Lexer's position is past the closing brace, so set that as the end position.
9311 ref_stack.back()->end_position = m_lexer_ref->get_position();
9312 }
9313#endif
9314
9315 ref_stack.back()->set_parents();
9316 }
9317 }
9318
9319 JSON_ASSERT(!ref_stack.empty());
9320 JSON_ASSERT(!keep_stack.empty());
9321 ref_stack.pop_back();
9322 keep_stack.pop_back();
9323
9324 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
9325 {
9326 // remove discarded value
9327 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
9328 {
9329 if (it->is_discarded())
9330 {
9331 ref_stack.back()->erase(it);
9332 break;
9333 }
9334 }
9335 }
9336
9337 return true;
9338 }
9339
9340 bool start_array(std::size_t len)
9341 {
9342 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
9343 keep_stack.push_back(keep);
9344
9345 auto val = handle_value(BasicJsonType::value_t::array, true);
9346 ref_stack.push_back(val.second);
9347
9348 if (ref_stack.back())
9349 {
9350
9351#if JSON_DIAGNOSTIC_POSITIONS
9352 // Manually set the start position of the array here.
9353 // Ensure this is after the call to handle_value to ensure correct start position.
9354 if (m_lexer_ref)
9355 {
9356 // Lexer has read the first character of the array, so
9357 // subtract 1 from the position to get the correct start position.
9358 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9359 }
9360#endif
9361
9362 // check array limit
9363 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9364 {
9365 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
9366 }
9367 }
9368
9369 return true;
9370 }
9371
9373 {
9374 bool keep = true;
9375
9376 if (ref_stack.back())
9377 {
9378 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
9379 if (keep)
9380 {
9381
9382#if JSON_DIAGNOSTIC_POSITIONS
9383 if (m_lexer_ref)
9384 {
9385 // Lexer's position is past the closing bracket, so set that as the end position.
9386 ref_stack.back()->end_position = m_lexer_ref->get_position();
9387 }
9388#endif
9389
9390 ref_stack.back()->set_parents();
9391 }
9392 else
9393 {
9394 // discard array
9395 *ref_stack.back() = discarded;
9396
9397#if JSON_DIAGNOSTIC_POSITIONS
9398 // Set start/end positions for discarded array.
9399 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9400#endif
9401 }
9402 }
9403
9404 JSON_ASSERT(!ref_stack.empty());
9405 JSON_ASSERT(!keep_stack.empty());
9406 ref_stack.pop_back();
9407 keep_stack.pop_back();
9408
9409 // remove discarded value
9410 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
9411 {
9412 ref_stack.back()->m_data.m_value.array->pop_back();
9413 }
9414
9415 return true;
9416 }
9417
9418 template<class Exception>
9419 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9420 const Exception& ex)
9421 {
9422 errored = true;
9423 static_cast<void>(ex);
9424 if (allow_exceptions)
9425 {
9426 JSON_THROW(ex);
9427 }
9428 return false;
9429 }
9430
9431 constexpr bool is_errored() const
9432 {
9433 return errored;
9434 }
9435
9436 private:
9437
9438#if JSON_DIAGNOSTIC_POSITIONS
9439 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9440 {
9441 if (m_lexer_ref)
9442 {
9443 // Lexer has read past the current field value, so set the end position to the current position.
9444 // The start position will be set below based on the length of the string representation
9445 // of the value.
9446 v.end_position = m_lexer_ref->get_position();
9447
9448 switch (v.type())
9449 {
9450 case value_t::boolean:
9451 {
9452 // 4 and 5 are the string length of "true" and "false"
9453 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9454 break;
9455 }
9456
9457 case value_t::null:
9458 {
9459 // 4 is the string length of "null"
9460 v.start_position = v.end_position - 4;
9461 break;
9462 }
9463
9464 case value_t::string:
9465 {
9466 // include the length of the quotes, which is 2
9467 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9468 break;
9469 }
9470
9471 case value_t::discarded:
9472 {
9473 v.end_position = std::string::npos;
9474 v.start_position = v.end_position;
9475 break;
9476 }
9477
9478 case value_t::binary:
9479 case value_t::number_integer:
9480 case value_t::number_unsigned:
9481 case value_t::number_float:
9482 {
9483 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9484 break;
9485 }
9486
9487 case value_t::object:
9488 case value_t::array:
9489 {
9490 // object and array are handled in start_object() and start_array() handlers
9491 // skip setting the values here.
9492 break;
9493 }
9494 default: // LCOV_EXCL_LINE
9495 // Handle all possible types discretely, default handler should never be reached.
9496 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9497 }
9498 }
9499 }
9500#endif
9501
9502 /*!
9503 @param[in] v value to add to the JSON value we build during parsing
9504 @param[in] skip_callback whether we should skip calling the callback
9505 function; this is required after start_array() and
9506 start_object() SAX events, because otherwise we would call the
9507 callback function with an empty array or object, respectively.
9508
9509 @invariant If the ref stack is empty, then the passed value will be the new
9510 root.
9511 @invariant If the ref stack contains a value, then it is an array or an
9512 object to which we can add elements
9513
9514 @return pair of boolean (whether value should be kept) and pointer (to the
9515 passed value in the ref_stack hierarchy; nullptr if not kept)
9516 */
9517 template<typename Value>
9518 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
9519 {
9520 JSON_ASSERT(!keep_stack.empty());
9521
9522 // do not handle this value if we know it would be added to a discarded
9523 // container
9524 if (!keep_stack.back())
9525 {
9526 return {false, nullptr};
9527 }
9528
9529 // create value
9530 auto value = BasicJsonType(std::forward<Value>(v));
9531
9532#if JSON_DIAGNOSTIC_POSITIONS
9533 handle_diagnostic_positions_for_json_value(value);
9534#endif
9535
9536 // check callback
9537 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
9538
9539 // do not handle this value if we just learnt it shall be discarded
9540 if (!keep)
9541 {
9542 return {false, nullptr};
9543 }
9544
9545 if (ref_stack.empty())
9546 {
9547 root = std::move(value);
9548 return {true, & root};
9549 }
9550
9551 // skip this value if we already decided to skip the parent
9552 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
9553 if (!ref_stack.back())
9554 {
9555 return {false, nullptr};
9556 }
9557
9558 // we now only expect arrays and objects
9559 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9560
9561 // array
9562 if (ref_stack.back()->is_array())
9563 {
9564 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
9565 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
9566 }
9567
9568 // object
9569 JSON_ASSERT(ref_stack.back()->is_object());
9570 // check if we should store an element for the current key
9571 JSON_ASSERT(!key_keep_stack.empty());
9572 const bool store_element = key_keep_stack.back();
9573 key_keep_stack.pop_back();
9574
9575 if (!store_element)
9576 {
9577 return {false, nullptr};
9578 }
9579
9580 JSON_ASSERT(object_element);
9581 *object_element = std::move(value);
9582 return {true, object_element};
9583 }
9584
9585 /// the parsed JSON value
9586 BasicJsonType& root;
9587 /// stack to model hierarchy of values
9588 std::vector<BasicJsonType*> ref_stack {};
9589 /// stack to manage which values to keep
9590 std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
9591 /// stack to manage which object keys to keep
9592 std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
9593 /// helper to hold the reference for the next object element
9594 BasicJsonType* object_element = nullptr;
9595 /// whether a syntax error occurred
9596 bool errored = false;
9597 /// callback function
9598 const parser_callback_t callback = nullptr;
9599 /// whether to throw exceptions in case of errors
9600 const bool allow_exceptions = true;
9601 /// a discarded value for the callback
9602 BasicJsonType discarded = BasicJsonType::value_t::discarded;
9603 /// the lexer reference to obtain the current position
9604 lexer_t* m_lexer_ref = nullptr;
9605};
9606
9607template<typename BasicJsonType>
9609{
9610 public:
9611 using number_integer_t = typename BasicJsonType::number_integer_t;
9612 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9613 using number_float_t = typename BasicJsonType::number_float_t;
9614 using string_t = typename BasicJsonType::string_t;
9615 using binary_t = typename BasicJsonType::binary_t;
9616
9617 bool null()
9618 {
9619 return true;
9620 }
9621
9622 bool boolean(bool /*unused*/)
9623 {
9624 return true;
9625 }
9626
9628 {
9629 return true;
9630 }
9631
9633 {
9634 return true;
9635 }
9636
9637 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
9638 {
9639 return true;
9640 }
9641
9642 bool string(string_t& /*unused*/)
9643 {
9644 return true;
9645 }
9646
9647 bool binary(binary_t& /*unused*/)
9648 {
9649 return true;
9650 }
9651
9652 bool start_object(std::size_t /*unused*/ = detail::unknown_size())
9653 {
9654 return true;
9655 }
9656
9657 bool key(string_t& /*unused*/)
9658 {
9659 return true;
9660 }
9661
9663 {
9664 return true;
9665 }
9666
9667 bool start_array(std::size_t /*unused*/ = detail::unknown_size())
9668 {
9669 return true;
9670 }
9671
9673 {
9674 return true;
9675 }
9676
9677 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
9678 {
9679 return false;
9680 }
9681};
9682
9683} // namespace detail
9685
9686// #include <nlohmann/detail/input/lexer.hpp>
9687
9688// #include <nlohmann/detail/macro_scope.hpp>
9689
9690// #include <nlohmann/detail/meta/is_sax.hpp>
9691// __ _____ _____ _____
9692// __| | __| | | | JSON for Modern C++
9693// | | |__ | | | | | | version 3.12.0
9694// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9695//
9696// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
9697// SPDX-License-Identifier: MIT
9698
9699
9700
9701#include <cstdint> // size_t
9702#include <utility> // declval
9703#include <string> // string
9704
9705// #include <nlohmann/detail/abi_macros.hpp>
9706
9707// #include <nlohmann/detail/meta/detected.hpp>
9708
9709// #include <nlohmann/detail/meta/type_traits.hpp>
9710
9711
9713namespace detail
9714{
9715
9716template<typename T>
9717using null_function_t = decltype(std::declval<T&>().null());
9718
9719template<typename T>
9721 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9722
9723template<typename T, typename Integer>
9725 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9726
9727template<typename T, typename Unsigned>
9729 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9730
9731template<typename T, typename Float, typename String>
9732using number_float_function_t = decltype(std::declval<T&>().number_float(
9733 std::declval<Float>(), std::declval<const String&>()));
9734
9735template<typename T, typename String>
9737 decltype(std::declval<T&>().string(std::declval<String&>()));
9738
9739template<typename T, typename Binary>
9741 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9742
9743template<typename T>
9745 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9746
9747template<typename T, typename String>
9749 decltype(std::declval<T&>().key(std::declval<String&>()));
9750
9751template<typename T>
9752using end_object_function_t = decltype(std::declval<T&>().end_object());
9753
9754template<typename T>
9756 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9757
9758template<typename T>
9759using end_array_function_t = decltype(std::declval<T&>().end_array());
9760
9761template<typename T, typename Exception>
9762using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9763 std::declval<std::size_t>(), std::declval<const std::string&>(),
9764 std::declval<const Exception&>()));
9765
9766template<typename SAX, typename BasicJsonType>
9768{
9769 private:
9771 "BasicJsonType must be of type basic_json<...>");
9772
9773 using number_integer_t = typename BasicJsonType::number_integer_t;
9774 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9775 using number_float_t = typename BasicJsonType::number_float_t;
9776 using string_t = typename BasicJsonType::string_t;
9777 using binary_t = typename BasicJsonType::binary_t;
9778 using exception_t = typename BasicJsonType::exception;
9779
9780 public:
9781 static constexpr bool value =
9795};
9796
9797template<typename SAX, typename BasicJsonType>
9799{
9800 private:
9802 "BasicJsonType must be of type basic_json<...>");
9803
9804 using number_integer_t = typename BasicJsonType::number_integer_t;
9805 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9806 using number_float_t = typename BasicJsonType::number_float_t;
9807 using string_t = typename BasicJsonType::string_t;
9808 using binary_t = typename BasicJsonType::binary_t;
9809 using exception_t = typename BasicJsonType::exception;
9810
9811 public:
9813 "Missing/invalid function: bool null()");
9815 "Missing/invalid function: bool boolean(bool)");
9817 "Missing/invalid function: bool boolean(bool)");
9818 static_assert(
9820 number_integer_t>::value,
9821 "Missing/invalid function: bool number_integer(number_integer_t)");
9822 static_assert(
9824 number_unsigned_t>::value,
9825 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9826 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9827 number_float_t, string_t>::value,
9828 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9829 static_assert(
9831 "Missing/invalid function: bool string(string_t&)");
9832 static_assert(
9834 "Missing/invalid function: bool binary(binary_t&)");
9836 "Missing/invalid function: bool start_object(std::size_t)");
9838 "Missing/invalid function: bool key(string_t&)");
9840 "Missing/invalid function: bool end_object()");
9842 "Missing/invalid function: bool start_array(std::size_t)");
9844 "Missing/invalid function: bool end_array()");
9845 static_assert(
9847 "Missing/invalid function: bool parse_error(std::size_t, const "
9848 "std::string&, const exception&)");
9849};
9850
9851} // namespace detail
9853
9854// #include <nlohmann/detail/meta/type_traits.hpp>
9855
9856// #include <nlohmann/detail/string_concat.hpp>
9857
9858// #include <nlohmann/detail/value_t.hpp>
9859
9860
9862namespace detail
9863{
9864
9865/// how to treat CBOR tags
9867{
9868 error, ///< throw a parse_error exception in case of a tag
9869 ignore, ///< ignore tags
9870 store ///< store tags as binary type
9871};
9872
9873/*!
9874@brief determine system byte order
9875
9876@return true if and only if system's byte order is little endian
9877
9878@note from https://stackoverflow.com/a/1001328/266378
9879*/
9880inline bool little_endianness(int num = 1) noexcept
9881{
9882 return *reinterpret_cast<char*>(&num) == 1;
9883}
9884
9885///////////////////
9886// binary reader //
9887///////////////////
9888
9889/*!
9890@brief deserialization of CBOR, MessagePack, and UBJSON values
9891*/
9892template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType, InputAdapterType>>
9894{
9895 using number_integer_t = typename BasicJsonType::number_integer_t;
9896 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9897 using number_float_t = typename BasicJsonType::number_float_t;
9898 using string_t = typename BasicJsonType::string_t;
9899 using binary_t = typename BasicJsonType::binary_t;
9900 using json_sax_t = SAX;
9901 using char_type = typename InputAdapterType::char_type;
9903
9904 public:
9905 /*!
9906 @brief create a binary reader
9907
9908 @param[in] adapter input adapter to read from
9909 */
9910 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9911 {
9913 }
9914
9915 // make class move-only
9917 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9919 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9920 ~binary_reader() = default;
9921
9922 /*!
9923 @param[in] format the binary format to parse
9924 @param[in] sax_ a SAX event processor
9925 @param[in] strict whether to expect the input to be consumed completed
9926 @param[in] tag_handler how to treat CBOR tags
9927
9928 @return whether parsing was successful
9929 */
9931 bool sax_parse(const input_format_t format,
9932 json_sax_t* sax_,
9933 const bool strict = true,
9934 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9935 {
9936 sax = sax_;
9937 bool result = false;
9938
9939 switch (format)
9940 {
9941 case input_format_t::bson:
9942 result = parse_bson_internal();
9943 break;
9944
9945 case input_format_t::cbor:
9946 result = parse_cbor_internal(true, tag_handler);
9947 break;
9948
9949 case input_format_t::msgpack:
9950 result = parse_msgpack_internal();
9951 break;
9952
9953 case input_format_t::ubjson:
9954 case input_format_t::bjdata:
9955 result = parse_ubjson_internal();
9956 break;
9957
9958 case input_format_t::json: // LCOV_EXCL_LINE
9959 default: // LCOV_EXCL_LINE
9960 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9961 }
9962
9963 // strict mode: next byte must be EOF
9964 if (result && strict)
9965 {
9966 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9967 {
9968 get_ignore_noop();
9969 }
9970 else
9971 {
9972 get();
9973 }
9974
9976 {
9977 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9978 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9979 }
9980 }
9981
9982 return result;
9983 }
9984
9985 private:
9986 //////////
9987 // BSON //
9988 //////////
9989
9990 /*!
9991 @brief Reads in a BSON-object and passes it to the SAX-parser.
9992 @return whether a valid BSON-value was passed to the SAX parser
9993 */
9995 {
9996 std::int32_t document_size{};
9997 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9998
9999 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
10000 {
10001 return false;
10002 }
10003
10004 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
10005 {
10006 return false;
10007 }
10008
10009 return sax->end_object();
10010 }
10011
10012 /*!
10013 @brief Parses a C-style string from the BSON input.
10014 @param[in,out] result A reference to the string variable where the read
10015 string is to be stored.
10016 @return `true` if the \x00-byte indicating the end of the string was
10017 encountered before the EOF; false` indicates an unexpected EOF.
10018 */
10020 {
10021 auto out = std::back_inserter(result);
10022 while (true)
10023 {
10024 get();
10025 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
10026 {
10027 return false;
10028 }
10029 if (current == 0x00)
10030 {
10031 return true;
10032 }
10033 *out++ = static_cast<typename string_t::value_type>(current);
10034 }
10035 }
10036
10037 /*!
10038 @brief Parses a zero-terminated string of length @a len from the BSON
10039 input.
10040 @param[in] len The length (including the zero-byte at the end) of the
10041 string to be read.
10042 @param[in,out] result A reference to the string variable where the read
10043 string is to be stored.
10044 @tparam NumberType The type of the length @a len
10045 @pre len >= 1
10046 @return `true` if the string was successfully parsed
10047 */
10048 template<typename NumberType>
10049 bool get_bson_string(const NumberType len, string_t& result)
10050 {
10051 if (JSON_HEDLEY_UNLIKELY(len < 1))
10052 {
10053 auto last_token = get_token_string();
10054 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10055 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
10056 }
10057
10058 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
10059 }
10060
10061 /*!
10062 @brief Parses a byte array input of length @a len from the BSON input.
10063 @param[in] len The length of the byte array to be read.
10064 @param[in,out] result A reference to the binary variable where the read
10065 array is to be stored.
10066 @tparam NumberType The type of the length @a len
10067 @pre len >= 0
10068 @return `true` if the byte array was successfully parsed
10069 */
10070 template<typename NumberType>
10071 bool get_bson_binary(const NumberType len, binary_t& result)
10072 {
10073 if (JSON_HEDLEY_UNLIKELY(len < 0))
10074 {
10075 auto last_token = get_token_string();
10076 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10077 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
10078 }
10079
10080 // All BSON binary values have a subtype
10081 std::uint8_t subtype{};
10082 get_number<std::uint8_t>(input_format_t::bson, subtype);
10083 result.set_subtype(subtype);
10084
10085 return get_binary(input_format_t::bson, len, result);
10086 }
10087
10088 /*!
10089 @brief Read a BSON document element of the given @a element_type.
10090 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
10091 @param[in] element_type_parse_position The position in the input stream,
10092 where the `element_type` was read.
10093 @warning Not all BSON element types are supported yet. An unsupported
10094 @a element_type will give rise to a parse_error.114:
10095 Unsupported BSON record type 0x...
10096 @return whether a valid BSON-object/array was passed to the SAX parser
10097 */
10099 const std::size_t element_type_parse_position)
10100 {
10101 switch (element_type)
10102 {
10103 case 0x01: // double
10104 {
10105 double number{};
10106 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10107 }
10108
10109 case 0x02: // string
10110 {
10111 std::int32_t len{};
10112 string_t value;
10113 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
10114 }
10115
10116 case 0x03: // object
10117 {
10118 return parse_bson_internal();
10119 }
10120
10121 case 0x04: // array
10122 {
10123 return parse_bson_array();
10124 }
10125
10126 case 0x05: // binary
10127 {
10128 std::int32_t len{};
10129 binary_t value;
10130 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
10131 }
10132
10133 case 0x08: // boolean
10134 {
10135 return sax->boolean(get() != 0);
10136 }
10137
10138 case 0x0A: // null
10139 {
10140 return sax->null();
10141 }
10142
10143 case 0x10: // int32
10144 {
10145 std::int32_t value{};
10146 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10147 }
10148
10149 case 0x12: // int64
10150 {
10151 std::int64_t value{};
10152 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10153 }
10154
10155 case 0x11: // uint64
10156 {
10157 std::uint64_t value{};
10158 return get_number<std::uint64_t, true>(input_format_t::bson, value) && sax->number_unsigned(value);
10159 }
10160
10161 default: // anything else is not supported (yet)
10162 {
10163 std::array<char, 3> cr{{}};
10164 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10165 const std::string cr_str{cr.data()};
10166 return sax->parse_error(element_type_parse_position, cr_str,
10167 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
10168 }
10169 }
10170 }
10171
10172 /*!
10173 @brief Read a BSON element list (as specified in the BSON-spec)
10174
10175 The same binary layout is used for objects and arrays, hence it must be
10176 indicated with the argument @a is_array which one is expected
10177 (true --> array, false --> object).
10178
10179 @param[in] is_array Determines if the element list being read is to be
10180 treated as an object (@a is_array == false), or as an
10181 array (@a is_array == true).
10182 @return whether a valid BSON-object/array was passed to the SAX parser
10183 */
10184 bool parse_bson_element_list(const bool is_array)
10185 {
10186 string_t key;
10187
10188 while (auto element_type = get())
10189 {
10190 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
10191 {
10192 return false;
10193 }
10194
10195 const std::size_t element_type_parse_position = chars_read;
10196 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
10197 {
10198 return false;
10199 }
10200
10201 if (!is_array && !sax->key(key))
10202 {
10203 return false;
10204 }
10205
10206 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
10207 {
10208 return false;
10209 }
10210
10211 // get_bson_cstr only appends
10212 key.clear();
10213 }
10214
10215 return true;
10216 }
10217
10218 /*!
10219 @brief Reads an array from the BSON input and passes it to the SAX-parser.
10220 @return whether a valid BSON-array was passed to the SAX parser
10221 */
10223 {
10224 std::int32_t document_size{};
10225 get_number<std::int32_t, true>(input_format_t::bson, document_size);
10226
10227 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
10228 {
10229 return false;
10230 }
10231
10232 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
10233 {
10234 return false;
10235 }
10236
10237 return sax->end_array();
10238 }
10239
10240 //////////
10241 // CBOR //
10242 //////////
10243
10244 /*!
10245 @param[in] get_char whether a new character should be retrieved from the
10246 input (true) or whether the last read character should
10247 be considered instead (false)
10248 @param[in] tag_handler how CBOR tags should be treated
10249
10250 @return whether a valid CBOR value was passed to the SAX parser
10251 */
10252 bool parse_cbor_internal(const bool get_char,
10253 const cbor_tag_handler_t tag_handler)
10254 {
10255 switch (get_char ? get() : current)
10256 {
10257 // EOF
10259 return unexpect_eof(input_format_t::cbor, "value");
10260
10261 // Integer 0x00..0x17 (0..23)
10262 case 0x00:
10263 case 0x01:
10264 case 0x02:
10265 case 0x03:
10266 case 0x04:
10267 case 0x05:
10268 case 0x06:
10269 case 0x07:
10270 case 0x08:
10271 case 0x09:
10272 case 0x0A:
10273 case 0x0B:
10274 case 0x0C:
10275 case 0x0D:
10276 case 0x0E:
10277 case 0x0F:
10278 case 0x10:
10279 case 0x11:
10280 case 0x12:
10281 case 0x13:
10282 case 0x14:
10283 case 0x15:
10284 case 0x16:
10285 case 0x17:
10286 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10287
10288 case 0x18: // Unsigned integer (one-byte uint8_t follows)
10289 {
10290 std::uint8_t number{};
10291 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10292 }
10293
10294 case 0x19: // Unsigned integer (two-byte uint16_t follows)
10295 {
10296 std::uint16_t number{};
10297 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10298 }
10299
10300 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
10301 {
10302 std::uint32_t number{};
10303 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10304 }
10305
10306 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
10307 {
10308 std::uint64_t number{};
10309 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10310 }
10311
10312 // Negative integer -1-0x00..-1-0x17 (-1..-24)
10313 case 0x20:
10314 case 0x21:
10315 case 0x22:
10316 case 0x23:
10317 case 0x24:
10318 case 0x25:
10319 case 0x26:
10320 case 0x27:
10321 case 0x28:
10322 case 0x29:
10323 case 0x2A:
10324 case 0x2B:
10325 case 0x2C:
10326 case 0x2D:
10327 case 0x2E:
10328 case 0x2F:
10329 case 0x30:
10330 case 0x31:
10331 case 0x32:
10332 case 0x33:
10333 case 0x34:
10334 case 0x35:
10335 case 0x36:
10336 case 0x37:
10337 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
10338
10339 case 0x38: // Negative integer (one-byte uint8_t follows)
10340 {
10341 std::uint8_t number{};
10342 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10343 }
10344
10345 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
10346 {
10347 std::uint16_t number{};
10348 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10349 }
10350
10351 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
10352 {
10353 std::uint32_t number{};
10354 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10355 }
10356
10357 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
10358 {
10359 std::uint64_t number{};
10360 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
10361 - static_cast<number_integer_t>(number));
10362 }
10363
10364 // Binary data (0x00..0x17 bytes follow)
10365 case 0x40:
10366 case 0x41:
10367 case 0x42:
10368 case 0x43:
10369 case 0x44:
10370 case 0x45:
10371 case 0x46:
10372 case 0x47:
10373 case 0x48:
10374 case 0x49:
10375 case 0x4A:
10376 case 0x4B:
10377 case 0x4C:
10378 case 0x4D:
10379 case 0x4E:
10380 case 0x4F:
10381 case 0x50:
10382 case 0x51:
10383 case 0x52:
10384 case 0x53:
10385 case 0x54:
10386 case 0x55:
10387 case 0x56:
10388 case 0x57:
10389 case 0x58: // Binary data (one-byte uint8_t for n follows)
10390 case 0x59: // Binary data (two-byte uint16_t for n follow)
10391 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10392 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10393 case 0x5F: // Binary data (indefinite length)
10394 {
10395 binary_t b;
10396 return get_cbor_binary(b) && sax->binary(b);
10397 }
10398
10399 // UTF-8 string (0x00..0x17 bytes follow)
10400 case 0x60:
10401 case 0x61:
10402 case 0x62:
10403 case 0x63:
10404 case 0x64:
10405 case 0x65:
10406 case 0x66:
10407 case 0x67:
10408 case 0x68:
10409 case 0x69:
10410 case 0x6A:
10411 case 0x6B:
10412 case 0x6C:
10413 case 0x6D:
10414 case 0x6E:
10415 case 0x6F:
10416 case 0x70:
10417 case 0x71:
10418 case 0x72:
10419 case 0x73:
10420 case 0x74:
10421 case 0x75:
10422 case 0x76:
10423 case 0x77:
10424 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10425 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10426 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10427 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10428 case 0x7F: // UTF-8 string (indefinite length)
10429 {
10430 string_t s;
10431 return get_cbor_string(s) && sax->string(s);
10432 }
10433
10434 // array (0x00..0x17 data items follow)
10435 case 0x80:
10436 case 0x81:
10437 case 0x82:
10438 case 0x83:
10439 case 0x84:
10440 case 0x85:
10441 case 0x86:
10442 case 0x87:
10443 case 0x88:
10444 case 0x89:
10445 case 0x8A:
10446 case 0x8B:
10447 case 0x8C:
10448 case 0x8D:
10449 case 0x8E:
10450 case 0x8F:
10451 case 0x90:
10452 case 0x91:
10453 case 0x92:
10454 case 0x93:
10455 case 0x94:
10456 case 0x95:
10457 case 0x96:
10458 case 0x97:
10459 return get_cbor_array(
10460 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10461
10462 case 0x98: // array (one-byte uint8_t for n follows)
10463 {
10464 std::uint8_t len{};
10465 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10466 }
10467
10468 case 0x99: // array (two-byte uint16_t for n follow)
10469 {
10470 std::uint16_t len{};
10471 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10472 }
10473
10474 case 0x9A: // array (four-byte uint32_t for n follow)
10475 {
10476 std::uint32_t len{};
10477 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10478 }
10479
10480 case 0x9B: // array (eight-byte uint64_t for n follow)
10481 {
10482 std::uint64_t len{};
10483 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10484 }
10485
10486 case 0x9F: // array (indefinite length)
10487 return get_cbor_array(detail::unknown_size(), tag_handler);
10488
10489 // map (0x00..0x17 pairs of data items follow)
10490 case 0xA0:
10491 case 0xA1:
10492 case 0xA2:
10493 case 0xA3:
10494 case 0xA4:
10495 case 0xA5:
10496 case 0xA6:
10497 case 0xA7:
10498 case 0xA8:
10499 case 0xA9:
10500 case 0xAA:
10501 case 0xAB:
10502 case 0xAC:
10503 case 0xAD:
10504 case 0xAE:
10505 case 0xAF:
10506 case 0xB0:
10507 case 0xB1:
10508 case 0xB2:
10509 case 0xB3:
10510 case 0xB4:
10511 case 0xB5:
10512 case 0xB6:
10513 case 0xB7:
10514 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10515
10516 case 0xB8: // map (one-byte uint8_t for n follows)
10517 {
10518 std::uint8_t len{};
10519 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10520 }
10521
10522 case 0xB9: // map (two-byte uint16_t for n follow)
10523 {
10524 std::uint16_t len{};
10525 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10526 }
10527
10528 case 0xBA: // map (four-byte uint32_t for n follow)
10529 {
10530 std::uint32_t len{};
10531 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10532 }
10533
10534 case 0xBB: // map (eight-byte uint64_t for n follow)
10535 {
10536 std::uint64_t len{};
10537 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10538 }
10539
10540 case 0xBF: // map (indefinite length)
10541 return get_cbor_object(detail::unknown_size(), tag_handler);
10542
10543 case 0xC6: // tagged item
10544 case 0xC7:
10545 case 0xC8:
10546 case 0xC9:
10547 case 0xCA:
10548 case 0xCB:
10549 case 0xCC:
10550 case 0xCD:
10551 case 0xCE:
10552 case 0xCF:
10553 case 0xD0:
10554 case 0xD1:
10555 case 0xD2:
10556 case 0xD3:
10557 case 0xD4:
10558 case 0xD8: // tagged item (1 byte follows)
10559 case 0xD9: // tagged item (2 bytes follow)
10560 case 0xDA: // tagged item (4 bytes follow)
10561 case 0xDB: // tagged item (8 bytes follow)
10562 {
10563 switch (tag_handler)
10564 {
10565 case cbor_tag_handler_t::error:
10566 {
10567 auto last_token = get_token_string();
10568 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10569 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10570 }
10571
10572 case cbor_tag_handler_t::ignore:
10573 {
10574 // ignore binary subtype
10575 switch (current)
10576 {
10577 case 0xD8:
10578 {
10579 std::uint8_t subtype_to_ignore{};
10580 get_number(input_format_t::cbor, subtype_to_ignore);
10581 break;
10582 }
10583 case 0xD9:
10584 {
10585 std::uint16_t subtype_to_ignore{};
10586 get_number(input_format_t::cbor, subtype_to_ignore);
10587 break;
10588 }
10589 case 0xDA:
10590 {
10591 std::uint32_t subtype_to_ignore{};
10592 get_number(input_format_t::cbor, subtype_to_ignore);
10593 break;
10594 }
10595 case 0xDB:
10596 {
10597 std::uint64_t subtype_to_ignore{};
10598 get_number(input_format_t::cbor, subtype_to_ignore);
10599 break;
10600 }
10601 default:
10602 break;
10603 }
10604 return parse_cbor_internal(true, tag_handler);
10605 }
10606
10607 case cbor_tag_handler_t::store:
10608 {
10609 binary_t b;
10610 // use binary subtype and store in a binary container
10611 switch (current)
10612 {
10613 case 0xD8:
10614 {
10615 std::uint8_t subtype{};
10616 get_number(input_format_t::cbor, subtype);
10617 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10618 break;
10619 }
10620 case 0xD9:
10621 {
10622 std::uint16_t subtype{};
10623 get_number(input_format_t::cbor, subtype);
10624 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10625 break;
10626 }
10627 case 0xDA:
10628 {
10629 std::uint32_t subtype{};
10630 get_number(input_format_t::cbor, subtype);
10631 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10632 break;
10633 }
10634 case 0xDB:
10635 {
10636 std::uint64_t subtype{};
10637 get_number(input_format_t::cbor, subtype);
10638 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10639 break;
10640 }
10641 default:
10642 return parse_cbor_internal(true, tag_handler);
10643 }
10644 get();
10645 return get_cbor_binary(b) && sax->binary(b);
10646 }
10647
10648 default: // LCOV_EXCL_LINE
10649 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10650 return false; // LCOV_EXCL_LINE
10651 }
10652 }
10653
10654 case 0xF4: // false
10655 return sax->boolean(false);
10656
10657 case 0xF5: // true
10658 return sax->boolean(true);
10659
10660 case 0xF6: // null
10661 return sax->null();
10662
10663 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10664 {
10665 const auto byte1_raw = get();
10666 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10667 {
10668 return false;
10669 }
10670 const auto byte2_raw = get();
10671 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10672 {
10673 return false;
10674 }
10675
10676 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10677 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10678
10679 // Code from RFC 7049, Appendix D, Figure 3:
10680 // As half-precision floating-point numbers were only added
10681 // to IEEE 754 in 2008, today's programming platforms often
10682 // still only have limited support for them. It is very
10683 // easy to include at least decoding support for them even
10684 // without such support. An example of a small decoder for
10685 // half-precision floating-point numbers in the C language
10686 // is shown in Fig. 3.
10687 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10688 const double val = [&half]
10689 {
10690 const int exp = (half >> 10u) & 0x1Fu;
10691 const unsigned int mant = half & 0x3FFu;
10692 JSON_ASSERT(0 <= exp&& exp <= 32);
10693 JSON_ASSERT(mant <= 1024);
10694 switch (exp)
10695 {
10696 case 0:
10697 return std::ldexp(mant, -24);
10698 case 31:
10699 return (mant == 0)
10700 ? std::numeric_limits<double>::infinity()
10701 : std::numeric_limits<double>::quiet_NaN();
10702 default:
10703 return std::ldexp(mant + 1024, exp - 25);
10704 }
10705 }();
10706 return sax->number_float((half & 0x8000u) != 0
10707 ? static_cast<number_float_t>(-val)
10708 : static_cast<number_float_t>(val), "");
10709 }
10710
10711 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10712 {
10713 float number{};
10714 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10715 }
10716
10717 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10718 {
10719 double number{};
10720 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10721 }
10722
10723 default: // anything else (0xFF is handled inside the other types)
10724 {
10725 auto last_token = get_token_string();
10726 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10727 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10728 }
10729 }
10730 }
10731
10732 /*!
10733 @brief reads a CBOR string
10734
10735 This function first reads starting bytes to determine the expected
10736 string length and then copies this number of bytes into a string.
10737 Additionally, CBOR's strings with indefinite lengths are supported.
10738
10739 @param[out] result created string
10740
10741 @return whether string creation completed
10742 */
10744 {
10745 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10746 {
10747 return false;
10748 }
10749
10750 switch (current)
10751 {
10752 // UTF-8 string (0x00..0x17 bytes follow)
10753 case 0x60:
10754 case 0x61:
10755 case 0x62:
10756 case 0x63:
10757 case 0x64:
10758 case 0x65:
10759 case 0x66:
10760 case 0x67:
10761 case 0x68:
10762 case 0x69:
10763 case 0x6A:
10764 case 0x6B:
10765 case 0x6C:
10766 case 0x6D:
10767 case 0x6E:
10768 case 0x6F:
10769 case 0x70:
10770 case 0x71:
10771 case 0x72:
10772 case 0x73:
10773 case 0x74:
10774 case 0x75:
10775 case 0x76:
10776 case 0x77:
10777 {
10778 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10779 }
10780
10781 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10782 {
10783 std::uint8_t len{};
10784 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10785 }
10786
10787 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10788 {
10789 std::uint16_t len{};
10790 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10791 }
10792
10793 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10794 {
10795 std::uint32_t len{};
10796 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10797 }
10798
10799 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10800 {
10801 std::uint64_t len{};
10802 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10803 }
10804
10805 case 0x7F: // UTF-8 string (indefinite length)
10806 {
10807 while (get() != 0xFF)
10808 {
10809 string_t chunk;
10810 if (!get_cbor_string(chunk))
10811 {
10812 return false;
10813 }
10814 result.append(chunk);
10815 }
10816 return true;
10817 }
10818
10819 default:
10820 {
10821 auto last_token = get_token_string();
10822 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10823 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10824 }
10825 }
10826 }
10827
10828 /*!
10829 @brief reads a CBOR byte array
10830
10831 This function first reads starting bytes to determine the expected
10832 byte array length and then copies this number of bytes into the byte array.
10833 Additionally, CBOR's byte arrays with indefinite lengths are supported.
10834
10835 @param[out] result created byte array
10836
10837 @return whether byte array creation completed
10838 */
10840 {
10841 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10842 {
10843 return false;
10844 }
10845
10846 switch (current)
10847 {
10848 // Binary data (0x00..0x17 bytes follow)
10849 case 0x40:
10850 case 0x41:
10851 case 0x42:
10852 case 0x43:
10853 case 0x44:
10854 case 0x45:
10855 case 0x46:
10856 case 0x47:
10857 case 0x48:
10858 case 0x49:
10859 case 0x4A:
10860 case 0x4B:
10861 case 0x4C:
10862 case 0x4D:
10863 case 0x4E:
10864 case 0x4F:
10865 case 0x50:
10866 case 0x51:
10867 case 0x52:
10868 case 0x53:
10869 case 0x54:
10870 case 0x55:
10871 case 0x56:
10872 case 0x57:
10873 {
10874 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10875 }
10876
10877 case 0x58: // Binary data (one-byte uint8_t for n follows)
10878 {
10879 std::uint8_t len{};
10880 return get_number(input_format_t::cbor, len) &&
10881 get_binary(input_format_t::cbor, len, result);
10882 }
10883
10884 case 0x59: // Binary data (two-byte uint16_t for n follow)
10885 {
10886 std::uint16_t len{};
10887 return get_number(input_format_t::cbor, len) &&
10888 get_binary(input_format_t::cbor, len, result);
10889 }
10890
10891 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10892 {
10893 std::uint32_t len{};
10894 return get_number(input_format_t::cbor, len) &&
10895 get_binary(input_format_t::cbor, len, result);
10896 }
10897
10898 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10899 {
10900 std::uint64_t len{};
10901 return get_number(input_format_t::cbor, len) &&
10902 get_binary(input_format_t::cbor, len, result);
10903 }
10904
10905 case 0x5F: // Binary data (indefinite length)
10906 {
10907 while (get() != 0xFF)
10908 {
10909 binary_t chunk;
10910 if (!get_cbor_binary(chunk))
10911 {
10912 return false;
10913 }
10914 result.insert(result.end(), chunk.begin(), chunk.end());
10915 }
10916 return true;
10917 }
10918
10919 default:
10920 {
10921 auto last_token = get_token_string();
10922 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10923 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));
10924 }
10925 }
10926 }
10927
10928 /*!
10929 @param[in] len the length of the array or detail::unknown_size() for an
10930 array of indefinite size
10931 @param[in] tag_handler how CBOR tags should be treated
10932 @return whether array creation completed
10933 */
10934 bool get_cbor_array(const std::size_t len,
10935 const cbor_tag_handler_t tag_handler)
10936 {
10937 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10938 {
10939 return false;
10940 }
10941
10942 if (len != detail::unknown_size())
10943 {
10944 for (std::size_t i = 0; i < len; ++i)
10945 {
10946 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10947 {
10948 return false;
10949 }
10950 }
10951 }
10952 else
10953 {
10954 while (get() != 0xFF)
10955 {
10956 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10957 {
10958 return false;
10959 }
10960 }
10961 }
10962
10963 return sax->end_array();
10964 }
10965
10966 /*!
10967 @param[in] len the length of the object or detail::unknown_size() for an
10968 object of indefinite size
10969 @param[in] tag_handler how CBOR tags should be treated
10970 @return whether object creation completed
10971 */
10972 bool get_cbor_object(const std::size_t len,
10973 const cbor_tag_handler_t tag_handler)
10974 {
10975 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10976 {
10977 return false;
10978 }
10979
10980 if (len != 0)
10981 {
10982 string_t key;
10983 if (len != detail::unknown_size())
10984 {
10985 for (std::size_t i = 0; i < len; ++i)
10986 {
10987 get();
10988 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10989 {
10990 return false;
10991 }
10992
10993 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10994 {
10995 return false;
10996 }
10997 key.clear();
10998 }
10999 }
11000 else
11001 {
11002 while (get() != 0xFF)
11003 {
11004 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
11005 {
11006 return false;
11007 }
11008
11009 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
11010 {
11011 return false;
11012 }
11013 key.clear();
11014 }
11015 }
11016 }
11017
11018 return sax->end_object();
11019 }
11020
11021 /////////////
11022 // MsgPack //
11023 /////////////
11024
11025 /*!
11026 @return whether a valid MessagePack value was passed to the SAX parser
11027 */
11029 {
11030 switch (get())
11031 {
11032 // EOF
11034 return unexpect_eof(input_format_t::msgpack, "value");
11035
11036 // positive fixint
11037 case 0x00:
11038 case 0x01:
11039 case 0x02:
11040 case 0x03:
11041 case 0x04:
11042 case 0x05:
11043 case 0x06:
11044 case 0x07:
11045 case 0x08:
11046 case 0x09:
11047 case 0x0A:
11048 case 0x0B:
11049 case 0x0C:
11050 case 0x0D:
11051 case 0x0E:
11052 case 0x0F:
11053 case 0x10:
11054 case 0x11:
11055 case 0x12:
11056 case 0x13:
11057 case 0x14:
11058 case 0x15:
11059 case 0x16:
11060 case 0x17:
11061 case 0x18:
11062 case 0x19:
11063 case 0x1A:
11064 case 0x1B:
11065 case 0x1C:
11066 case 0x1D:
11067 case 0x1E:
11068 case 0x1F:
11069 case 0x20:
11070 case 0x21:
11071 case 0x22:
11072 case 0x23:
11073 case 0x24:
11074 case 0x25:
11075 case 0x26:
11076 case 0x27:
11077 case 0x28:
11078 case 0x29:
11079 case 0x2A:
11080 case 0x2B:
11081 case 0x2C:
11082 case 0x2D:
11083 case 0x2E:
11084 case 0x2F:
11085 case 0x30:
11086 case 0x31:
11087 case 0x32:
11088 case 0x33:
11089 case 0x34:
11090 case 0x35:
11091 case 0x36:
11092 case 0x37:
11093 case 0x38:
11094 case 0x39:
11095 case 0x3A:
11096 case 0x3B:
11097 case 0x3C:
11098 case 0x3D:
11099 case 0x3E:
11100 case 0x3F:
11101 case 0x40:
11102 case 0x41:
11103 case 0x42:
11104 case 0x43:
11105 case 0x44:
11106 case 0x45:
11107 case 0x46:
11108 case 0x47:
11109 case 0x48:
11110 case 0x49:
11111 case 0x4A:
11112 case 0x4B:
11113 case 0x4C:
11114 case 0x4D:
11115 case 0x4E:
11116 case 0x4F:
11117 case 0x50:
11118 case 0x51:
11119 case 0x52:
11120 case 0x53:
11121 case 0x54:
11122 case 0x55:
11123 case 0x56:
11124 case 0x57:
11125 case 0x58:
11126 case 0x59:
11127 case 0x5A:
11128 case 0x5B:
11129 case 0x5C:
11130 case 0x5D:
11131 case 0x5E:
11132 case 0x5F:
11133 case 0x60:
11134 case 0x61:
11135 case 0x62:
11136 case 0x63:
11137 case 0x64:
11138 case 0x65:
11139 case 0x66:
11140 case 0x67:
11141 case 0x68:
11142 case 0x69:
11143 case 0x6A:
11144 case 0x6B:
11145 case 0x6C:
11146 case 0x6D:
11147 case 0x6E:
11148 case 0x6F:
11149 case 0x70:
11150 case 0x71:
11151 case 0x72:
11152 case 0x73:
11153 case 0x74:
11154 case 0x75:
11155 case 0x76:
11156 case 0x77:
11157 case 0x78:
11158 case 0x79:
11159 case 0x7A:
11160 case 0x7B:
11161 case 0x7C:
11162 case 0x7D:
11163 case 0x7E:
11164 case 0x7F:
11165 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
11166
11167 // fixmap
11168 case 0x80:
11169 case 0x81:
11170 case 0x82:
11171 case 0x83:
11172 case 0x84:
11173 case 0x85:
11174 case 0x86:
11175 case 0x87:
11176 case 0x88:
11177 case 0x89:
11178 case 0x8A:
11179 case 0x8B:
11180 case 0x8C:
11181 case 0x8D:
11182 case 0x8E:
11183 case 0x8F:
11184 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11185
11186 // fixarray
11187 case 0x90:
11188 case 0x91:
11189 case 0x92:
11190 case 0x93:
11191 case 0x94:
11192 case 0x95:
11193 case 0x96:
11194 case 0x97:
11195 case 0x98:
11196 case 0x99:
11197 case 0x9A:
11198 case 0x9B:
11199 case 0x9C:
11200 case 0x9D:
11201 case 0x9E:
11202 case 0x9F:
11203 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11204
11205 // fixstr
11206 case 0xA0:
11207 case 0xA1:
11208 case 0xA2:
11209 case 0xA3:
11210 case 0xA4:
11211 case 0xA5:
11212 case 0xA6:
11213 case 0xA7:
11214 case 0xA8:
11215 case 0xA9:
11216 case 0xAA:
11217 case 0xAB:
11218 case 0xAC:
11219 case 0xAD:
11220 case 0xAE:
11221 case 0xAF:
11222 case 0xB0:
11223 case 0xB1:
11224 case 0xB2:
11225 case 0xB3:
11226 case 0xB4:
11227 case 0xB5:
11228 case 0xB6:
11229 case 0xB7:
11230 case 0xB8:
11231 case 0xB9:
11232 case 0xBA:
11233 case 0xBB:
11234 case 0xBC:
11235 case 0xBD:
11236 case 0xBE:
11237 case 0xBF:
11238 case 0xD9: // str 8
11239 case 0xDA: // str 16
11240 case 0xDB: // str 32
11241 {
11242 string_t s;
11243 return get_msgpack_string(s) && sax->string(s);
11244 }
11245
11246 case 0xC0: // nil
11247 return sax->null();
11248
11249 case 0xC2: // false
11250 return sax->boolean(false);
11251
11252 case 0xC3: // true
11253 return sax->boolean(true);
11254
11255 case 0xC4: // bin 8
11256 case 0xC5: // bin 16
11257 case 0xC6: // bin 32
11258 case 0xC7: // ext 8
11259 case 0xC8: // ext 16
11260 case 0xC9: // ext 32
11261 case 0xD4: // fixext 1
11262 case 0xD5: // fixext 2
11263 case 0xD6: // fixext 4
11264 case 0xD7: // fixext 8
11265 case 0xD8: // fixext 16
11266 {
11267 binary_t b;
11268 return get_msgpack_binary(b) && sax->binary(b);
11269 }
11270
11271 case 0xCA: // float 32
11272 {
11273 float number{};
11274 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11275 }
11276
11277 case 0xCB: // float 64
11278 {
11279 double number{};
11280 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11281 }
11282
11283 case 0xCC: // uint 8
11284 {
11285 std::uint8_t number{};
11286 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11287 }
11288
11289 case 0xCD: // uint 16
11290 {
11291 std::uint16_t number{};
11292 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11293 }
11294
11295 case 0xCE: // uint 32
11296 {
11297 std::uint32_t number{};
11298 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11299 }
11300
11301 case 0xCF: // uint 64
11302 {
11303 std::uint64_t number{};
11304 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11305 }
11306
11307 case 0xD0: // int 8
11308 {
11309 std::int8_t number{};
11310 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11311 }
11312
11313 case 0xD1: // int 16
11314 {
11315 std::int16_t number{};
11316 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11317 }
11318
11319 case 0xD2: // int 32
11320 {
11321 std::int32_t number{};
11322 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11323 }
11324
11325 case 0xD3: // int 64
11326 {
11327 std::int64_t number{};
11328 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11329 }
11330
11331 case 0xDC: // array 16
11332 {
11333 std::uint16_t len{};
11334 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
11335 }
11336
11337 case 0xDD: // array 32
11338 {
11339 std::uint32_t len{};
11340 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
11341 }
11342
11343 case 0xDE: // map 16
11344 {
11345 std::uint16_t len{};
11346 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
11347 }
11348
11349 case 0xDF: // map 32
11350 {
11351 std::uint32_t len{};
11352 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
11353 }
11354
11355 // negative fixint
11356 case 0xE0:
11357 case 0xE1:
11358 case 0xE2:
11359 case 0xE3:
11360 case 0xE4:
11361 case 0xE5:
11362 case 0xE6:
11363 case 0xE7:
11364 case 0xE8:
11365 case 0xE9:
11366 case 0xEA:
11367 case 0xEB:
11368 case 0xEC:
11369 case 0xED:
11370 case 0xEE:
11371 case 0xEF:
11372 case 0xF0:
11373 case 0xF1:
11374 case 0xF2:
11375 case 0xF3:
11376 case 0xF4:
11377 case 0xF5:
11378 case 0xF6:
11379 case 0xF7:
11380 case 0xF8:
11381 case 0xF9:
11382 case 0xFA:
11383 case 0xFB:
11384 case 0xFC:
11385 case 0xFD:
11386 case 0xFE:
11387 case 0xFF:
11388 return sax->number_integer(static_cast<std::int8_t>(current));
11389
11390 default: // anything else
11391 {
11392 auto last_token = get_token_string();
11393 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11394 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
11395 }
11396 }
11397 }
11398
11399 /*!
11400 @brief reads a MessagePack string
11401
11402 This function first reads starting bytes to determine the expected
11403 string length and then copies this number of bytes into a string.
11404
11405 @param[out] result created string
11406
11407 @return whether string creation completed
11408 */
11410 {
11411 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
11412 {
11413 return false;
11414 }
11415
11416 switch (current)
11417 {
11418 // fixstr
11419 case 0xA0:
11420 case 0xA1:
11421 case 0xA2:
11422 case 0xA3:
11423 case 0xA4:
11424 case 0xA5:
11425 case 0xA6:
11426 case 0xA7:
11427 case 0xA8:
11428 case 0xA9:
11429 case 0xAA:
11430 case 0xAB:
11431 case 0xAC:
11432 case 0xAD:
11433 case 0xAE:
11434 case 0xAF:
11435 case 0xB0:
11436 case 0xB1:
11437 case 0xB2:
11438 case 0xB3:
11439 case 0xB4:
11440 case 0xB5:
11441 case 0xB6:
11442 case 0xB7:
11443 case 0xB8:
11444 case 0xB9:
11445 case 0xBA:
11446 case 0xBB:
11447 case 0xBC:
11448 case 0xBD:
11449 case 0xBE:
11450 case 0xBF:
11451 {
11452 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
11453 }
11454
11455 case 0xD9: // str 8
11456 {
11457 std::uint8_t len{};
11458 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11459 }
11460
11461 case 0xDA: // str 16
11462 {
11463 std::uint16_t len{};
11464 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11465 }
11466
11467 case 0xDB: // str 32
11468 {
11469 std::uint32_t len{};
11470 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11471 }
11472
11473 default:
11474 {
11475 auto last_token = get_token_string();
11476 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11477 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
11478 }
11479 }
11480 }
11481
11482 /*!
11483 @brief reads a MessagePack byte array
11484
11485 This function first reads starting bytes to determine the expected
11486 byte array length and then copies this number of bytes into a byte array.
11487
11488 @param[out] result created byte array
11489
11490 @return whether byte array creation completed
11491 */
11493 {
11494 // helper function to set the subtype
11495 auto assign_and_return_true = [&result](std::int8_t subtype)
11496 {
11497 result.set_subtype(static_cast<std::uint8_t>(subtype));
11498 return true;
11499 };
11500
11501 switch (current)
11502 {
11503 case 0xC4: // bin 8
11504 {
11505 std::uint8_t len{};
11506 return get_number(input_format_t::msgpack, len) &&
11507 get_binary(input_format_t::msgpack, len, result);
11508 }
11509
11510 case 0xC5: // bin 16
11511 {
11512 std::uint16_t len{};
11513 return get_number(input_format_t::msgpack, len) &&
11514 get_binary(input_format_t::msgpack, len, result);
11515 }
11516
11517 case 0xC6: // bin 32
11518 {
11519 std::uint32_t len{};
11520 return get_number(input_format_t::msgpack, len) &&
11521 get_binary(input_format_t::msgpack, len, result);
11522 }
11523
11524 case 0xC7: // ext 8
11525 {
11526 std::uint8_t len{};
11527 std::int8_t subtype{};
11528 return get_number(input_format_t::msgpack, len) &&
11529 get_number(input_format_t::msgpack, subtype) &&
11530 get_binary(input_format_t::msgpack, len, result) &&
11531 assign_and_return_true(subtype);
11532 }
11533
11534 case 0xC8: // ext 16
11535 {
11536 std::uint16_t len{};
11537 std::int8_t subtype{};
11538 return get_number(input_format_t::msgpack, len) &&
11539 get_number(input_format_t::msgpack, subtype) &&
11540 get_binary(input_format_t::msgpack, len, result) &&
11541 assign_and_return_true(subtype);
11542 }
11543
11544 case 0xC9: // ext 32
11545 {
11546 std::uint32_t len{};
11547 std::int8_t subtype{};
11548 return get_number(input_format_t::msgpack, len) &&
11549 get_number(input_format_t::msgpack, subtype) &&
11550 get_binary(input_format_t::msgpack, len, result) &&
11551 assign_and_return_true(subtype);
11552 }
11553
11554 case 0xD4: // fixext 1
11555 {
11556 std::int8_t subtype{};
11557 return get_number(input_format_t::msgpack, subtype) &&
11558 get_binary(input_format_t::msgpack, 1, result) &&
11559 assign_and_return_true(subtype);
11560 }
11561
11562 case 0xD5: // fixext 2
11563 {
11564 std::int8_t subtype{};
11565 return get_number(input_format_t::msgpack, subtype) &&
11566 get_binary(input_format_t::msgpack, 2, result) &&
11567 assign_and_return_true(subtype);
11568 }
11569
11570 case 0xD6: // fixext 4
11571 {
11572 std::int8_t subtype{};
11573 return get_number(input_format_t::msgpack, subtype) &&
11574 get_binary(input_format_t::msgpack, 4, result) &&
11575 assign_and_return_true(subtype);
11576 }
11577
11578 case 0xD7: // fixext 8
11579 {
11580 std::int8_t subtype{};
11581 return get_number(input_format_t::msgpack, subtype) &&
11582 get_binary(input_format_t::msgpack, 8, result) &&
11583 assign_and_return_true(subtype);
11584 }
11585
11586 case 0xD8: // fixext 16
11587 {
11588 std::int8_t subtype{};
11589 return get_number(input_format_t::msgpack, subtype) &&
11590 get_binary(input_format_t::msgpack, 16, result) &&
11591 assign_and_return_true(subtype);
11592 }
11593
11594 default: // LCOV_EXCL_LINE
11595 return false; // LCOV_EXCL_LINE
11596 }
11597 }
11598
11599 /*!
11600 @param[in] len the length of the array
11601 @return whether array creation completed
11602 */
11603 bool get_msgpack_array(const std::size_t len)
11604 {
11605 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
11606 {
11607 return false;
11608 }
11609
11610 for (std::size_t i = 0; i < len; ++i)
11611 {
11612 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11613 {
11614 return false;
11615 }
11616 }
11617
11618 return sax->end_array();
11619 }
11620
11621 /*!
11622 @param[in] len the length of the object
11623 @return whether object creation completed
11624 */
11625 bool get_msgpack_object(const std::size_t len)
11626 {
11627 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
11628 {
11629 return false;
11630 }
11631
11632 string_t key;
11633 for (std::size_t i = 0; i < len; ++i)
11634 {
11635 get();
11636 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
11637 {
11638 return false;
11639 }
11640
11641 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11642 {
11643 return false;
11644 }
11645 key.clear();
11646 }
11647
11648 return sax->end_object();
11649 }
11650
11651 ////////////
11652 // UBJSON //
11653 ////////////
11654
11655 /*!
11656 @param[in] get_char whether a new character should be retrieved from the
11657 input (true, default) or whether the last read
11658 character should be considered instead
11659
11660 @return whether a valid UBJSON value was passed to the SAX parser
11661 */
11662 bool parse_ubjson_internal(const bool get_char = true)
11663 {
11664 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11665 }
11666
11667 /*!
11668 @brief reads a UBJSON string
11669
11670 This function is either called after reading the 'S' byte explicitly
11671 indicating a string, or in case of an object key where the 'S' byte can be
11672 left out.
11673
11674 @param[out] result created string
11675 @param[in] get_char whether a new character should be retrieved from the
11676 input (true, default) or whether the last read
11677 character should be considered instead
11678
11679 @return whether string creation completed
11680 */
11681 bool get_ubjson_string(string_t& result, const bool get_char = true)
11682 {
11683 if (get_char)
11684 {
11685 get(); // TODO(niels): may we ignore N here?
11686 }
11687
11688 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11689 {
11690 return false;
11691 }
11692
11693 switch (current)
11694 {
11695 case 'U':
11696 {
11697 std::uint8_t len{};
11698 return get_number(input_format, len) && get_string(input_format, len, result);
11699 }
11700
11701 case 'i':
11702 {
11703 std::int8_t len{};
11704 return get_number(input_format, len) && get_string(input_format, len, result);
11705 }
11706
11707 case 'I':
11708 {
11709 std::int16_t len{};
11710 return get_number(input_format, len) && get_string(input_format, len, result);
11711 }
11712
11713 case 'l':
11714 {
11715 std::int32_t len{};
11716 return get_number(input_format, len) && get_string(input_format, len, result);
11717 }
11718
11719 case 'L':
11720 {
11721 std::int64_t len{};
11722 return get_number(input_format, len) && get_string(input_format, len, result);
11723 }
11724
11725 case 'u':
11726 {
11727 if (input_format != input_format_t::bjdata)
11728 {
11729 break;
11730 }
11731 std::uint16_t len{};
11732 return get_number(input_format, len) && get_string(input_format, len, result);
11733 }
11734
11735 case 'm':
11736 {
11737 if (input_format != input_format_t::bjdata)
11738 {
11739 break;
11740 }
11741 std::uint32_t len{};
11742 return get_number(input_format, len) && get_string(input_format, len, result);
11743 }
11744
11745 case 'M':
11746 {
11747 if (input_format != input_format_t::bjdata)
11748 {
11749 break;
11750 }
11751 std::uint64_t len{};
11752 return get_number(input_format, len) && get_string(input_format, len, result);
11753 }
11754
11755 default:
11756 break;
11757 }
11758 auto last_token = get_token_string();
11759 std::string message;
11760
11761 if (input_format != input_format_t::bjdata)
11762 {
11763 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11764 }
11765 else
11766 {
11767 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11768 }
11769 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11770 }
11771
11772 /*!
11773 @param[out] dim an integer vector storing the ND array dimensions
11774 @return whether reading ND array size vector is successful
11775 */
11776 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11777 {
11778 std::pair<std::size_t, char_int_type> size_and_type;
11779 size_t dimlen = 0;
11780 bool no_ndarray = true;
11781
11782 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11783 {
11784 return false;
11785 }
11786
11787 if (size_and_type.first != npos)
11788 {
11789 if (size_and_type.second != 0)
11790 {
11791 if (size_and_type.second != 'N')
11792 {
11793 for (std::size_t i = 0; i < size_and_type.first; ++i)
11794 {
11795 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11796 {
11797 return false;
11798 }
11799 dim.push_back(dimlen);
11800 }
11801 }
11802 }
11803 else
11804 {
11805 for (std::size_t i = 0; i < size_and_type.first; ++i)
11806 {
11807 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11808 {
11809 return false;
11810 }
11811 dim.push_back(dimlen);
11812 }
11813 }
11814 }
11815 else
11816 {
11817 while (current != ']')
11818 {
11819 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11820 {
11821 return false;
11822 }
11823 dim.push_back(dimlen);
11824 get_ignore_noop();
11825 }
11826 }
11827 return true;
11828 }
11829
11830 /*!
11831 @param[out] result determined size
11832 @param[in,out] is_ndarray for input, `true` means already inside an ndarray vector
11833 or ndarray dimension is not allowed; `false` means ndarray
11834 is allowed; for output, `true` means an ndarray is found;
11835 is_ndarray can only return `true` when its initial value
11836 is `false`
11837 @param[in] prefix type marker if already read, otherwise set to 0
11838
11839 @return whether size determination completed
11840 */
11841 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11842 {
11843 if (prefix == 0)
11844 {
11845 prefix = get_ignore_noop();
11846 }
11847
11848 switch (prefix)
11849 {
11850 case 'U':
11851 {
11852 std::uint8_t number{};
11853 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11854 {
11855 return false;
11856 }
11857 result = static_cast<std::size_t>(number);
11858 return true;
11859 }
11860
11861 case 'i':
11862 {
11863 std::int8_t number{};
11864 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11865 {
11866 return false;
11867 }
11868 if (number < 0)
11869 {
11870 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11871 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11872 }
11873 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11874 return true;
11875 }
11876
11877 case 'I':
11878 {
11879 std::int16_t number{};
11880 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11881 {
11882 return false;
11883 }
11884 if (number < 0)
11885 {
11886 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11887 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11888 }
11889 result = static_cast<std::size_t>(number);
11890 return true;
11891 }
11892
11893 case 'l':
11894 {
11895 std::int32_t number{};
11896 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11897 {
11898 return false;
11899 }
11900 if (number < 0)
11901 {
11902 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11903 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11904 }
11905 result = static_cast<std::size_t>(number);
11906 return true;
11907 }
11908
11909 case 'L':
11910 {
11911 std::int64_t number{};
11912 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11913 {
11914 return false;
11915 }
11916 if (number < 0)
11917 {
11918 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11919 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11920 }
11921 if (!value_in_range_of<std::size_t>(number))
11922 {
11923 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11924 exception_message(input_format, "integer value overflow", "size"), nullptr));
11925 }
11926 result = static_cast<std::size_t>(number);
11927 return true;
11928 }
11929
11930 case 'u':
11931 {
11932 if (input_format != input_format_t::bjdata)
11933 {
11934 break;
11935 }
11936 std::uint16_t number{};
11937 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11938 {
11939 return false;
11940 }
11941 result = static_cast<std::size_t>(number);
11942 return true;
11943 }
11944
11945 case 'm':
11946 {
11947 if (input_format != input_format_t::bjdata)
11948 {
11949 break;
11950 }
11951 std::uint32_t number{};
11952 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11953 {
11954 return false;
11955 }
11956 result = conditional_static_cast<std::size_t>(number);
11957 return true;
11958 }
11959
11960 case 'M':
11961 {
11962 if (input_format != input_format_t::bjdata)
11963 {
11964 break;
11965 }
11966 std::uint64_t number{};
11967 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11968 {
11969 return false;
11970 }
11971 if (!value_in_range_of<std::size_t>(number))
11972 {
11973 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11974 exception_message(input_format, "integer value overflow", "size"), nullptr));
11975 }
11976 result = detail::conditional_static_cast<std::size_t>(number);
11977 return true;
11978 }
11979
11980 case '[':
11981 {
11982 if (input_format != input_format_t::bjdata)
11983 {
11984 break;
11985 }
11986 if (is_ndarray) // ndarray dimensional vector can only contain integers and cannot embed another array
11987 {
11988 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));
11989 }
11990 std::vector<size_t> dim;
11991 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11992 {
11993 return false;
11994 }
11995 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11996 {
11997 result = dim.at(dim.size() - 1);
11998 return true;
11999 }
12000 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
12001 {
12002 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
12003 {
12004 if ( i == 0 )
12005 {
12006 result = 0;
12007 return true;
12008 }
12009 }
12010
12011 string_t key = "_ArraySize_";
12012 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
12013 {
12014 return false;
12015 }
12016 result = 1;
12017 for (auto i : dim)
12018 {
12019 // Pre-multiplication overflow check: if i > 0 and result > SIZE_MAX/i, then result*i would overflow.
12020 // This check must happen before multiplication since overflow detection after the fact is unreliable
12021 // as modular arithmetic can produce any value, not just 0 or SIZE_MAX.
12022 if (JSON_HEDLEY_UNLIKELY(i > 0 && result > (std::numeric_limits<std::size_t>::max)() / i))
12023 {
12024 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));
12025 }
12026 result *= i;
12027 // Additional post-multiplication check to catch any edge cases the pre-check might miss
12028 if (result == 0 || result == npos)
12029 {
12030 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));
12031 }
12032 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
12033 {
12034 return false;
12035 }
12036 }
12037 is_ndarray = true;
12038 return sax->end_array();
12039 }
12040 result = 0;
12041 return true;
12042 }
12043
12044 default:
12045 break;
12046 }
12047 auto last_token = get_token_string();
12048 std::string message;
12049
12050 if (input_format != input_format_t::bjdata)
12051 {
12052 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
12053 }
12054 else
12055 {
12056 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
12057 }
12058 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
12059 }
12060
12061 /*!
12062 @brief determine the type and size for a container
12063
12064 In the optimized UBJSON format, a type and a size can be provided to allow
12065 for a more compact representation.
12066
12067 @param[out] result pair of the size and the type
12068 @param[in] inside_ndarray whether the parser is parsing an ND array dimensional vector
12069
12070 @return whether pair creation completed
12071 */
12072 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
12073 {
12074 result.first = npos; // size
12075 result.second = 0; // type
12076 bool is_ndarray = false;
12077
12078 get_ignore_noop();
12079
12080 if (current == '$')
12081 {
12082 result.second = get(); // must not ignore 'N', because 'N' maybe the type
12083 if (input_format == input_format_t::bjdata
12084 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
12085 {
12086 auto last_token = get_token_string();
12087 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12088 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
12089 }
12090
12091 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
12092 {
12093 return false;
12094 }
12095
12096 get_ignore_noop();
12097 if (JSON_HEDLEY_UNLIKELY(current != '#'))
12098 {
12099 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
12100 {
12101 return false;
12102 }
12103 auto last_token = get_token_string();
12104 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12105 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
12106 }
12107
12108 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12109 if (input_format == input_format_t::bjdata && is_ndarray)
12110 {
12111 if (inside_ndarray)
12112 {
12113 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12114 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
12115 }
12116 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
12117 }
12118 return is_error;
12119 }
12120
12121 if (current == '#')
12122 {
12123 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12124 if (input_format == input_format_t::bjdata && is_ndarray)
12125 {
12126 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12127 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
12128 }
12129 return is_error;
12130 }
12131
12132 return true;
12133 }
12134
12135 /*!
12136 @param prefix the previously read or set type prefix
12137 @return whether value creation completed
12138 */
12140 {
12141 switch (prefix)
12142 {
12143 case char_traits<char_type>::eof(): // EOF
12144 return unexpect_eof(input_format, "value");
12145
12146 case 'T': // true
12147 return sax->boolean(true);
12148 case 'F': // false
12149 return sax->boolean(false);
12150
12151 case 'Z': // null
12152 return sax->null();
12153
12154 case 'B': // byte
12155 {
12156 if (input_format != input_format_t::bjdata)
12157 {
12158 break;
12159 }
12160 std::uint8_t number{};
12161 return get_number(input_format, number) && sax->number_unsigned(number);
12162 }
12163
12164 case 'U':
12165 {
12166 std::uint8_t number{};
12167 return get_number(input_format, number) && sax->number_unsigned(number);
12168 }
12169
12170 case 'i':
12171 {
12172 std::int8_t number{};
12173 return get_number(input_format, number) && sax->number_integer(number);
12174 }
12175
12176 case 'I':
12177 {
12178 std::int16_t number{};
12179 return get_number(input_format, number) && sax->number_integer(number);
12180 }
12181
12182 case 'l':
12183 {
12184 std::int32_t number{};
12185 return get_number(input_format, number) && sax->number_integer(number);
12186 }
12187
12188 case 'L':
12189 {
12190 std::int64_t number{};
12191 return get_number(input_format, number) && sax->number_integer(number);
12192 }
12193
12194 case 'u':
12195 {
12196 if (input_format != input_format_t::bjdata)
12197 {
12198 break;
12199 }
12200 std::uint16_t number{};
12201 return get_number(input_format, number) && sax->number_unsigned(number);
12202 }
12203
12204 case 'm':
12205 {
12206 if (input_format != input_format_t::bjdata)
12207 {
12208 break;
12209 }
12210 std::uint32_t number{};
12211 return get_number(input_format, number) && sax->number_unsigned(number);
12212 }
12213
12214 case 'M':
12215 {
12216 if (input_format != input_format_t::bjdata)
12217 {
12218 break;
12219 }
12220 std::uint64_t number{};
12221 return get_number(input_format, number) && sax->number_unsigned(number);
12222 }
12223
12224 case 'h':
12225 {
12226 if (input_format != input_format_t::bjdata)
12227 {
12228 break;
12229 }
12230 const auto byte1_raw = get();
12231 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12232 {
12233 return false;
12234 }
12235 const auto byte2_raw = get();
12236 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12237 {
12238 return false;
12239 }
12240
12241 const auto byte1 = static_cast<unsigned char>(byte1_raw);
12242 const auto byte2 = static_cast<unsigned char>(byte2_raw);
12243
12244 // Code from RFC 7049, Appendix D, Figure 3:
12245 // As half-precision floating-point numbers were only added
12246 // to IEEE 754 in 2008, today's programming platforms often
12247 // still only have limited support for them. It is very
12248 // easy to include at least decoding support for them even
12249 // without such support. An example of a small decoder for
12250 // half-precision floating-point numbers in the C language
12251 // is shown in Fig. 3.
12252 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
12253 const double val = [&half]
12254 {
12255 const int exp = (half >> 10u) & 0x1Fu;
12256 const unsigned int mant = half & 0x3FFu;
12257 JSON_ASSERT(0 <= exp&& exp <= 32);
12258 JSON_ASSERT(mant <= 1024);
12259 switch (exp)
12260 {
12261 case 0:
12262 return std::ldexp(mant, -24);
12263 case 31:
12264 return (mant == 0)
12265 ? std::numeric_limits<double>::infinity()
12266 : std::numeric_limits<double>::quiet_NaN();
12267 default:
12268 return std::ldexp(mant + 1024, exp - 25);
12269 }
12270 }();
12271 return sax->number_float((half & 0x8000u) != 0
12272 ? static_cast<number_float_t>(-val)
12273 : static_cast<number_float_t>(val), "");
12274 }
12275
12276 case 'd':
12277 {
12278 float number{};
12279 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12280 }
12281
12282 case 'D':
12283 {
12284 double number{};
12285 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12286 }
12287
12288 case 'H':
12289 {
12290 return get_ubjson_high_precision_number();
12291 }
12292
12293 case 'C': // char
12294 {
12295 get();
12296 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
12297 {
12298 return false;
12299 }
12300 if (JSON_HEDLEY_UNLIKELY(current > 127))
12301 {
12302 auto last_token = get_token_string();
12303 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
12304 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
12305 }
12306 string_t s(1, static_cast<typename string_t::value_type>(current));
12307 return sax->string(s);
12308 }
12309
12310 case 'S': // string
12311 {
12312 string_t s;
12313 return get_ubjson_string(s) && sax->string(s);
12314 }
12315
12316 case '[': // array
12317 return get_ubjson_array();
12318
12319 case '{': // object
12320 return get_ubjson_object();
12321
12322 default: // anything else
12323 break;
12324 }
12325 auto last_token = get_token_string();
12326 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));
12327 }
12328
12329 /*!
12330 @return whether array creation completed
12331 */
12333 {
12334 std::pair<std::size_t, char_int_type> size_and_type;
12335 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12336 {
12337 return false;
12338 }
12339
12340 // 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):
12341 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
12342
12343 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12344 {
12345 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
12346 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)
12347 {
12348 return p.first < t;
12349 });
12350 string_t key = "_ArrayType_";
12351 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
12352 {
12353 auto last_token = get_token_string();
12354 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12355 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
12356 }
12357
12358 string_t type = it->second; // sax->string() takes a reference
12359 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
12360 {
12361 return false;
12362 }
12363
12364 if (size_and_type.second == 'C' || size_and_type.second == 'B')
12365 {
12366 size_and_type.second = 'U';
12367 }
12368
12369 key = "_ArrayData_";
12370 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
12371 {
12372 return false;
12373 }
12374
12375 for (std::size_t i = 0; i < size_and_type.first; ++i)
12376 {
12377 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12378 {
12379 return false;
12380 }
12381 }
12382
12383 return (sax->end_array() && sax->end_object());
12384 }
12385
12386 // If BJData type marker is 'B' decode as binary
12387 if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second == 'B')
12388 {
12389 binary_t result;
12390 return get_binary(input_format, size_and_type.first, result) && sax->binary(result);
12391 }
12392
12393 if (size_and_type.first != npos)
12394 {
12395 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
12396 {
12397 return false;
12398 }
12399
12400 if (size_and_type.second != 0)
12401 {
12402 if (size_and_type.second != 'N')
12403 {
12404 for (std::size_t i = 0; i < size_and_type.first; ++i)
12405 {
12406 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12407 {
12408 return false;
12409 }
12410 }
12411 }
12412 }
12413 else
12414 {
12415 for (std::size_t i = 0; i < size_and_type.first; ++i)
12416 {
12417 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12418 {
12419 return false;
12420 }
12421 }
12422 }
12423 }
12424 else
12425 {
12426 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
12427 {
12428 return false;
12429 }
12430
12431 while (current != ']')
12432 {
12433 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
12434 {
12435 return false;
12436 }
12437 get_ignore_noop();
12438 }
12439 }
12440
12441 return sax->end_array();
12442 }
12443
12444 /*!
12445 @return whether object creation completed
12446 */
12448 {
12449 std::pair<std::size_t, char_int_type> size_and_type;
12450 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12451 {
12452 return false;
12453 }
12454
12455 // do not accept ND-array size in objects in BJData
12456 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12457 {
12458 auto last_token = get_token_string();
12459 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12460 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
12461 }
12462
12463 string_t key;
12464 if (size_and_type.first != npos)
12465 {
12466 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
12467 {
12468 return false;
12469 }
12470
12471 if (size_and_type.second != 0)
12472 {
12473 for (std::size_t i = 0; i < size_and_type.first; ++i)
12474 {
12475 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12476 {
12477 return false;
12478 }
12479 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12480 {
12481 return false;
12482 }
12483 key.clear();
12484 }
12485 }
12486 else
12487 {
12488 for (std::size_t i = 0; i < size_and_type.first; ++i)
12489 {
12490 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12491 {
12492 return false;
12493 }
12494 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12495 {
12496 return false;
12497 }
12498 key.clear();
12499 }
12500 }
12501 }
12502 else
12503 {
12504 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
12505 {
12506 return false;
12507 }
12508
12509 while (current != '}')
12510 {
12511 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
12512 {
12513 return false;
12514 }
12515 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12516 {
12517 return false;
12518 }
12519 get_ignore_noop();
12520 key.clear();
12521 }
12522 }
12523
12524 return sax->end_object();
12525 }
12526
12527 // Note, no reader for UBJSON binary types is implemented because they do
12528 // not exist
12529
12531 {
12532 // get the size of the following number string
12533 std::size_t size{};
12534 bool no_ndarray = true;
12535 auto res = get_ubjson_size_value(size, no_ndarray);
12536 if (JSON_HEDLEY_UNLIKELY(!res))
12537 {
12538 return res;
12539 }
12540
12541 // get number string
12542 std::vector<char> number_vector;
12543 for (std::size_t i = 0; i < size; ++i)
12544 {
12545 get();
12546 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12547 {
12548 return false;
12549 }
12550 number_vector.push_back(static_cast<char>(current));
12551 }
12552
12553 // parse number string
12554 using ia_type = decltype(detail::input_adapter(number_vector));
12555 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
12556 const auto result_number = number_lexer.scan();
12557 const auto number_string = number_lexer.get_token_string();
12558 const auto result_remainder = number_lexer.scan();
12559
12560 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
12561
12562 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
12563 {
12564 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12565 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12566 }
12567
12568 switch (result_number)
12569 {
12570 case token_type::value_integer:
12571 return sax->number_integer(number_lexer.get_number_integer());
12572 case token_type::value_unsigned:
12573 return sax->number_unsigned(number_lexer.get_number_unsigned());
12574 case token_type::value_float:
12575 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
12576 case token_type::uninitialized:
12577 case token_type::literal_true:
12578 case token_type::literal_false:
12579 case token_type::literal_null:
12580 case token_type::value_string:
12581 case token_type::begin_array:
12582 case token_type::begin_object:
12583 case token_type::end_array:
12584 case token_type::end_object:
12585 case token_type::name_separator:
12586 case token_type::value_separator:
12587 case token_type::parse_error:
12588 case token_type::end_of_input:
12589 case token_type::literal_or_value:
12590 default:
12591 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12592 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12593 }
12594 }
12595
12596 ///////////////////////
12597 // Utility functions //
12598 ///////////////////////
12599
12600 /*!
12601 @brief get next character from the input
12602
12603 This function provides the interface to the used input adapter. It does
12604 not throw in case the input reached EOF, but returns a -'ve valued
12605 `char_traits<char_type>::eof()` in that case.
12606
12607 @return character read from the input
12608 */
12610 {
12611 ++chars_read;
12612 return current = ia.get_character();
12613 }
12614
12615 /*!
12616 @brief get_to read into a primitive type
12617
12618 This function provides the interface to the used input adapter. It does
12619 not throw in case the input reached EOF, but returns false instead
12620
12621 @return bool, whether the read was successful
12622 */
12623 template<class T>
12624 bool get_to(T& dest, const input_format_t format, const char* context)
12625 {
12626 auto new_chars_read = ia.get_elements(&dest);
12627 chars_read += new_chars_read;
12628 if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T)))
12629 {
12630 // in case of failure, advance position by 1 to report the failing location
12631 ++chars_read;
12632 sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12633 return false;
12634 }
12635 return true;
12636 }
12637
12638 /*!
12639 @return character read from the input after ignoring all 'N' entries
12640 */
12642 {
12643 do
12644 {
12645 get();
12646 }
12647 while (current == 'N');
12648
12649 return current;
12650 }
12651
12652 template<class NumberType>
12653 static void byte_swap(NumberType& number)
12654 {
12655 constexpr std::size_t sz = sizeof(number);
12656#ifdef __cpp_lib_byteswap
12657 if constexpr (sz == 1)
12658 {
12659 return;
12660 }
12661 else if constexpr(std::is_integral_v<NumberType>)
12662 {
12663 number = std::byteswap(number);
12664 return;
12665 }
12666 else
12667 {
12668#endif
12669 auto* ptr = reinterpret_cast<std::uint8_t*>(&number);
12670 for (std::size_t i = 0; i < sz / 2; ++i)
12671 {
12672 std::swap(ptr[i], ptr[sz - i - 1]);
12673 }
12674#ifdef __cpp_lib_byteswap
12675 }
12676#endif
12677 }
12678
12679 /*
12680 @brief read a number from the input
12681
12682 @tparam NumberType the type of the number
12683 @param[in] format the current format (for diagnostics)
12684 @param[out] result number of type @a NumberType
12685
12686 @return whether conversion completed
12687
12688 @note This function needs to respect the system's endianness, because
12689 bytes in CBOR, MessagePack, and UBJSON are stored in network order
12690 (big endian) and therefore need reordering on little endian systems.
12691 On the other hand, BSON and BJData use little endian and should reorder
12692 on big endian systems.
12693 */
12694 template<typename NumberType, bool InputIsLittleEndian = false>
12695 bool get_number(const input_format_t format, NumberType& result)
12696 {
12697 // read in the original format
12698
12699 if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number")))
12700 {
12701 return false;
12702 }
12703 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
12704 {
12705 byte_swap(result);
12706 }
12707 return true;
12708 }
12709
12710 /*!
12711 @brief create a string by reading characters from the input
12712
12713 @tparam NumberType the type of the number
12714 @param[in] format the current format (for diagnostics)
12715 @param[in] len number of characters to read
12716 @param[out] result string created by reading @a len bytes
12717
12718 @return whether string creation completed
12719
12720 @note We can not reserve @a len bytes for the result, because @a len
12721 may be too large. Usually, @ref unexpect_eof() detects the end of
12722 the input before we run out of string memory.
12723 */
12724 template<typename NumberType>
12725 bool get_string(const input_format_t format,
12726 const NumberType len,
12727 string_t& result)
12728 {
12729 bool success = true;
12730 for (NumberType i = 0; i < len; i++)
12731 {
12732 get();
12733 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
12734 {
12735 success = false;
12736 break;
12737 }
12738 result.push_back(static_cast<typename string_t::value_type>(current));
12739 }
12740 return success;
12741 }
12742
12743 /*!
12744 @brief create a byte array by reading bytes from the input
12745
12746 @tparam NumberType the type of the number
12747 @param[in] format the current format (for diagnostics)
12748 @param[in] len number of bytes to read
12749 @param[out] result byte array created by reading @a len bytes
12750
12751 @return whether byte array creation completed
12752
12753 @note We can not reserve @a len bytes for the result, because @a len
12754 may be too large. Usually, @ref unexpect_eof() detects the end of
12755 the input before we run out of memory.
12756 */
12757 template<typename NumberType>
12758 bool get_binary(const input_format_t format,
12759 const NumberType len,
12760 binary_t& result)
12761 {
12762 bool success = true;
12763 for (NumberType i = 0; i < len; i++)
12764 {
12765 get();
12766 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12767 {
12768 success = false;
12769 break;
12770 }
12771 result.push_back(static_cast<typename binary_t::value_type>(current));
12772 }
12773 return success;
12774 }
12775
12776 /*!
12777 @param[in] format the current format (for diagnostics)
12778 @param[in] context further context information (for diagnostics)
12779 @return whether the last read character is not EOF
12780 */
12782 bool unexpect_eof(const input_format_t format, const char* context) const
12783 {
12785 {
12786 return sax->parse_error(chars_read, "<end of file>",
12787 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12788 }
12789 return true;
12790 }
12791
12792 /*!
12793 @return a string representation of the last read byte
12794 */
12795 std::string get_token_string() const
12796 {
12797 std::array<char, 3> cr{{}};
12798 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12799 return std::string{cr.data()};
12800 }
12801
12802 /*!
12803 @param[in] format the current format
12804 @param[in] detail a detailed error message
12805 @param[in] context further context information
12806 @return a message string to use in the parse_error exceptions
12807 */
12808 std::string exception_message(const input_format_t format,
12809 const std::string& detail,
12810 const std::string& context) const
12811 {
12812 std::string error_msg = "syntax error while parsing ";
12813
12814 switch (format)
12815 {
12816 case input_format_t::cbor:
12817 error_msg += "CBOR";
12818 break;
12819
12820 case input_format_t::msgpack:
12821 error_msg += "MessagePack";
12822 break;
12823
12824 case input_format_t::ubjson:
12825 error_msg += "UBJSON";
12826 break;
12827
12828 case input_format_t::bson:
12829 error_msg += "BSON";
12830 break;
12831
12832 case input_format_t::bjdata:
12833 error_msg += "BJData";
12834 break;
12835
12836 case input_format_t::json: // LCOV_EXCL_LINE
12837 default: // LCOV_EXCL_LINE
12838 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12839 }
12840
12841 return concat(error_msg, ' ', context, ": ", detail);
12842 }
12843
12844 private:
12845 static JSON_INLINE_VARIABLE constexpr std::size_t npos = detail::unknown_size();
12846
12847 /// input adapter
12848 InputAdapterType ia;
12849
12850 /// the current character
12852
12853 /// the number of characters read
12854 std::size_t chars_read = 0;
12855
12856 /// whether we can assume little endianness
12857 const bool is_little_endian = little_endianness();
12858
12859 /// input format
12860 const input_format_t input_format = input_format_t::json;
12861
12862 /// the SAX parser
12863 json_sax_t* sax = nullptr;
12864
12865 // excluded markers in bjdata optimized type
12866#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12867 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12868
12869#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12870 make_array<bjd_type>( \
12871 bjd_type{'B', "byte"}, \
12872 bjd_type{'C', "char"}, \
12873 bjd_type{'D', "double"}, \
12874 bjd_type{'I', "int16"}, \
12875 bjd_type{'L', "int64"}, \
12876 bjd_type{'M', "uint64"}, \
12877 bjd_type{'U', "uint8"}, \
12878 bjd_type{'d', "single"}, \
12879 bjd_type{'i', "int8"}, \
12880 bjd_type{'l', "int32"}, \
12881 bjd_type{'m', "uint32"}, \
12882 bjd_type{'u', "uint16"})
12883
12885 // lookup tables
12886 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12887 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12889
12890 using bjd_type = std::pair<char_int_type, string_t>;
12891 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12892 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12894
12895#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12896#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12897};
12898
12899#ifndef JSON_HAS_CPP_17
12900 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12902#endif
12903
12904} // namespace detail
12906
12907// #include <nlohmann/detail/input/input_adapters.hpp>
12908
12909// #include <nlohmann/detail/input/lexer.hpp>
12910
12911// #include <nlohmann/detail/input/parser.hpp>
12912// __ _____ _____ _____
12913// __| | __| | | | JSON for Modern C++
12914// | | |__ | | | | | | version 3.12.0
12915// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12916//
12917// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
12918// SPDX-License-Identifier: MIT
12919
12920
12921
12922#include <cmath> // isfinite
12923#include <cstdint> // uint8_t
12924#include <functional> // function
12925#include <string> // string
12926#include <utility> // move
12927#include <vector> // vector
12928
12929// #include <nlohmann/detail/exceptions.hpp>
12930
12931// #include <nlohmann/detail/input/input_adapters.hpp>
12932
12933// #include <nlohmann/detail/input/json_sax.hpp>
12934
12935// #include <nlohmann/detail/input/lexer.hpp>
12936
12937// #include <nlohmann/detail/macro_scope.hpp>
12938
12939// #include <nlohmann/detail/meta/is_sax.hpp>
12940
12941// #include <nlohmann/detail/string_concat.hpp>
12942
12943// #include <nlohmann/detail/value_t.hpp>
12944
12945
12947namespace detail
12948{
12949////////////
12950// parser //
12951////////////
12952
12953enum class parse_event_t : std::uint8_t
12954{
12955 /// the parser read `{` and started to process a JSON object
12957 /// the parser read `}` and finished processing a JSON object
12958 object_end,
12959 /// the parser read `[` and started to process a JSON array
12961 /// the parser read `]` and finished processing a JSON array
12962 array_end,
12963 /// the parser read a key of a value in an object
12964 key,
12965 /// the parser finished reading a JSON value
12966 value
12967};
12968
12969template<typename BasicJsonType>
12971 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12972
12973/*!
12974@brief syntax analysis
12975
12976This class implements a recursive descent parser.
12977*/
12978template<typename BasicJsonType, typename InputAdapterType>
12980{
12981 using number_integer_t = typename BasicJsonType::number_integer_t;
12982 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12983 using number_float_t = typename BasicJsonType::number_float_t;
12984 using string_t = typename BasicJsonType::string_t;
12987
12988 public:
12989 /// a parser reading from an input adapter
12990 explicit parser(InputAdapterType&& adapter,
12992 const bool allow_exceptions_ = true,
12993 const bool ignore_comments = false,
12994 const bool ignore_trailing_commas_ = false)
12995 : callback(std::move(cb))
12996 , m_lexer(std::move(adapter), ignore_comments)
12997 , allow_exceptions(allow_exceptions_)
12998 , ignore_trailing_commas(ignore_trailing_commas_)
12999 {
13000 // read first token
13001 get_token();
13002 }
13003
13004 /*!
13005 @brief public parser interface
13006
13007 @param[in] strict whether to expect the last token to be EOF
13008 @param[in,out] result parsed JSON value
13009
13010 @throw parse_error.101 in case of an unexpected token
13011 @throw parse_error.102 if to_unicode fails or surrogate error
13012 @throw parse_error.103 if to_unicode fails
13013 */
13014 void parse(const bool strict, BasicJsonType& result)
13015 {
13016 if (callback)
13017 {
13018 json_sax_dom_callback_parser<BasicJsonType, InputAdapterType> sdp(result, callback, allow_exceptions, &m_lexer);
13019 sax_parse_internal(&sdp);
13020
13021 // in strict mode, input must be completely read
13022 if (strict && (get_token() != token_type::end_of_input))
13023 {
13024 sdp.parse_error(m_lexer.get_position(),
13025 m_lexer.get_token_string(),
13026 parse_error::create(101, m_lexer.get_position(),
13027 exception_message(token_type::end_of_input, "value"), nullptr));
13028 }
13029
13030 // in case of an error, return a discarded value
13031 if (sdp.is_errored())
13032 {
13033 result = value_t::discarded;
13034 return;
13035 }
13036
13037 // set top-level value to null if it was discarded by the callback
13038 // function
13039 if (result.is_discarded())
13040 {
13041 result = nullptr;
13042 }
13043 }
13044 else
13045 {
13046 json_sax_dom_parser<BasicJsonType, InputAdapterType> sdp(result, allow_exceptions, &m_lexer);
13047 sax_parse_internal(&sdp);
13048
13049 // in strict mode, input must be completely read
13050 if (strict && (get_token() != token_type::end_of_input))
13051 {
13052 sdp.parse_error(m_lexer.get_position(),
13053 m_lexer.get_token_string(),
13054 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13055 }
13056
13057 // in case of an error, return a discarded value
13058 if (sdp.is_errored())
13059 {
13060 result = value_t::discarded;
13061 return;
13062 }
13063 }
13064
13065 result.assert_invariant();
13066 }
13067
13068 /*!
13069 @brief public accept interface
13070
13071 @param[in] strict whether to expect the last token to be EOF
13072 @return whether the input is a proper JSON text
13073 */
13074 bool accept(const bool strict = true)
13075 {
13077 return sax_parse(&sax_acceptor, strict);
13078 }
13079
13080 template<typename SAX>
13082 bool sax_parse(SAX* sax, const bool strict = true)
13083 {
13085 const bool result = sax_parse_internal(sax);
13086
13087 // strict mode: next byte must be EOF
13088 if (result && strict && (get_token() != token_type::end_of_input))
13089 {
13090 return sax->parse_error(m_lexer.get_position(),
13091 m_lexer.get_token_string(),
13092 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13093 }
13094
13095 return result;
13096 }
13097
13098 private:
13099 template<typename SAX>
13101 bool sax_parse_internal(SAX* sax)
13102 {
13103 // stack to remember the hierarchy of structured values we are parsing
13104 // true = array; false = object
13105 std::vector<bool> states;
13106 // value to avoid a goto (see comment where set to true)
13107 bool skip_to_state_evaluation = false;
13108
13109 while (true)
13110 {
13111 if (!skip_to_state_evaluation)
13112 {
13113 // invariant: get_token() was called before each iteration
13114 switch (last_token)
13115 {
13116 case token_type::begin_object:
13117 {
13118 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
13119 {
13120 return false;
13121 }
13122
13123 // closing } -> we are done
13124 if (get_token() == token_type::end_object)
13125 {
13126 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13127 {
13128 return false;
13129 }
13130 break;
13131 }
13132
13133 // parse key
13134 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13135 {
13136 return sax->parse_error(m_lexer.get_position(),
13137 m_lexer.get_token_string(),
13138 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13139 }
13140 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13141 {
13142 return false;
13143 }
13144
13145 // parse separator (:)
13146 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13147 {
13148 return sax->parse_error(m_lexer.get_position(),
13149 m_lexer.get_token_string(),
13150 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13151 }
13152
13153 // remember we are now inside an object
13154 states.push_back(false);
13155
13156 // parse values
13157 get_token();
13158 continue;
13159 }
13160
13161 case token_type::begin_array:
13162 {
13163 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
13164 {
13165 return false;
13166 }
13167
13168 // closing ] -> we are done
13169 if (get_token() == token_type::end_array)
13170 {
13171 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13172 {
13173 return false;
13174 }
13175 break;
13176 }
13177
13178 // remember we are now inside an array
13179 states.push_back(true);
13180
13181 // parse values (no need to call get_token)
13182 continue;
13183 }
13184
13185 case token_type::value_float:
13186 {
13187 const auto res = m_lexer.get_number_float();
13188
13189 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
13190 {
13191 return sax->parse_error(m_lexer.get_position(),
13192 m_lexer.get_token_string(),
13193 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
13194 }
13195
13196 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
13197 {
13198 return false;
13199 }
13200
13201 break;
13202 }
13203
13204 case token_type::literal_false:
13205 {
13206 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
13207 {
13208 return false;
13209 }
13210 break;
13211 }
13212
13213 case token_type::literal_null:
13214 {
13215 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
13216 {
13217 return false;
13218 }
13219 break;
13220 }
13221
13222 case token_type::literal_true:
13223 {
13224 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
13225 {
13226 return false;
13227 }
13228 break;
13229 }
13230
13231 case token_type::value_integer:
13232 {
13233 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
13234 {
13235 return false;
13236 }
13237 break;
13238 }
13239
13240 case token_type::value_string:
13241 {
13242 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
13243 {
13244 return false;
13245 }
13246 break;
13247 }
13248
13249 case token_type::value_unsigned:
13250 {
13251 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
13252 {
13253 return false;
13254 }
13255 break;
13256 }
13257
13258 case token_type::parse_error:
13259 {
13260 // using "uninitialized" to avoid an "expected" message
13261 return sax->parse_error(m_lexer.get_position(),
13262 m_lexer.get_token_string(),
13263 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
13264 }
13265 case token_type::end_of_input:
13266 {
13267 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
13268 {
13269 return sax->parse_error(m_lexer.get_position(),
13270 m_lexer.get_token_string(),
13271 parse_error::create(101, m_lexer.get_position(),
13272 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
13273 }
13274
13275 return sax->parse_error(m_lexer.get_position(),
13276 m_lexer.get_token_string(),
13277 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13278 }
13279 case token_type::uninitialized:
13280 case token_type::end_array:
13281 case token_type::end_object:
13282 case token_type::name_separator:
13283 case token_type::value_separator:
13284 case token_type::literal_or_value:
13285 default: // the last token was unexpected
13286 {
13287 return sax->parse_error(m_lexer.get_position(),
13288 m_lexer.get_token_string(),
13289 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13290 }
13291 }
13292 }
13293 else
13294 {
13295 skip_to_state_evaluation = false;
13296 }
13297
13298 // we reached this line after we successfully parsed a value
13299 if (states.empty())
13300 {
13301 // empty stack: we reached the end of the hierarchy: done
13302 return true;
13303 }
13304
13305 if (states.back()) // array
13306 {
13307 // comma -> next value
13308 // or end of array (ignore_trailing_commas = true)
13309 if (get_token() == token_type::value_separator)
13310 {
13311 // parse a new value
13312 get_token();
13313
13314 // if ignore_trailing_commas and last_token is ], we can continue to "closing ]"
13315 if (!(ignore_trailing_commas && last_token == token_type::end_array))
13316 {
13317 continue;
13318 }
13319 }
13320
13321 // closing ]
13322 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
13323 {
13324 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13325 {
13326 return false;
13327 }
13328
13329 // We are done with this array. Before we can parse a
13330 // new value, we need to evaluate the new state first.
13331 // By setting skip_to_state_evaluation to false, we
13332 // are effectively jumping to the beginning of this if.
13333 JSON_ASSERT(!states.empty());
13334 states.pop_back();
13335 skip_to_state_evaluation = true;
13336 continue;
13337 }
13338
13339 return sax->parse_error(m_lexer.get_position(),
13340 m_lexer.get_token_string(),
13341 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
13342 }
13343
13344 // states.back() is false -> object
13345
13346 // comma -> next value
13347 // or end of object (ignore_trailing_commas = true)
13348 if (get_token() == token_type::value_separator)
13349 {
13350 get_token();
13351
13352 // if ignore_trailing_commas and last_token is }, we can continue to "closing }"
13353 if (!(ignore_trailing_commas && last_token == token_type::end_object))
13354 {
13355 // parse key
13356 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13357 {
13358 return sax->parse_error(m_lexer.get_position(),
13359 m_lexer.get_token_string(),
13360 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13361 }
13362
13363 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13364 {
13365 return false;
13366 }
13367
13368 // parse separator (:)
13369 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13370 {
13371 return sax->parse_error(m_lexer.get_position(),
13372 m_lexer.get_token_string(),
13373 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13374 }
13375
13376 // parse values
13377 get_token();
13378 continue;
13379 }
13380 }
13381
13382 // closing }
13383 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
13384 {
13385 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13386 {
13387 return false;
13388 }
13389
13390 // We are done with this object. Before we can parse a
13391 // new value, we need to evaluate the new state first.
13392 // By setting skip_to_state_evaluation to false, we
13393 // are effectively jumping to the beginning of this if.
13394 JSON_ASSERT(!states.empty());
13395 states.pop_back();
13396 skip_to_state_evaluation = true;
13397 continue;
13398 }
13399
13400 return sax->parse_error(m_lexer.get_position(),
13401 m_lexer.get_token_string(),
13402 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
13403 }
13404 }
13405
13406 /// get next token from lexer
13408 {
13409 return last_token = m_lexer.scan();
13410 }
13411
13412 std::string exception_message(const token_type expected, const std::string& context)
13413 {
13414 std::string error_msg = "syntax error ";
13415
13416 if (!context.empty())
13417 {
13418 error_msg += concat("while parsing ", context, ' ');
13419 }
13420
13421 error_msg += "- ";
13422
13423 if (last_token == token_type::parse_error)
13424 {
13425 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
13426 m_lexer.get_token_string(), '\'');
13427 }
13428 else
13429 {
13430 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
13431 }
13432
13433 if (expected != token_type::uninitialized)
13434 {
13435 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
13436 }
13437
13438 return error_msg;
13439 }
13440
13441 private:
13442 /// callback function
13443 const parser_callback_t<BasicJsonType> callback = nullptr;
13444 /// the type of the last read token
13445 token_type last_token = token_type::uninitialized;
13446 /// the lexer
13448 /// whether to throw exceptions in case of errors
13449 const bool allow_exceptions = true;
13450 /// whether trailing commas in objects and arrays should be ignored (true) or signaled as errors (false)
13451 const bool ignore_trailing_commas = false;
13452};
13453
13454} // namespace detail
13456
13457// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13458// __ _____ _____ _____
13459// __| | __| | | | JSON for Modern C++
13460// | | |__ | | | | | | version 3.12.0
13461// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13462//
13463// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13464// SPDX-License-Identifier: MIT
13465
13466
13467
13468// #include <nlohmann/detail/abi_macros.hpp>
13469
13470// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13471// __ _____ _____ _____
13472// __| | __| | | | JSON for Modern C++
13473// | | |__ | | | | | | version 3.12.0
13474// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13475//
13476// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13477// SPDX-License-Identifier: MIT
13478
13479
13480
13481#include <cstddef> // ptrdiff_t
13482#include <limits> // numeric_limits
13483
13484// #include <nlohmann/detail/macro_scope.hpp>
13485
13486
13488namespace detail
13489{
13490
13491/*
13492@brief an iterator for primitive JSON types
13493
13494This class models an iterator for primitive JSON types (boolean, number,
13495string). Its only purpose is to allow the iterator/const_iterator classes
13496to "iterate" over primitive values. Internally, the iterator is modeled by
13497a `difference_type` variable. Value begin_value (`0`) models the begin and
13498end_value (`1`) models past the end.
13499*/
13501{
13502 private:
13503 using difference_type = std::ptrdiff_t;
13504 static constexpr difference_type begin_value = 0;
13505 static constexpr difference_type end_value = begin_value + 1;
13506
13508 /// iterator as signed integer type
13509 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
13510
13511 public:
13512 constexpr difference_type get_value() const noexcept
13513 {
13514 return m_it;
13515 }
13516
13517 /// set iterator to a defined beginning
13518 void set_begin() noexcept
13519 {
13520 m_it = begin_value;
13521 }
13522
13523 /// set iterator to a defined past the end
13524 void set_end() noexcept
13525 {
13526 m_it = end_value;
13527 }
13528
13529 /// return whether the iterator can be dereferenced
13530 constexpr bool is_begin() const noexcept
13531 {
13532 return m_it == begin_value;
13533 }
13534
13535 /// return whether the iterator is at end
13536 constexpr bool is_end() const noexcept
13537 {
13538 return m_it == end_value;
13539 }
13540
13541 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13542 {
13543 return lhs.m_it == rhs.m_it;
13544 }
13545
13546 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13547 {
13548 return lhs.m_it < rhs.m_it;
13549 }
13550
13552 {
13553 auto result = *this;
13554 result += n;
13555 return result;
13556 }
13557
13559 {
13560 return lhs.m_it - rhs.m_it;
13561 }
13562
13564 {
13565 ++m_it;
13566 return *this;
13567 }
13568
13569 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
13570 {
13571 auto result = *this;
13572 ++m_it;
13573 return result;
13574 }
13575
13577 {
13578 --m_it;
13579 return *this;
13580 }
13581
13582 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
13583 {
13584 auto result = *this;
13585 --m_it;
13586 return result;
13587 }
13588
13590 {
13591 m_it += n;
13592 return *this;
13593 }
13594
13596 {
13597 m_it -= n;
13598 return *this;
13599 }
13600};
13601
13602} // namespace detail
13604
13605
13607namespace detail
13608{
13609
13610/*!
13611@brief an iterator value
13612
13613@note This structure could easily be a union, but MSVC currently does not allow
13614unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
13615*/
13616template<typename BasicJsonType> struct internal_iterator
13617{
13618 /// iterator for JSON objects
13619 typename BasicJsonType::object_t::iterator object_iterator {};
13620 /// iterator for JSON arrays
13621 typename BasicJsonType::array_t::iterator array_iterator {};
13622 /// generic iterator for all other types
13623 primitive_iterator_t primitive_iterator {};
13624};
13625
13626} // namespace detail
13628
13629// #include <nlohmann/detail/iterators/iter_impl.hpp>
13630// __ _____ _____ _____
13631// __| | __| | | | JSON for Modern C++
13632// | | |__ | | | | | | version 3.12.0
13633// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13634//
13635// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13636// SPDX-License-Identifier: MIT
13637
13638
13639
13640#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
13641#include <type_traits> // conditional, is_const, remove_const
13642
13643// #include <nlohmann/detail/exceptions.hpp>
13644
13645// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13646
13647// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13648
13649// #include <nlohmann/detail/macro_scope.hpp>
13650
13651// #include <nlohmann/detail/meta/cpp_future.hpp>
13652
13653// #include <nlohmann/detail/meta/type_traits.hpp>
13654
13655// #include <nlohmann/detail/value_t.hpp>
13656
13657
13659namespace detail
13660{
13661
13662// forward declare to be able to friend it later on
13663template<typename IteratorType> class iteration_proxy;
13664template<typename IteratorType> class iteration_proxy_value;
13665
13666/*!
13667@brief a template for a bidirectional iterator for the @ref basic_json class
13668This class implements a both iterators (iterator and const_iterator) for the
13669@ref basic_json class.
13670@note An iterator is called *initialized* when a pointer to a JSON value has
13671 been set (e.g., by a constructor or a copy assignment). If the iterator is
13672 default-constructed, it is *uninitialized* and most methods are undefined.
13673 **The library uses assertions to detect calls on uninitialized iterators.**
13674@requirement The class satisfies the following concept requirements:
13675-
13676[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
13677 The iterator that can be moved can be moved in both directions (i.e.
13678 incremented and decremented).
13679@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
13680 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
13681*/
13682template<typename BasicJsonType>
13683class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
13684{
13685 /// the iterator with BasicJsonType of different const-ness
13686 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
13687 /// allow basic_json to access private members
13692
13693 using object_t = typename BasicJsonType::object_t;
13694 using array_t = typename BasicJsonType::array_t;
13695 // make sure BasicJsonType is basic_json or const basic_json
13697 "iter_impl only accepts (const) basic_json");
13698 // superficial check for the LegacyBidirectionalIterator named requirement
13699 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
13700 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
13701 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
13702
13703 public:
13704 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
13705 /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
13706 /// A user-defined iterator should provide publicly accessible typedefs named
13707 /// iterator_category, value_type, difference_type, pointer, and reference.
13708 /// Note that value_type is required to be non-const, even for constant iterators.
13709 using iterator_category = std::bidirectional_iterator_tag;
13710
13711 /// the type of the values when the iterator is dereferenced
13712 using value_type = typename BasicJsonType::value_type;
13713 /// a type to represent differences between iterators
13714 using difference_type = typename BasicJsonType::difference_type;
13715 /// defines a pointer to the type iterated over (value_type)
13716 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
13717 typename BasicJsonType::const_pointer,
13718 typename BasicJsonType::pointer>::type;
13719 /// defines a reference to the type iterated over (value_type)
13721 typename std::conditional<std::is_const<BasicJsonType>::value,
13722 typename BasicJsonType::const_reference,
13723 typename BasicJsonType::reference>::type;
13724
13725 iter_impl() = default;
13726 ~iter_impl() = default;
13727 iter_impl(iter_impl&&) noexcept = default;
13728 iter_impl& operator=(iter_impl&&) noexcept = default;
13729
13730 /*!
13731 @brief constructor for a given JSON instance
13732 @param[in] object pointer to a JSON object for this iterator
13733 @pre object != nullptr
13734 @post The iterator is initialized; i.e. `m_object != nullptr`.
13735 */
13736 explicit iter_impl(pointer object) noexcept : m_object(object)
13737 {
13738 JSON_ASSERT(m_object != nullptr);
13739
13740 switch (m_object->m_data.m_type)
13741 {
13742 case value_t::object:
13743 {
13744 m_it.object_iterator = typename object_t::iterator();
13745 break;
13746 }
13747
13748 case value_t::array:
13749 {
13750 m_it.array_iterator = typename array_t::iterator();
13751 break;
13752 }
13753
13754 case value_t::null:
13755 case value_t::string:
13756 case value_t::boolean:
13757 case value_t::number_integer:
13758 case value_t::number_unsigned:
13759 case value_t::number_float:
13760 case value_t::binary:
13761 case value_t::discarded:
13762 default:
13763 {
13764 m_it.primitive_iterator = primitive_iterator_t();
13765 break;
13766 }
13767 }
13768 }
13769
13770 /*!
13771 @note The conventional copy constructor and copy assignment are implicitly
13772 defined. Combined with the following converting constructor and
13773 assignment, they support: (1) copy from iterator to iterator, (2)
13774 copy from const iterator to const iterator, and (3) conversion from
13775 iterator to const iterator. However conversion from const iterator
13776 to iterator is not defined.
13777 */
13778
13779 /*!
13780 @brief const copy constructor
13781 @param[in] other const iterator to copy from
13782 @note This copy constructor had to be defined explicitly to circumvent a bug
13783 occurring on msvc v19.0 compiler (VS 2015) debug build. For more
13784 information refer to: https://github.com/nlohmann/json/issues/1608
13785 */
13787 : m_object(other.m_object), m_it(other.m_it)
13788 {}
13789
13790 /*!
13791 @brief converting assignment
13792 @param[in] other const iterator to copy from
13793 @return const/non-const iterator
13794 @note It is not checked whether @a other is initialized.
13795 */
13797 {
13798 if (&other != this)
13799 {
13800 m_object = other.m_object;
13801 m_it = other.m_it;
13802 }
13803 return *this;
13804 }
13805
13806 /*!
13807 @brief converting constructor
13808 @param[in] other non-const iterator to copy from
13809 @note It is not checked whether @a other is initialized.
13810 */
13811 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13812 : m_object(other.m_object), m_it(other.m_it)
13813 {}
13814
13815 /*!
13816 @brief converting assignment
13817 @param[in] other non-const iterator to copy from
13818 @return const/non-const iterator
13819 @note It is not checked whether @a other is initialized.
13820 */
13821 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13822 {
13823 m_object = other.m_object;
13824 m_it = other.m_it;
13825 return *this;
13826 }
13827
13829 /*!
13830 @brief set the iterator to the first value
13831 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13832 */
13833 void set_begin() noexcept
13834 {
13835 JSON_ASSERT(m_object != nullptr);
13836
13837 switch (m_object->m_data.m_type)
13838 {
13839 case value_t::object:
13840 {
13841 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13842 break;
13843 }
13844
13845 case value_t::array:
13846 {
13847 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13848 break;
13849 }
13850
13851 case value_t::null:
13852 {
13853 // set to end so begin()==end() is true: null is empty
13854 m_it.primitive_iterator.set_end();
13855 break;
13856 }
13857
13858 case value_t::string:
13859 case value_t::boolean:
13860 case value_t::number_integer:
13861 case value_t::number_unsigned:
13862 case value_t::number_float:
13863 case value_t::binary:
13864 case value_t::discarded:
13865 default:
13866 {
13867 m_it.primitive_iterator.set_begin();
13868 break;
13869 }
13870 }
13871 }
13872
13873 /*!
13874 @brief set the iterator past the last value
13875 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13876 */
13877 void set_end() noexcept
13878 {
13879 JSON_ASSERT(m_object != nullptr);
13880
13881 switch (m_object->m_data.m_type)
13882 {
13883 case value_t::object:
13884 {
13885 m_it.object_iterator = m_object->m_data.m_value.object->end();
13886 break;
13887 }
13888
13889 case value_t::array:
13890 {
13891 m_it.array_iterator = m_object->m_data.m_value.array->end();
13892 break;
13893 }
13894
13895 case value_t::null:
13896 case value_t::string:
13897 case value_t::boolean:
13898 case value_t::number_integer:
13899 case value_t::number_unsigned:
13900 case value_t::number_float:
13901 case value_t::binary:
13902 case value_t::discarded:
13903 default:
13904 {
13905 m_it.primitive_iterator.set_end();
13906 break;
13907 }
13908 }
13909 }
13910
13911 public:
13912 /*!
13913 @brief return a reference to the value pointed to by the iterator
13914 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13915 */
13917 {
13918 JSON_ASSERT(m_object != nullptr);
13919
13920 switch (m_object->m_data.m_type)
13921 {
13922 case value_t::object:
13923 {
13924 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13925 return m_it.object_iterator->second;
13926 }
13927
13928 case value_t::array:
13929 {
13930 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13931 return *m_it.array_iterator;
13932 }
13933
13934 case value_t::null:
13935 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13936
13937 case value_t::string:
13938 case value_t::boolean:
13939 case value_t::number_integer:
13940 case value_t::number_unsigned:
13941 case value_t::number_float:
13942 case value_t::binary:
13943 case value_t::discarded:
13944 default:
13945 {
13946 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13947 {
13948 return *m_object;
13949 }
13950
13951 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13952 }
13953 }
13954 }
13955
13956 /*!
13957 @brief dereference the iterator
13958 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13959 */
13961 {
13962 JSON_ASSERT(m_object != nullptr);
13963
13964 switch (m_object->m_data.m_type)
13965 {
13966 case value_t::object:
13967 {
13968 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13969 return &(m_it.object_iterator->second);
13970 }
13971
13972 case value_t::array:
13973 {
13974 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13975 return &*m_it.array_iterator;
13976 }
13977
13978 case value_t::null:
13979 case value_t::string:
13980 case value_t::boolean:
13981 case value_t::number_integer:
13982 case value_t::number_unsigned:
13983 case value_t::number_float:
13984 case value_t::binary:
13985 case value_t::discarded:
13986 default:
13987 {
13988 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13989 {
13990 return m_object;
13991 }
13992
13993 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13994 }
13995 }
13996 }
13997
13998 /*!
13999 @brief post-increment (it++)
14000 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14001 */
14002 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
14003 {
14004 auto result = *this;
14005 ++(*this);
14006 return result;
14007 }
14008
14009 /*!
14010 @brief pre-increment (++it)
14011 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14012 */
14014 {
14015 JSON_ASSERT(m_object != nullptr);
14016
14017 switch (m_object->m_data.m_type)
14018 {
14019 case value_t::object:
14020 {
14021 std::advance(m_it.object_iterator, 1);
14022 break;
14023 }
14024
14025 case value_t::array:
14026 {
14027 std::advance(m_it.array_iterator, 1);
14028 break;
14029 }
14030
14031 case value_t::null:
14032 case value_t::string:
14033 case value_t::boolean:
14034 case value_t::number_integer:
14035 case value_t::number_unsigned:
14036 case value_t::number_float:
14037 case value_t::binary:
14038 case value_t::discarded:
14039 default:
14040 {
14041 ++m_it.primitive_iterator;
14042 break;
14043 }
14044 }
14045
14046 return *this;
14047 }
14048
14049 /*!
14050 @brief post-decrement (it--)
14051 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14052 */
14053 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
14054 {
14055 auto result = *this;
14056 --(*this);
14057 return result;
14058 }
14059
14060 /*!
14061 @brief pre-decrement (--it)
14062 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14063 */
14065 {
14066 JSON_ASSERT(m_object != nullptr);
14067
14068 switch (m_object->m_data.m_type)
14069 {
14070 case value_t::object:
14071 {
14072 std::advance(m_it.object_iterator, -1);
14073 break;
14074 }
14075
14076 case value_t::array:
14077 {
14078 std::advance(m_it.array_iterator, -1);
14079 break;
14080 }
14081
14082 case value_t::null:
14083 case value_t::string:
14084 case value_t::boolean:
14085 case value_t::number_integer:
14086 case value_t::number_unsigned:
14087 case value_t::number_float:
14088 case value_t::binary:
14089 case value_t::discarded:
14090 default:
14091 {
14092 --m_it.primitive_iterator;
14093 break;
14094 }
14095 }
14096
14097 return *this;
14098 }
14099
14100 /*!
14101 @brief comparison: equal
14102 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14103 */
14104 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 >
14105 bool operator==(const IterImpl& other) const
14106 {
14107 // if objects are not the same, the comparison is undefined
14108 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14109 {
14110 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14111 }
14112
14113 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14114 if (m_object == nullptr)
14115 {
14116 return true;
14117 }
14118
14119 switch (m_object->m_data.m_type)
14120 {
14121 case value_t::object:
14122 return (m_it.object_iterator == other.m_it.object_iterator);
14123
14124 case value_t::array:
14125 return (m_it.array_iterator == other.m_it.array_iterator);
14126
14127 case value_t::null:
14128 case value_t::string:
14129 case value_t::boolean:
14130 case value_t::number_integer:
14131 case value_t::number_unsigned:
14132 case value_t::number_float:
14133 case value_t::binary:
14134 case value_t::discarded:
14135 default:
14136 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
14137 }
14138 }
14139
14140 /*!
14141 @brief comparison: not equal
14142 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14143 */
14144 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 >
14145 bool operator!=(const IterImpl& other) const
14146 {
14147 return !operator==(other);
14148 }
14149
14150 /*!
14151 @brief comparison: smaller
14152 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14153 */
14154 bool operator<(const iter_impl& other) const
14155 {
14156 // if objects are not the same, the comparison is undefined
14157 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14158 {
14159 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14160 }
14161
14162 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14163 if (m_object == nullptr)
14164 {
14165 // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false
14166 return false;
14167 }
14168
14169 switch (m_object->m_data.m_type)
14170 {
14171 case value_t::object:
14172 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
14173
14174 case value_t::array:
14175 return (m_it.array_iterator < other.m_it.array_iterator);
14176
14177 case value_t::null:
14178 case value_t::string:
14179 case value_t::boolean:
14180 case value_t::number_integer:
14181 case value_t::number_unsigned:
14182 case value_t::number_float:
14183 case value_t::binary:
14184 case value_t::discarded:
14185 default:
14186 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
14187 }
14188 }
14189
14190 /*!
14191 @brief comparison: less than or equal
14192 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14193 */
14194 bool operator<=(const iter_impl& other) const
14195 {
14196 return !other.operator < (*this);
14197 }
14198
14199 /*!
14200 @brief comparison: greater than
14201 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14202 */
14203 bool operator>(const iter_impl& other) const
14204 {
14205 return !operator<=(other);
14206 }
14207
14208 /*!
14209 @brief comparison: greater than or equal
14210 @pre (1) The iterator is initialized; i.e. `m_object != nullptr`, or (2) both iterators are value-initialized.
14211 */
14212 bool operator>=(const iter_impl& other) const
14213 {
14214 return !operator<(other);
14215 }
14216
14217 /*!
14218 @brief add to iterator
14219 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14220 */
14222 {
14223 JSON_ASSERT(m_object != nullptr);
14224
14225 switch (m_object->m_data.m_type)
14226 {
14227 case value_t::object:
14228 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14229
14230 case value_t::array:
14231 {
14232 std::advance(m_it.array_iterator, i);
14233 break;
14234 }
14235
14236 case value_t::null:
14237 case value_t::string:
14238 case value_t::boolean:
14239 case value_t::number_integer:
14240 case value_t::number_unsigned:
14241 case value_t::number_float:
14242 case value_t::binary:
14243 case value_t::discarded:
14244 default:
14245 {
14246 m_it.primitive_iterator += i;
14247 break;
14248 }
14249 }
14250
14251 return *this;
14252 }
14253
14254 /*!
14255 @brief subtract from iterator
14256 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14257 */
14259 {
14260 return operator+=(-i);
14261 }
14262
14263 /*!
14264 @brief add to iterator
14265 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14266 */
14268 {
14269 auto result = *this;
14270 result += i;
14271 return result;
14272 }
14273
14274 /*!
14275 @brief addition of distance and iterator
14276 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14277 */
14279 {
14280 auto result = it;
14281 result += i;
14282 return result;
14283 }
14284
14285 /*!
14286 @brief subtract from iterator
14287 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14288 */
14290 {
14291 auto result = *this;
14292 result -= i;
14293 return result;
14294 }
14295
14296 /*!
14297 @brief return difference
14298 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14299 */
14301 {
14302 JSON_ASSERT(m_object != nullptr);
14303
14304 switch (m_object->m_data.m_type)
14305 {
14306 case value_t::object:
14307 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14308
14309 case value_t::array:
14310 return m_it.array_iterator - other.m_it.array_iterator;
14311
14312 case value_t::null:
14313 case value_t::string:
14314 case value_t::boolean:
14315 case value_t::number_integer:
14316 case value_t::number_unsigned:
14317 case value_t::number_float:
14318 case value_t::binary:
14319 case value_t::discarded:
14320 default:
14321 return m_it.primitive_iterator - other.m_it.primitive_iterator;
14322 }
14323 }
14324
14325 /*!
14326 @brief access to successor
14327 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14328 */
14330 {
14331 JSON_ASSERT(m_object != nullptr);
14332
14333 switch (m_object->m_data.m_type)
14334 {
14335 case value_t::object:
14336 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
14337
14338 case value_t::array:
14339 return *std::next(m_it.array_iterator, n);
14340
14341 case value_t::null:
14342 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14343
14344 case value_t::string:
14345 case value_t::boolean:
14346 case value_t::number_integer:
14347 case value_t::number_unsigned:
14348 case value_t::number_float:
14349 case value_t::binary:
14350 case value_t::discarded:
14351 default:
14352 {
14353 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
14354 {
14355 return *m_object;
14356 }
14357
14358 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14359 }
14360 }
14361 }
14362
14363 /*!
14364 @brief return the key of an object iterator
14365 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14366 */
14367 const typename object_t::key_type& key() const
14368 {
14369 JSON_ASSERT(m_object != nullptr);
14370
14371 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
14372 {
14373 return m_it.object_iterator->first;
14374 }
14375
14376 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
14377 }
14378
14379 /*!
14380 @brief return the value of an iterator
14381 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14382 */
14384 {
14385 return operator*();
14386 }
14387
14389 /// associated JSON instance
14390 pointer m_object = nullptr;
14391 /// the actual iterator of the associated instance
14393};
14394
14395} // namespace detail
14397
14398// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
14399
14400// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
14401// __ _____ _____ _____
14402// __| | __| | | | JSON for Modern C++
14403// | | |__ | | | | | | version 3.12.0
14404// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14405//
14406// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14407// SPDX-License-Identifier: MIT
14408
14409
14410
14411#include <cstddef> // ptrdiff_t
14412#include <iterator> // reverse_iterator
14413#include <utility> // declval
14414
14415// #include <nlohmann/detail/abi_macros.hpp>
14416
14417
14419namespace detail
14420{
14421
14422//////////////////////
14423// reverse_iterator //
14424//////////////////////
14425
14426/*!
14427@brief a template for a reverse iterator class
14428
14429@tparam Base the base iterator type to reverse. Valid types are @ref
14430iterator (to create @ref reverse_iterator) and @ref const_iterator (to
14431create @ref const_reverse_iterator).
14432
14433@requirement The class satisfies the following concept requirements:
14434-
14435[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
14436 The iterator that can be moved can be moved in both directions (i.e.
14437 incremented and decremented).
14438- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
14439 It is possible to write to the pointed-to element (only if @a Base is
14440 @ref iterator).
14441
14442@since version 1.0.0
14443*/
14444template<typename Base>
14445class json_reverse_iterator : public std::reverse_iterator<Base>
14446{
14447 public:
14448 using difference_type = std::ptrdiff_t;
14449 /// shortcut to the reverse iterator adapter
14450 using base_iterator = std::reverse_iterator<Base>;
14451 /// the reference type for the pointed-to element
14452 using reference = typename Base::reference;
14453
14454 /// create reverse iterator from iterator
14455 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
14456 : base_iterator(it) {}
14457
14458 /// create reverse iterator from base class
14459 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
14460
14461 /// post-increment (it++)
14462 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
14463 {
14464 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
14465 }
14466
14467 /// pre-increment (++it)
14469 {
14470 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
14471 }
14472
14473 /// post-decrement (it--)
14474 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
14475 {
14476 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
14477 }
14478
14479 /// pre-decrement (--it)
14481 {
14482 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
14483 }
14484
14485 /// add to iterator
14487 {
14488 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
14489 }
14490
14491 /// add to iterator
14493 {
14494 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
14495 }
14496
14497 /// subtract from iterator
14499 {
14500 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
14501 }
14502
14503 /// return difference
14505 {
14506 return base_iterator(*this) - base_iterator(other);
14507 }
14508
14509 /// access to successor
14511 {
14512 return *(this->operator+(n));
14513 }
14514
14515 /// return the key of an object iterator
14516 auto key() const -> decltype(std::declval<Base>().key())
14517 {
14518 auto it = --this->base();
14519 return it.key();
14520 }
14521
14522 /// return the value of an iterator
14524 {
14525 auto it = --this->base();
14526 return it.operator * ();
14527 }
14528};
14529
14530} // namespace detail
14532
14533// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
14534
14535// #include <nlohmann/detail/json_custom_base_class.hpp>
14536// __ _____ _____ _____
14537// __| | __| | | | JSON for Modern C++
14538// | | |__ | | | | | | version 3.12.0
14539// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14540//
14541// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14542// SPDX-License-Identifier: MIT
14543
14544
14545
14546#include <type_traits> // conditional, is_same
14547
14548// #include <nlohmann/detail/abi_macros.hpp>
14549
14550
14552namespace detail
14553{
14554
14555/*!
14556@brief Default base class of the @ref basic_json class.
14557
14558So that the correct implementations of the copy / move ctors / assign operators
14559of @ref basic_json do not require complex case distinctions
14560(no base class / custom base class used as customization point),
14561@ref basic_json always has a base class.
14562By default, this class is used because it is empty and thus has no effect
14563on the behavior of @ref basic_json.
14564*/
14566
14567template<class T>
14568using json_base_class = typename std::conditional <
14569 std::is_same<T, void>::value,
14571 T
14572 >::type;
14573
14574} // namespace detail
14576
14577// #include <nlohmann/detail/json_pointer.hpp>
14578// __ _____ _____ _____
14579// __| | __| | | | JSON for Modern C++
14580// | | |__ | | | | | | version 3.12.0
14581// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14582//
14583// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14584// SPDX-License-Identifier: MIT
14585
14586
14587
14588#include <algorithm> // all_of
14589#include <cctype> // isdigit
14590#include <cerrno> // errno, ERANGE
14591#include <cstdlib> // strtoull
14592#ifndef JSON_NO_IO
14593 #include <iosfwd> // ostream
14594#endif // JSON_NO_IO
14595#include <limits> // max
14596#include <numeric> // accumulate
14597#include <string> // string
14598#include <utility> // move
14599#include <vector> // vector
14600
14601// #include <nlohmann/detail/exceptions.hpp>
14602
14603// #include <nlohmann/detail/macro_scope.hpp>
14604
14605// #include <nlohmann/detail/string_concat.hpp>
14606
14607// #include <nlohmann/detail/string_escape.hpp>
14608
14609// #include <nlohmann/detail/value_t.hpp>
14610
14611
14613
14614/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
14615/// @sa https://json.nlohmann.me/api/json_pointer/
14616template<typename RefStringType>
14618{
14619 // allow basic_json to access private members
14621 friend class basic_json;
14622
14623 template<typename>
14624 friend class json_pointer;
14625
14626 template<typename T>
14628 {
14629 using type = T;
14630 };
14631
14634 {
14635 using type = StringType;
14636 };
14637
14638 public:
14639 // for backwards compatibility accept BasicJsonType
14641
14642 /// @brief create JSON pointer
14643 /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
14644 explicit json_pointer(const string_t& s = "")
14645 : reference_tokens(split(s))
14646 {}
14647
14648 /// @brief return a string representation of the JSON pointer
14649 /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
14651 {
14652 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
14653 string_t{},
14654 [](const string_t& a, const string_t& b)
14655 {
14656 return detail::concat(a, '/', detail::escape(b));
14657 });
14658 }
14659
14660 /// @brief return a string representation of the JSON pointer
14661 /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
14663 operator string_t() const
14664 {
14665 return to_string();
14666 }
14667
14668#ifndef JSON_NO_IO
14669 /// @brief write string representation of the JSON pointer to stream
14670 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
14671 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
14672 {
14673 o << ptr.to_string();
14674 return o;
14675 }
14676#endif
14677
14678 /// @brief append another JSON pointer at the end of this JSON pointer
14679 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
14681 {
14682 reference_tokens.insert(reference_tokens.end(),
14683 ptr.reference_tokens.begin(),
14684 ptr.reference_tokens.end());
14685 return *this;
14686 }
14687
14688 /// @brief append an unescaped reference token at the end of this JSON pointer
14689 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
14691 {
14692 push_back(std::move(token));
14693 return *this;
14694 }
14695
14696 /// @brief append an array index at the end of this JSON pointer
14697 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
14698 json_pointer& operator/=(std::size_t array_idx)
14699 {
14700 return *this /= std::to_string(array_idx);
14701 }
14702
14703 /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
14704 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
14706 const json_pointer& rhs)
14707 {
14708 return json_pointer(lhs) /= rhs;
14709 }
14710
14711 /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
14712 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
14713 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
14714 {
14715 return json_pointer(lhs) /= std::move(token);
14716 }
14717
14718 /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
14719 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
14720 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
14721 {
14722 return json_pointer(lhs) /= array_idx;
14723 }
14724
14725 /// @brief returns the parent of this JSON pointer
14726 /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
14728 {
14729 if (empty())
14730 {
14731 return *this;
14732 }
14733
14734 json_pointer res = *this;
14735 res.pop_back();
14736 return res;
14737 }
14738
14739 /// @brief remove last reference token
14740 /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
14742 {
14743 if (JSON_HEDLEY_UNLIKELY(empty()))
14744 {
14745 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14746 }
14747
14748 reference_tokens.pop_back();
14749 }
14750
14751 /// @brief return last reference token
14752 /// @sa https://json.nlohmann.me/api/json_pointer/back/
14753 const string_t& back() const
14754 {
14755 if (JSON_HEDLEY_UNLIKELY(empty()))
14756 {
14757 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14758 }
14759
14760 return reference_tokens.back();
14761 }
14762
14763 /// @brief append an unescaped token at the end of the reference pointer
14764 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
14765 void push_back(const string_t& token)
14766 {
14767 reference_tokens.push_back(token);
14768 }
14769
14770 /// @brief append an unescaped token at the end of the reference pointer
14771 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
14772 void push_back(string_t&& token)
14773 {
14774 reference_tokens.push_back(std::move(token));
14775 }
14776
14777 /// @brief return whether pointer points to the root document
14778 /// @sa https://json.nlohmann.me/api/json_pointer/empty/
14779 bool empty() const noexcept
14780 {
14781 return reference_tokens.empty();
14782 }
14783
14784 private:
14785 /*!
14786 @param[in] s reference token to be converted into an array index
14787
14788 @return integer representation of @a s
14789
14790 @throw parse_error.106 if an array index begins with '0'
14791 @throw parse_error.109 if an array index begins not with a digit
14792 @throw out_of_range.404 if string @a s could not be converted to an integer
14793 @throw out_of_range.410 if an array index exceeds size_type
14794 */
14795 template<typename BasicJsonType>
14796 static typename BasicJsonType::size_type array_index(const string_t& s)
14797 {
14798 using size_type = typename BasicJsonType::size_type;
14799
14800 // error condition (cf. RFC 6901, Sect. 4)
14801 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14802 {
14803 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14804 }
14805
14806 // error condition (cf. RFC 6901, Sect. 4)
14807 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14808 {
14809 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14810 }
14811
14812 const char* p = s.c_str();
14813 char* p_end = nullptr; // NOLINT(misc-const-correctness)
14814 errno = 0; // strtoull doesn't reset errno
14815 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14816 if (p == p_end // invalid input or empty string
14817 || errno == ERANGE // out of range
14818 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14819 {
14820 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14821 }
14822
14823 // only triggered on special platforms (like 32bit), see also
14824 // https://github.com/nlohmann/json/pull/2203
14825 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14826 {
14827 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14828 }
14829
14830 return static_cast<size_type>(res);
14831 }
14832
14834 json_pointer top() const
14835 {
14836 if (JSON_HEDLEY_UNLIKELY(empty()))
14837 {
14838 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14839 }
14840
14841 json_pointer result = *this;
14842 result.reference_tokens = {reference_tokens[0]};
14843 return result;
14844 }
14845
14846 private:
14847 /*!
14848 @brief create and return a reference to the pointed to value
14849
14850 @complexity Linear in the number of reference tokens.
14851
14852 @throw parse_error.109 if array index is not a number
14853 @throw type_error.313 if value cannot be unflattened
14854 */
14855 template<typename BasicJsonType>
14856 BasicJsonType& get_and_create(BasicJsonType& j) const
14857 {
14858 auto* result = &j;
14859
14860 // in case no reference tokens exist, return a reference to the JSON value
14861 // j which will be overwritten by a primitive value
14862 for (const auto& reference_token : reference_tokens)
14863 {
14864 switch (result->type())
14865 {
14867 {
14868 if (reference_token == "0")
14869 {
14870 // start a new array if the reference token is 0
14871 result = &result->operator[](0);
14872 }
14873 else
14874 {
14875 // start a new object otherwise
14876 result = &result->operator[](reference_token);
14877 }
14878 break;
14879 }
14880
14882 {
14883 // create an entry in the object
14884 result = &result->operator[](reference_token);
14885 break;
14886 }
14887
14889 {
14890 // create an entry in the array
14891 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14892 break;
14893 }
14894
14895 /*
14896 The following code is only reached if there exists a reference
14897 token _and_ the current value is primitive. In this case, we have
14898 an error situation, because primitive values may only occur as
14899 a single value; that is, with an empty list of reference tokens.
14900 */
14908 default:
14909 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14910 }
14911 }
14912
14913 return *result;
14914 }
14915
14916 /*!
14917 @brief return a reference to the pointed to value
14918
14919 @note This version does not throw if a value is not present, but tries to
14920 create nested values instead. For instance, calling this function
14921 with pointer `"/this/that"` on a null value is equivalent to calling
14922 `operator[]("this").operator[]("that")` on that value, effectively
14923 changing the null value to an object.
14924
14925 @param[in] ptr a JSON value
14926
14927 @return reference to the JSON value pointed to by the JSON pointer
14928
14929 @complexity Linear in the length of the JSON pointer.
14930
14931 @throw parse_error.106 if an array index begins with '0'
14932 @throw parse_error.109 if an array index was not a number
14933 @throw out_of_range.404 if the JSON pointer can not be resolved
14934 */
14935 template<typename BasicJsonType>
14936 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14937 {
14938 for (const auto& reference_token : reference_tokens)
14939 {
14940 // convert null values to arrays or objects before continuing
14941 if (ptr->is_null())
14942 {
14943 // check if the reference token is a number
14944 const bool nums =
14945 std::all_of(reference_token.begin(), reference_token.end(),
14946 [](const unsigned char x)
14947 {
14948 return std::isdigit(x);
14949 });
14950
14951 // change value to an array for numbers or "-" or to object otherwise
14952 *ptr = (nums || reference_token == "-")
14955 }
14956
14957 switch (ptr->type())
14958 {
14960 {
14961 // use unchecked object access
14962 ptr = &ptr->operator[](reference_token);
14963 break;
14964 }
14965
14967 {
14968 if (reference_token == "-")
14969 {
14970 // explicitly treat "-" as index beyond the end
14971 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14972 }
14973 else
14974 {
14975 // convert array index to number; unchecked access
14976 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14977 }
14978 break;
14979 }
14980
14989 default:
14990 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14991 }
14992 }
14993
14994 return *ptr;
14995 }
14996
14997 /*!
14998 @throw parse_error.106 if an array index begins with '0'
14999 @throw parse_error.109 if an array index was not a number
15000 @throw out_of_range.402 if the array index '-' is used
15001 @throw out_of_range.404 if the JSON pointer can not be resolved
15002 */
15003 template<typename BasicJsonType>
15004 BasicJsonType& get_checked(BasicJsonType* ptr) const
15005 {
15006 for (const auto& reference_token : reference_tokens)
15007 {
15008 switch (ptr->type())
15009 {
15011 {
15012 // note: at performs range check
15013 ptr = &ptr->at(reference_token);
15014 break;
15015 }
15016
15018 {
15019 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15020 {
15021 // "-" always fails the range check
15023 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15024 ") is out of range"), ptr));
15025 }
15026
15027 // note: at performs range check
15028 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15029 break;
15030 }
15031
15040 default:
15041 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15042 }
15043 }
15044
15045 return *ptr;
15046 }
15047
15048 /*!
15049 @brief return a const reference to the pointed to value
15050
15051 @param[in] ptr a JSON value
15052
15053 @return const reference to the JSON value pointed to by the JSON
15054 pointer
15055
15056 @throw parse_error.106 if an array index begins with '0'
15057 @throw parse_error.109 if an array index was not a number
15058 @throw out_of_range.402 if the array index '-' is used
15059 @throw out_of_range.404 if the JSON pointer can not be resolved
15060 */
15061 template<typename BasicJsonType>
15062 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
15063 {
15064 for (const auto& reference_token : reference_tokens)
15065 {
15066 switch (ptr->type())
15067 {
15069 {
15070 // use unchecked object access
15071 ptr = &ptr->operator[](reference_token);
15072 break;
15073 }
15074
15076 {
15077 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15078 {
15079 // "-" cannot be used for const access
15080 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));
15081 }
15082
15083 // use unchecked array access
15084 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
15085 break;
15086 }
15087
15096 default:
15097 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15098 }
15099 }
15100
15101 return *ptr;
15102 }
15103
15104 /*!
15105 @throw parse_error.106 if an array index begins with '0'
15106 @throw parse_error.109 if an array index was not a number
15107 @throw out_of_range.402 if the array index '-' is used
15108 @throw out_of_range.404 if the JSON pointer can not be resolved
15109 */
15110 template<typename BasicJsonType>
15111 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
15112 {
15113 for (const auto& reference_token : reference_tokens)
15114 {
15115 switch (ptr->type())
15116 {
15118 {
15119 // note: at performs range check
15120 ptr = &ptr->at(reference_token);
15121 break;
15122 }
15123
15125 {
15126 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15127 {
15128 // "-" always fails the range check
15130 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15131 ") is out of range"), ptr));
15132 }
15133
15134 // note: at performs range check
15135 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15136 break;
15137 }
15138
15147 default:
15148 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15149 }
15150 }
15151
15152 return *ptr;
15153 }
15154
15155 /*!
15156 @throw parse_error.106 if an array index begins with '0'
15157 @throw parse_error.109 if an array index was not a number
15158 */
15159 template<typename BasicJsonType>
15160 bool contains(const BasicJsonType* ptr) const
15161 {
15162 for (const auto& reference_token : reference_tokens)
15163 {
15164 switch (ptr->type())
15165 {
15167 {
15168 if (!ptr->contains(reference_token))
15169 {
15170 // we did not find the key in the object
15171 return false;
15172 }
15173
15174 ptr = &ptr->operator[](reference_token);
15175 break;
15176 }
15177
15179 {
15180 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15181 {
15182 // "-" always fails the range check
15183 return false;
15184 }
15185 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
15186 {
15187 // invalid char
15188 return false;
15189 }
15190 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
15191 {
15192 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
15193 {
15194 // the first char should be between '1' and '9'
15195 return false;
15196 }
15197 for (std::size_t i = 1; i < reference_token.size(); i++)
15198 {
15199 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
15200 {
15201 // other char should be between '0' and '9'
15202 return false;
15203 }
15204 }
15205 }
15206
15207 const auto idx = array_index<BasicJsonType>(reference_token);
15208 if (idx >= ptr->size())
15209 {
15210 // index out of range
15211 return false;
15212 }
15213
15214 ptr = &ptr->operator[](idx);
15215 break;
15216 }
15217
15226 default:
15227 {
15228 // we do not expect primitive values if there is still a
15229 // reference token to process
15230 return false;
15231 }
15232 }
15233 }
15234
15235 // no reference token left means we found a primitive value
15236 return true;
15237 }
15238
15239 /*!
15240 @brief split the string input to reference tokens
15241
15242 @note This function is only called by the json_pointer constructor.
15243 All exceptions below are documented there.
15244
15245 @throw parse_error.107 if the pointer is not empty or begins with '/'
15246 @throw parse_error.108 if character '~' is not followed by '0' or '1'
15247 */
15248 static std::vector<string_t> split(const string_t& reference_string)
15249 {
15250 std::vector<string_t> result;
15251
15252 // special case: empty reference string -> no reference tokens
15253 if (reference_string.empty())
15254 {
15255 return result;
15256 }
15257
15258 // check if a nonempty reference string begins with slash
15259 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
15260 {
15261 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
15262 }
15263
15264 // extract the reference tokens:
15265 // - slash: position of the last read slash (or end of string)
15266 // - start: position after the previous slash
15267 for (
15268 // search for the first slash after the first character
15269 std::size_t slash = reference_string.find_first_of('/', 1),
15270 // set the beginning of the first reference token
15271 start = 1;
15272 // we can stop if start == 0 (if slash == string_t::npos)
15273 start != 0;
15274 // set the beginning of the next reference token
15275 // (will eventually be 0 if slash == string_t::npos)
15276 start = (slash == string_t::npos) ? 0 : slash + 1,
15277 // find next slash
15278 slash = reference_string.find_first_of('/', start))
15279 {
15280 // use the text between the beginning of the reference token
15281 // (start) and the last slash (slash).
15282 auto reference_token = reference_string.substr(start, slash - start);
15283
15284 // check reference tokens are properly escaped
15285 for (std::size_t pos = reference_token.find_first_of('~');
15286 pos != string_t::npos;
15287 pos = reference_token.find_first_of('~', pos + 1))
15288 {
15289 JSON_ASSERT(reference_token[pos] == '~');
15290
15291 // ~ must be followed by 0 or 1
15292 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
15293 (reference_token[pos + 1] != '0' &&
15294 reference_token[pos + 1] != '1')))
15295 {
15296 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
15297 }
15298 }
15299
15300 // finally, store the reference token
15301 detail::unescape(reference_token);
15302 result.push_back(reference_token);
15303 }
15304
15305 return result;
15306 }
15307
15308 private:
15309 /*!
15310 @param[in] reference_string the reference string to the current value
15311 @param[in] value the value to consider
15312 @param[in,out] result the result object to insert values to
15313
15314 @note Empty objects or arrays are flattened to `null`.
15315 */
15316 template<typename BasicJsonType>
15317 static void flatten(const string_t& reference_string,
15318 const BasicJsonType& value,
15319 BasicJsonType& result)
15320 {
15321 switch (value.type())
15322 {
15324 {
15325 if (value.m_data.m_value.array->empty())
15326 {
15327 // flatten empty array as null
15328 result[reference_string] = nullptr;
15329 }
15330 else
15331 {
15332 // iterate array and use index as a reference string
15333 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
15334 {
15335 flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
15336 value.m_data.m_value.array->operator[](i), result);
15337 }
15338 }
15339 break;
15340 }
15341
15343 {
15344 if (value.m_data.m_value.object->empty())
15345 {
15346 // flatten empty object as null
15347 result[reference_string] = nullptr;
15348 }
15349 else
15350 {
15351 // iterate object and use keys as reference string
15352 for (const auto& element : *value.m_data.m_value.object)
15353 {
15354 flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
15355 }
15356 }
15357 break;
15358 }
15359
15368 default:
15369 {
15370 // add a primitive value with its reference string
15371 result[reference_string] = value;
15372 break;
15373 }
15374 }
15375 }
15376
15377 /*!
15378 @param[in] value flattened JSON
15379
15380 @return unflattened JSON
15381
15382 @throw parse_error.109 if array index is not a number
15383 @throw type_error.314 if value is not an object
15384 @throw type_error.315 if object values are not primitive
15385 @throw type_error.313 if value cannot be unflattened
15386 */
15387 template<typename BasicJsonType>
15388 static BasicJsonType
15389 unflatten(const BasicJsonType& value)
15390 {
15391 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
15392 {
15393 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
15394 }
15395
15396 BasicJsonType result;
15397
15398 // iterate the JSON object values
15399 for (const auto& element : *value.m_data.m_value.object)
15400 {
15401 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
15402 {
15403 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
15404 }
15405
15406 // Assign the value to the reference pointed to by JSON pointer. Note
15407 // that if the JSON pointer is "" (i.e., points to the whole value),
15408 // function get_and_create returns a reference to the result itself.
15409 // An assignment will then create a primitive value.
15410 json_pointer(element.first).get_and_create(result) = element.second;
15411 }
15412
15413 return result;
15414 }
15415
15416 // can't use the conversion operator because of ambiguity
15418 {
15420 result.reference_tokens = reference_tokens;
15421 return result;
15422 }
15423
15425 {
15427 result.reference_tokens = std::move(reference_tokens);
15428 return result;
15429 }
15430
15431 public:
15432#if JSON_HAS_THREE_WAY_COMPARISON
15433 /// @brief compares two JSON pointers for equality
15434 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15435 template<typename RefStringTypeRhs>
15436 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
15437 {
15438 return reference_tokens == rhs.reference_tokens;
15439 }
15440
15441 /// @brief compares JSON pointer and string for equality
15442 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15443 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
15444 bool operator==(const string_t& rhs) const
15445 {
15446 return *this == json_pointer(rhs);
15447 }
15448
15449 /// @brief 3-way compares two JSON pointers
15450 template<typename RefStringTypeRhs>
15451 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
15452 {
15453 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
15454 }
15455#else
15456 /// @brief compares two JSON pointers for equality
15457 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15458 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15459 // NOLINTNEXTLINE(readability-redundant-declaration)
15460 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15461 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15462
15463 /// @brief compares JSON pointer and string for equality
15464 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15465 template<typename RefStringTypeLhs, typename StringType>
15466 // NOLINTNEXTLINE(readability-redundant-declaration)
15467 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15468 const StringType& rhs);
15469
15470 /// @brief compares string and JSON pointer for equality
15471 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15472 template<typename RefStringTypeRhs, typename StringType>
15473 // NOLINTNEXTLINE(readability-redundant-declaration)
15474 friend bool operator==(const StringType& lhs,
15476
15477 /// @brief compares two JSON pointers for inequality
15478 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
15479 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15480 // NOLINTNEXTLINE(readability-redundant-declaration)
15481 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15482 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15483
15484 /// @brief compares JSON pointer and string for inequality
15485 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
15486 template<typename RefStringTypeLhs, typename StringType>
15487 // NOLINTNEXTLINE(readability-redundant-declaration)
15488 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15489 const StringType& rhs);
15490
15491 /// @brief compares string and JSON pointer for inequality
15492 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
15493 template<typename RefStringTypeRhs, typename StringType>
15494 // NOLINTNEXTLINE(readability-redundant-declaration)
15495 friend bool operator!=(const StringType& lhs,
15497
15498 /// @brief compares two JSON pointer for less-than
15499 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15500 // NOLINTNEXTLINE(readability-redundant-declaration)
15501 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
15502 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15503#endif
15504
15505 private:
15506 /// the reference tokens
15507 std::vector<string_t> reference_tokens;
15508};
15509
15510#if !JSON_HAS_THREE_WAY_COMPARISON
15511// functions cannot be defined inside the class due to ODR violations
15512template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15514 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15515{
15516 return lhs.reference_tokens == rhs.reference_tokens;
15517}
15518
15519template<typename RefStringTypeLhs,
15520 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15522inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15523 const StringType& rhs)
15524{
15525 return lhs == json_pointer<RefStringTypeLhs>(rhs);
15526}
15527
15528template<typename RefStringTypeRhs,
15529 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15531inline bool operator==(const StringType& lhs,
15532 const json_pointer<RefStringTypeRhs>& rhs)
15533{
15534 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
15535}
15536
15537template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15539 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15540{
15541 return !(lhs == rhs);
15542}
15543
15544template<typename RefStringTypeLhs,
15545 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15547inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15548 const StringType& rhs)
15549{
15550 return !(lhs == rhs);
15551}
15552
15553template<typename RefStringTypeRhs,
15554 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15556inline bool operator!=(const StringType& lhs,
15557 const json_pointer<RefStringTypeRhs>& rhs)
15558{
15559 return !(lhs == rhs);
15560}
15561
15562template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15564 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15565{
15566 return lhs.reference_tokens < rhs.reference_tokens;
15567}
15568#endif
15569
15571
15572// #include <nlohmann/detail/json_ref.hpp>
15573// __ _____ _____ _____
15574// __| | __| | | | JSON for Modern C++
15575// | | |__ | | | | | | version 3.12.0
15576// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15577//
15578// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15579// SPDX-License-Identifier: MIT
15580
15581
15582
15583#include <initializer_list>
15584#include <utility>
15585
15586// #include <nlohmann/detail/abi_macros.hpp>
15587
15588// #include <nlohmann/detail/meta/type_traits.hpp>
15589
15590
15592namespace detail
15593{
15594
15595template<typename BasicJsonType>
15597{
15598 public:
15599 using value_type = BasicJsonType;
15600
15602 : owned_value(std::move(value))
15603 {}
15604
15605 json_ref(const value_type& value)
15606 : value_ref(&value)
15607 {}
15608
15609 json_ref(std::initializer_list<json_ref> init)
15610 : owned_value(init)
15611 {}
15612
15613 template <
15614 class... Args,
15615 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
15616 json_ref(Args && ... args)
15617 : owned_value(std::forward<Args>(args)...)
15618 {}
15619
15620 // class should be movable only
15621 json_ref(json_ref&&) noexcept = default;
15623 json_ref& operator=(const json_ref&) = delete;
15624 json_ref& operator=(json_ref&&) = delete;
15625 ~json_ref() = default;
15626
15627 value_type moved_or_copied() const
15628 {
15629 if (value_ref == nullptr)
15630 {
15631 return std::move(owned_value);
15632 }
15633 return *value_ref;
15634 }
15635
15636 value_type const& operator*() const
15637 {
15638 return value_ref ? *value_ref : owned_value;
15639 }
15640
15641 value_type const* operator->() const
15642 {
15643 return &** this;
15644 }
15645
15646 private:
15647 mutable value_type owned_value = nullptr;
15648 value_type const* value_ref = nullptr;
15649};
15650
15651} // namespace detail
15653
15654// #include <nlohmann/detail/macro_scope.hpp>
15655
15656// #include <nlohmann/detail/string_concat.hpp>
15657
15658// #include <nlohmann/detail/string_escape.hpp>
15659
15660// #include <nlohmann/detail/string_utils.hpp>
15661
15662// #include <nlohmann/detail/meta/cpp_future.hpp>
15663
15664// #include <nlohmann/detail/meta/type_traits.hpp>
15665
15666// #include <nlohmann/detail/output/binary_writer.hpp>
15667// __ _____ _____ _____
15668// __| | __| | | | JSON for Modern C++
15669// | | |__ | | | | | | version 3.12.0
15670// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15671//
15672// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15673// SPDX-License-Identifier: MIT
15674
15675
15676
15677#include <algorithm> // reverse
15678#include <array> // array
15679#include <map> // map
15680#include <cmath> // isnan, isinf
15681#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
15682#include <cstring> // memcpy
15683#include <limits> // numeric_limits
15684#include <string> // string
15685#include <utility> // move
15686#include <vector> // vector
15687
15688// #include <nlohmann/detail/input/binary_reader.hpp>
15689
15690// #include <nlohmann/detail/macro_scope.hpp>
15691
15692// #include <nlohmann/detail/output/output_adapters.hpp>
15693// __ _____ _____ _____
15694// __| | __| | | | JSON for Modern C++
15695// | | |__ | | | | | | version 3.12.0
15696// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15697//
15698// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15699// SPDX-License-Identifier: MIT
15700
15701
15702
15703#include <algorithm> // copy
15704#include <cstddef> // size_t
15705#include <iterator> // back_inserter
15706#include <memory> // shared_ptr, make_shared
15707#include <string> // basic_string
15708#include <vector> // vector
15709
15710#ifndef JSON_NO_IO
15711 #include <ios> // streamsize
15712 #include <ostream> // basic_ostream
15713#endif // JSON_NO_IO
15714
15715// #include <nlohmann/detail/macro_scope.hpp>
15716
15717
15719namespace detail
15720{
15721
15722/// abstract output adapter interface
15723template<typename CharType> struct output_adapter_protocol
15724{
15725 virtual void write_character(CharType c) = 0;
15726 virtual void write_characters(const CharType* s, std::size_t length) = 0;
15727 virtual ~output_adapter_protocol() = default;
15728
15733 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
15734};
15735
15736/// a type to simplify interfaces
15737template<typename CharType>
15738using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
15739
15740/// output adapter for byte vectors
15741template<typename CharType, typename AllocatorType = std::allocator<CharType>>
15743{
15744 public:
15745 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
15746 : v(vec)
15747 {}
15748
15749 void write_character(CharType c) override
15750 {
15751 v.push_back(c);
15752 }
15753
15755 void write_characters(const CharType* s, std::size_t length) override
15756 {
15757 v.insert(v.end(), s, s + length);
15758 }
15759
15760 private:
15761 std::vector<CharType, AllocatorType>& v;
15762};
15763
15764#ifndef JSON_NO_IO
15765/// output adapter for output streams
15766template<typename CharType>
15768{
15769 public:
15770 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15771 : stream(s)
15772 {}
15773
15774 void write_character(CharType c) override
15775 {
15776 stream.put(c);
15777 }
15778
15780 void write_characters(const CharType* s, std::size_t length) override
15781 {
15782 stream.write(s, static_cast<std::streamsize>(length));
15783 }
15784
15785 private:
15786 std::basic_ostream<CharType>& stream;
15787};
15788#endif // JSON_NO_IO
15789
15790/// output adapter for basic_string
15791template<typename CharType, typename StringType = std::basic_string<CharType>>
15793{
15794 public:
15795 explicit output_string_adapter(StringType& s) noexcept
15796 : str(s)
15797 {}
15798
15799 void write_character(CharType c) override
15800 {
15801 str.push_back(c);
15802 }
15803
15805 void write_characters(const CharType* s, std::size_t length) override
15806 {
15807 str.append(s, length);
15808 }
15809
15810 private:
15811 StringType& str;
15812};
15813
15814template<typename CharType, typename StringType = std::basic_string<CharType>>
15816{
15817 public:
15818 template<typename AllocatorType = std::allocator<CharType>>
15819 output_adapter(std::vector<CharType, AllocatorType>& vec)
15820 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15821
15822#ifndef JSON_NO_IO
15823 output_adapter(std::basic_ostream<CharType>& s)
15824 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15825#endif // JSON_NO_IO
15826
15827 output_adapter(StringType& s)
15828 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15829
15831 {
15832 return oa;
15833 }
15834
15835 private:
15837};
15838
15839} // namespace detail
15841
15842// #include <nlohmann/detail/string_concat.hpp>
15843
15844
15846namespace detail
15847{
15848
15849/// how to encode BJData
15851{
15852 draft2,
15853 draft3,
15854};
15855
15856///////////////////
15857// binary writer //
15858///////////////////
15859
15860/*!
15861@brief serialization to CBOR and MessagePack values
15862*/
15863template<typename BasicJsonType, typename CharType>
15865{
15866 using string_t = typename BasicJsonType::string_t;
15867 using binary_t = typename BasicJsonType::binary_t;
15868 using number_float_t = typename BasicJsonType::number_float_t;
15869
15870 public:
15871 /*!
15872 @brief create a binary writer
15873
15874 @param[in] adapter output adapter to write to
15875 */
15876 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15877 {
15878 JSON_ASSERT(oa);
15879 }
15880
15881 /*!
15882 @param[in] j JSON value to serialize
15883 @pre j.type() == value_t::object
15884 */
15885 void write_bson(const BasicJsonType& j)
15886 {
15887 switch (j.type())
15888 {
15889 case value_t::object:
15890 {
15891 write_bson_object(*j.m_data.m_value.object);
15892 break;
15893 }
15894
15895 case value_t::null:
15896 case value_t::array:
15897 case value_t::string:
15898 case value_t::boolean:
15899 case value_t::number_integer:
15900 case value_t::number_unsigned:
15901 case value_t::number_float:
15902 case value_t::binary:
15903 case value_t::discarded:
15904 default:
15905 {
15906 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15907 }
15908 }
15909 }
15910
15911 /*!
15912 @param[in] j JSON value to serialize
15913 */
15914 void write_cbor(const BasicJsonType& j)
15915 {
15916 switch (j.type())
15917 {
15918 case value_t::null:
15919 {
15920 oa->write_character(to_char_type(0xF6));
15921 break;
15922 }
15923
15924 case value_t::boolean:
15925 {
15926 oa->write_character(j.m_data.m_value.boolean
15927 ? to_char_type(0xF5)
15928 : to_char_type(0xF4));
15929 break;
15930 }
15931
15932 case value_t::number_integer:
15933 {
15934 if (j.m_data.m_value.number_integer >= 0)
15935 {
15936 // CBOR does not differentiate between positive signed
15937 // integers and unsigned integers. Therefore, we used the
15938 // code from the value_t::number_unsigned case here.
15939 if (j.m_data.m_value.number_integer <= 0x17)
15940 {
15941 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15942 }
15943 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15944 {
15945 oa->write_character(to_char_type(0x18));
15946 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15947 }
15948 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15949 {
15950 oa->write_character(to_char_type(0x19));
15951 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15952 }
15953 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15954 {
15955 oa->write_character(to_char_type(0x1A));
15956 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15957 }
15958 else
15959 {
15960 oa->write_character(to_char_type(0x1B));
15961 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15962 }
15963 }
15964 else
15965 {
15966 // The conversions below encode the sign in the first
15967 // byte, and the value is converted to a positive number.
15968 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15969 if (j.m_data.m_value.number_integer >= -24)
15970 {
15971 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15972 }
15973 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15974 {
15975 oa->write_character(to_char_type(0x38));
15976 write_number(static_cast<std::uint8_t>(positive_number));
15977 }
15978 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15979 {
15980 oa->write_character(to_char_type(0x39));
15981 write_number(static_cast<std::uint16_t>(positive_number));
15982 }
15983 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15984 {
15985 oa->write_character(to_char_type(0x3A));
15986 write_number(static_cast<std::uint32_t>(positive_number));
15987 }
15988 else
15989 {
15990 oa->write_character(to_char_type(0x3B));
15991 write_number(static_cast<std::uint64_t>(positive_number));
15992 }
15993 }
15994 break;
15995 }
15996
15997 case value_t::number_unsigned:
15998 {
15999 if (j.m_data.m_value.number_unsigned <= 0x17)
16000 {
16001 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
16002 }
16003 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16004 {
16005 oa->write_character(to_char_type(0x18));
16006 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
16007 }
16008 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16009 {
16010 oa->write_character(to_char_type(0x19));
16011 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
16012 }
16013 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16014 {
16015 oa->write_character(to_char_type(0x1A));
16016 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
16017 }
16018 else
16019 {
16020 oa->write_character(to_char_type(0x1B));
16021 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
16022 }
16023 break;
16024 }
16025
16026 case value_t::number_float:
16027 {
16028 if (std::isnan(j.m_data.m_value.number_float))
16029 {
16030 // NaN is 0xf97e00 in CBOR
16031 oa->write_character(to_char_type(0xF9));
16032 oa->write_character(to_char_type(0x7E));
16033 oa->write_character(to_char_type(0x00));
16034 }
16035 else if (std::isinf(j.m_data.m_value.number_float))
16036 {
16037 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
16038 oa->write_character(to_char_type(0xf9));
16039 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
16040 oa->write_character(to_char_type(0x00));
16041 }
16042 else
16043 {
16044 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
16045 }
16046 break;
16047 }
16048
16049 case value_t::string:
16050 {
16051 // step 1: write control byte and the string length
16052 const auto N = j.m_data.m_value.string->size();
16053 if (N <= 0x17)
16054 {
16055 write_number(static_cast<std::uint8_t>(0x60 + N));
16056 }
16057 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16058 {
16059 oa->write_character(to_char_type(0x78));
16060 write_number(static_cast<std::uint8_t>(N));
16061 }
16062 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16063 {
16064 oa->write_character(to_char_type(0x79));
16065 write_number(static_cast<std::uint16_t>(N));
16066 }
16067 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16068 {
16069 oa->write_character(to_char_type(0x7A));
16070 write_number(static_cast<std::uint32_t>(N));
16071 }
16072 // LCOV_EXCL_START
16073 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16074 {
16075 oa->write_character(to_char_type(0x7B));
16076 write_number(static_cast<std::uint64_t>(N));
16077 }
16078 // LCOV_EXCL_STOP
16079
16080 // step 2: write the string
16081 oa->write_characters(
16082 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16083 j.m_data.m_value.string->size());
16084 break;
16085 }
16086
16087 case value_t::array:
16088 {
16089 // step 1: write control byte and the array size
16090 const auto N = j.m_data.m_value.array->size();
16091 if (N <= 0x17)
16092 {
16093 write_number(static_cast<std::uint8_t>(0x80 + N));
16094 }
16095 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16096 {
16097 oa->write_character(to_char_type(0x98));
16098 write_number(static_cast<std::uint8_t>(N));
16099 }
16100 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16101 {
16102 oa->write_character(to_char_type(0x99));
16103 write_number(static_cast<std::uint16_t>(N));
16104 }
16105 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16106 {
16107 oa->write_character(to_char_type(0x9A));
16108 write_number(static_cast<std::uint32_t>(N));
16109 }
16110 // LCOV_EXCL_START
16111 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16112 {
16113 oa->write_character(to_char_type(0x9B));
16114 write_number(static_cast<std::uint64_t>(N));
16115 }
16116 // LCOV_EXCL_STOP
16117
16118 // step 2: write each element
16119 for (const auto& el : *j.m_data.m_value.array)
16120 {
16121 write_cbor(el);
16122 }
16123 break;
16124 }
16125
16126 case value_t::binary:
16127 {
16128 if (j.m_data.m_value.binary->has_subtype())
16129 {
16130 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
16131 {
16132 write_number(static_cast<std::uint8_t>(0xd8));
16133 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
16134 }
16135 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
16136 {
16137 write_number(static_cast<std::uint8_t>(0xd9));
16138 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
16139 }
16140 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
16141 {
16142 write_number(static_cast<std::uint8_t>(0xda));
16143 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
16144 }
16145 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
16146 {
16147 write_number(static_cast<std::uint8_t>(0xdb));
16148 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
16149 }
16150 }
16151
16152 // step 1: write control byte and the binary array size
16153 const auto N = j.m_data.m_value.binary->size();
16154 if (N <= 0x17)
16155 {
16156 write_number(static_cast<std::uint8_t>(0x40 + N));
16157 }
16158 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16159 {
16160 oa->write_character(to_char_type(0x58));
16161 write_number(static_cast<std::uint8_t>(N));
16162 }
16163 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16164 {
16165 oa->write_character(to_char_type(0x59));
16166 write_number(static_cast<std::uint16_t>(N));
16167 }
16168 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16169 {
16170 oa->write_character(to_char_type(0x5A));
16171 write_number(static_cast<std::uint32_t>(N));
16172 }
16173 // LCOV_EXCL_START
16174 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16175 {
16176 oa->write_character(to_char_type(0x5B));
16177 write_number(static_cast<std::uint64_t>(N));
16178 }
16179 // LCOV_EXCL_STOP
16180
16181 // step 2: write each element
16182 oa->write_characters(
16183 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16184 N);
16185
16186 break;
16187 }
16188
16189 case value_t::object:
16190 {
16191 // step 1: write control byte and the object size
16192 const auto N = j.m_data.m_value.object->size();
16193 if (N <= 0x17)
16194 {
16195 write_number(static_cast<std::uint8_t>(0xA0 + N));
16196 }
16197 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16198 {
16199 oa->write_character(to_char_type(0xB8));
16200 write_number(static_cast<std::uint8_t>(N));
16201 }
16202 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16203 {
16204 oa->write_character(to_char_type(0xB9));
16205 write_number(static_cast<std::uint16_t>(N));
16206 }
16207 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16208 {
16209 oa->write_character(to_char_type(0xBA));
16210 write_number(static_cast<std::uint32_t>(N));
16211 }
16212 // LCOV_EXCL_START
16213 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16214 {
16215 oa->write_character(to_char_type(0xBB));
16216 write_number(static_cast<std::uint64_t>(N));
16217 }
16218 // LCOV_EXCL_STOP
16219
16220 // step 2: write each element
16221 for (const auto& el : *j.m_data.m_value.object)
16222 {
16223 write_cbor(el.first);
16224 write_cbor(el.second);
16225 }
16226 break;
16227 }
16228
16229 case value_t::discarded:
16230 default:
16231 break;
16232 }
16233 }
16234
16235 /*!
16236 @param[in] j JSON value to serialize
16237 */
16238 void write_msgpack(const BasicJsonType& j)
16239 {
16240 switch (j.type())
16241 {
16242 case value_t::null: // nil
16243 {
16244 oa->write_character(to_char_type(0xC0));
16245 break;
16246 }
16247
16248 case value_t::boolean: // true and false
16249 {
16250 oa->write_character(j.m_data.m_value.boolean
16251 ? to_char_type(0xC3)
16252 : to_char_type(0xC2));
16253 break;
16254 }
16255
16256 case value_t::number_integer:
16257 {
16258 if (j.m_data.m_value.number_integer >= 0)
16259 {
16260 // MessagePack does not differentiate between positive
16261 // signed integers and unsigned integers. Therefore, we used
16262 // the code from the value_t::number_unsigned case here.
16263 if (j.m_data.m_value.number_unsigned < 128)
16264 {
16265 // positive fixnum
16266 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16267 }
16268 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16269 {
16270 // uint 8
16271 oa->write_character(to_char_type(0xCC));
16272 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16273 }
16274 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16275 {
16276 // uint 16
16277 oa->write_character(to_char_type(0xCD));
16278 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16279 }
16280 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16281 {
16282 // uint 32
16283 oa->write_character(to_char_type(0xCE));
16284 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16285 }
16286 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16287 {
16288 // uint 64
16289 oa->write_character(to_char_type(0xCF));
16290 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16291 }
16292 }
16293 else
16294 {
16295 if (j.m_data.m_value.number_integer >= -32)
16296 {
16297 // negative fixnum
16298 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16299 }
16300 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
16301 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16302 {
16303 // int 8
16304 oa->write_character(to_char_type(0xD0));
16305 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16306 }
16307 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
16308 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16309 {
16310 // int 16
16311 oa->write_character(to_char_type(0xD1));
16312 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
16313 }
16314 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
16315 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16316 {
16317 // int 32
16318 oa->write_character(to_char_type(0xD2));
16319 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
16320 }
16321 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
16322 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16323 {
16324 // int 64
16325 oa->write_character(to_char_type(0xD3));
16326 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
16327 }
16328 }
16329 break;
16330 }
16331
16332 case value_t::number_unsigned:
16333 {
16334 if (j.m_data.m_value.number_unsigned < 128)
16335 {
16336 // positive fixnum
16337 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16338 }
16339 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16340 {
16341 // uint 8
16342 oa->write_character(to_char_type(0xCC));
16343 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16344 }
16345 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16346 {
16347 // uint 16
16348 oa->write_character(to_char_type(0xCD));
16349 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16350 }
16351 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16352 {
16353 // uint 32
16354 oa->write_character(to_char_type(0xCE));
16355 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16356 }
16357 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16358 {
16359 // uint 64
16360 oa->write_character(to_char_type(0xCF));
16361 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16362 }
16363 break;
16364 }
16365
16366 case value_t::number_float:
16367 {
16368 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
16369 break;
16370 }
16371
16372 case value_t::string:
16373 {
16374 // step 1: write control byte and the string length
16375 const auto N = j.m_data.m_value.string->size();
16376 if (N <= 31)
16377 {
16378 // fixstr
16379 write_number(static_cast<std::uint8_t>(0xA0 | N));
16380 }
16381 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16382 {
16383 // str 8
16384 oa->write_character(to_char_type(0xD9));
16385 write_number(static_cast<std::uint8_t>(N));
16386 }
16387 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16388 {
16389 // str 16
16390 oa->write_character(to_char_type(0xDA));
16391 write_number(static_cast<std::uint16_t>(N));
16392 }
16393 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16394 {
16395 // str 32
16396 oa->write_character(to_char_type(0xDB));
16397 write_number(static_cast<std::uint32_t>(N));
16398 }
16399
16400 // step 2: write the string
16401 oa->write_characters(
16402 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16403 j.m_data.m_value.string->size());
16404 break;
16405 }
16406
16407 case value_t::array:
16408 {
16409 // step 1: write control byte and the array size
16410 const auto N = j.m_data.m_value.array->size();
16411 if (N <= 15)
16412 {
16413 // fixarray
16414 write_number(static_cast<std::uint8_t>(0x90 | N));
16415 }
16416 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16417 {
16418 // array 16
16419 oa->write_character(to_char_type(0xDC));
16420 write_number(static_cast<std::uint16_t>(N));
16421 }
16422 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16423 {
16424 // array 32
16425 oa->write_character(to_char_type(0xDD));
16426 write_number(static_cast<std::uint32_t>(N));
16427 }
16428
16429 // step 2: write each element
16430 for (const auto& el : *j.m_data.m_value.array)
16431 {
16432 write_msgpack(el);
16433 }
16434 break;
16435 }
16436
16437 case value_t::binary:
16438 {
16439 // step 0: determine if the binary type has a set subtype to
16440 // determine whether to use the ext or fixext types
16441 const bool use_ext = j.m_data.m_value.binary->has_subtype();
16442
16443 // step 1: write control byte and the byte string length
16444 const auto N = j.m_data.m_value.binary->size();
16445 if (N <= (std::numeric_limits<std::uint8_t>::max)())
16446 {
16447 std::uint8_t output_type{};
16448 bool fixed = true;
16449 if (use_ext)
16450 {
16451 switch (N)
16452 {
16453 case 1:
16454 output_type = 0xD4; // fixext 1
16455 break;
16456 case 2:
16457 output_type = 0xD5; // fixext 2
16458 break;
16459 case 4:
16460 output_type = 0xD6; // fixext 4
16461 break;
16462 case 8:
16463 output_type = 0xD7; // fixext 8
16464 break;
16465 case 16:
16466 output_type = 0xD8; // fixext 16
16467 break;
16468 default:
16469 output_type = 0xC7; // ext 8
16470 fixed = false;
16471 break;
16472 }
16473
16474 }
16475 else
16476 {
16477 output_type = 0xC4; // bin 8
16478 fixed = false;
16479 }
16480
16481 oa->write_character(to_char_type(output_type));
16482 if (!fixed)
16483 {
16484 write_number(static_cast<std::uint8_t>(N));
16485 }
16486 }
16487 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16488 {
16489 const std::uint8_t output_type = use_ext
16490 ? 0xC8 // ext 16
16491 : 0xC5; // bin 16
16492
16493 oa->write_character(to_char_type(output_type));
16494 write_number(static_cast<std::uint16_t>(N));
16495 }
16496 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16497 {
16498 const std::uint8_t output_type = use_ext
16499 ? 0xC9 // ext 32
16500 : 0xC6; // bin 32
16501
16502 oa->write_character(to_char_type(output_type));
16503 write_number(static_cast<std::uint32_t>(N));
16504 }
16505
16506 // step 1.5: if this is an ext type, write the subtype
16507 if (use_ext)
16508 {
16509 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
16510 }
16511
16512 // step 2: write the byte string
16513 oa->write_characters(
16514 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16515 N);
16516
16517 break;
16518 }
16519
16520 case value_t::object:
16521 {
16522 // step 1: write control byte and the object size
16523 const auto N = j.m_data.m_value.object->size();
16524 if (N <= 15)
16525 {
16526 // fixmap
16527 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
16528 }
16529 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16530 {
16531 // map 16
16532 oa->write_character(to_char_type(0xDE));
16533 write_number(static_cast<std::uint16_t>(N));
16534 }
16535 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16536 {
16537 // map 32
16538 oa->write_character(to_char_type(0xDF));
16539 write_number(static_cast<std::uint32_t>(N));
16540 }
16541
16542 // step 2: write each element
16543 for (const auto& el : *j.m_data.m_value.object)
16544 {
16545 write_msgpack(el.first);
16546 write_msgpack(el.second);
16547 }
16548 break;
16549 }
16550
16551 case value_t::discarded:
16552 default:
16553 break;
16554 }
16555 }
16556
16557 /*!
16558 @param[in] j JSON value to serialize
16559 @param[in] use_count whether to use '#' prefixes (optimized format)
16560 @param[in] use_type whether to use '$' prefixes (optimized format)
16561 @param[in] add_prefix whether prefixes need to be used for this value
16562 @param[in] use_bjdata whether write in BJData format, default is false
16563 @param[in] bjdata_version which BJData version to use, default is draft2
16564 */
16565 void write_ubjson(const BasicJsonType& j, const bool use_count,
16566 const bool use_type, const bool add_prefix = true,
16567 const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2)
16568 {
16569 const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3;
16570
16571 switch (j.type())
16572 {
16573 case value_t::null:
16574 {
16575 if (add_prefix)
16576 {
16577 oa->write_character(to_char_type('Z'));
16578 }
16579 break;
16580 }
16581
16582 case value_t::boolean:
16583 {
16584 if (add_prefix)
16585 {
16586 oa->write_character(j.m_data.m_value.boolean
16587 ? to_char_type('T')
16588 : to_char_type('F'));
16589 }
16590 break;
16591 }
16592
16593 case value_t::number_integer:
16594 {
16595 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
16596 break;
16597 }
16598
16599 case value_t::number_unsigned:
16600 {
16601 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
16602 break;
16603 }
16604
16605 case value_t::number_float:
16606 {
16607 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
16608 break;
16609 }
16610
16611 case value_t::string:
16612 {
16613 if (add_prefix)
16614 {
16615 oa->write_character(to_char_type('S'));
16616 }
16617 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
16618 oa->write_characters(
16619 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16620 j.m_data.m_value.string->size());
16621 break;
16622 }
16623
16624 case value_t::array:
16625 {
16626 if (add_prefix)
16627 {
16628 oa->write_character(to_char_type('['));
16629 }
16630
16631 bool prefix_required = true;
16632 if (use_type && !j.m_data.m_value.array->empty())
16633 {
16634 JSON_ASSERT(use_count);
16635 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16636 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
16637 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16638 {
16639 return ubjson_prefix(v, use_bjdata) == first_prefix;
16640 });
16641
16642 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16643
16644 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16645 {
16646 prefix_required = false;
16647 oa->write_character(to_char_type('$'));
16648 oa->write_character(first_prefix);
16649 }
16650 }
16651
16652 if (use_count)
16653 {
16654 oa->write_character(to_char_type('#'));
16655 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
16656 }
16657
16658 for (const auto& el : *j.m_data.m_value.array)
16659 {
16660 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16661 }
16662
16663 if (!use_count)
16664 {
16665 oa->write_character(to_char_type(']'));
16666 }
16667
16668 break;
16669 }
16670
16671 case value_t::binary:
16672 {
16673 if (add_prefix)
16674 {
16675 oa->write_character(to_char_type('['));
16676 }
16677
16678 if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
16679 {
16680 JSON_ASSERT(use_count);
16681 oa->write_character(to_char_type('$'));
16682 oa->write_character(bjdata_draft3 ? 'B' : 'U');
16683 }
16684
16685 if (use_count)
16686 {
16687 oa->write_character(to_char_type('#'));
16688 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
16689 }
16690
16691 if (use_type)
16692 {
16693 oa->write_characters(
16694 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16695 j.m_data.m_value.binary->size());
16696 }
16697 else
16698 {
16699 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
16700 {
16701 oa->write_character(to_char_type(bjdata_draft3 ? 'B' : 'U'));
16702 oa->write_character(j.m_data.m_value.binary->data()[i]);
16703 }
16704 }
16705
16706 if (!use_count)
16707 {
16708 oa->write_character(to_char_type(']'));
16709 }
16710
16711 break;
16712 }
16713
16714 case value_t::object:
16715 {
16716 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())
16717 {
16718 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)
16719 {
16720 break;
16721 }
16722 }
16723
16724 if (add_prefix)
16725 {
16726 oa->write_character(to_char_type('{'));
16727 }
16728
16729 bool prefix_required = true;
16730 if (use_type && !j.m_data.m_value.object->empty())
16731 {
16732 JSON_ASSERT(use_count);
16733 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16734 const bool same_prefix = std::all_of(j.begin(), j.end(),
16735 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16736 {
16737 return ubjson_prefix(v, use_bjdata) == first_prefix;
16738 });
16739
16740 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16741
16742 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16743 {
16744 prefix_required = false;
16745 oa->write_character(to_char_type('$'));
16746 oa->write_character(first_prefix);
16747 }
16748 }
16749
16750 if (use_count)
16751 {
16752 oa->write_character(to_char_type('#'));
16753 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
16754 }
16755
16756 for (const auto& el : *j.m_data.m_value.object)
16757 {
16758 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
16759 oa->write_characters(
16760 reinterpret_cast<const CharType*>(el.first.c_str()),
16761 el.first.size());
16762 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16763 }
16764
16765 if (!use_count)
16766 {
16767 oa->write_character(to_char_type('}'));
16768 }
16769
16770 break;
16771 }
16772
16773 case value_t::discarded:
16774 default:
16775 break;
16776 }
16777 }
16778
16779 private:
16780 //////////
16781 // BSON //
16782 //////////
16783
16784 /*!
16785 @return The size of a BSON document entry header, including the id marker
16786 and the entry name size (and its null-terminator).
16787 */
16788 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16789 {
16790 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16791 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16792 {
16793 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16794 }
16795
16796 static_cast<void>(j);
16797 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16798 }
16799
16800 /*!
16801 @brief Writes the given @a element_type and @a name to the output adapter
16802 */
16804 const std::uint8_t element_type)
16805 {
16806 oa->write_character(to_char_type(element_type)); // boolean
16807 oa->write_characters(
16808 reinterpret_cast<const CharType*>(name.c_str()),
16809 name.size() + 1u);
16810 }
16811
16812 /*!
16813 @brief Writes a BSON element with key @a name and boolean value @a value
16814 */
16816 const bool value)
16817 {
16818 write_bson_entry_header(name, 0x08);
16819 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16820 }
16821
16822 /*!
16823 @brief Writes a BSON element with key @a name and double value @a value
16824 */
16825 void write_bson_double(const string_t& name,
16826 const double value)
16827 {
16828 write_bson_entry_header(name, 0x01);
16829 write_number<double>(value, true);
16830 }
16831
16832 /*!
16833 @return The size of the BSON-encoded string in @a value
16834 */
16835 static std::size_t calc_bson_string_size(const string_t& value)
16836 {
16837 return sizeof(std::int32_t) + value.size() + 1ul;
16838 }
16839
16840 /*!
16841 @brief Writes a BSON element with key @a name and string value @a value
16842 */
16843 void write_bson_string(const string_t& name,
16844 const string_t& value)
16845 {
16846 write_bson_entry_header(name, 0x02);
16847
16848 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16849 oa->write_characters(
16850 reinterpret_cast<const CharType*>(value.c_str()),
16851 value.size() + 1);
16852 }
16853
16854 /*!
16855 @brief Writes a BSON element with key @a name and null value
16856 */
16857 void write_bson_null(const string_t& name)
16858 {
16859 write_bson_entry_header(name, 0x0A);
16860 }
16861
16862 /*!
16863 @return The size of the BSON-encoded integer @a value
16864 */
16865 static std::size_t calc_bson_integer_size(const std::int64_t value)
16866 {
16867 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16868 ? sizeof(std::int32_t)
16869 : sizeof(std::int64_t);
16870 }
16871
16872 /*!
16873 @brief Writes a BSON element with key @a name and integer @a value
16874 */
16876 const std::int64_t value)
16877 {
16878 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16879 {
16880 write_bson_entry_header(name, 0x10); // int32
16881 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16882 }
16883 else
16884 {
16885 write_bson_entry_header(name, 0x12); // int64
16886 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16887 }
16888 }
16889
16890 /*!
16891 @return The size of the BSON-encoded unsigned integer in @a j
16892 */
16893 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16894 {
16895 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16896 ? sizeof(std::int32_t)
16897 : sizeof(std::int64_t);
16898 }
16899
16900 /*!
16901 @brief Writes a BSON element with key @a name and unsigned @a value
16902 */
16904 const BasicJsonType& j)
16905 {
16906 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16907 {
16908 write_bson_entry_header(name, 0x10 /* int32 */);
16909 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16910 }
16911 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16912 {
16913 write_bson_entry_header(name, 0x12 /* int64 */);
16914 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16915 }
16916 else
16917 {
16918 write_bson_entry_header(name, 0x11 /* uint64 */);
16919 write_number<std::uint64_t>(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned), true);
16920 }
16921 }
16922
16923 /*!
16924 @brief Writes a BSON element with key @a name and object @a value
16925 */
16927 const typename BasicJsonType::object_t& value)
16928 {
16929 write_bson_entry_header(name, 0x03); // object
16930 write_bson_object(value);
16931 }
16932
16933 /*!
16934 @return The size of the BSON-encoded array @a value
16935 */
16936 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16937 {
16938 std::size_t array_index = 0ul;
16939
16940 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)
16941 {
16942 return result + calc_bson_element_size(std::to_string(array_index++), el);
16943 });
16944
16945 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16946 }
16947
16948 /*!
16949 @return The size of the BSON-encoded binary array @a value
16950 */
16951 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16952 {
16953 return sizeof(std::int32_t) + value.size() + 1ul;
16954 }
16955
16956 /*!
16957 @brief Writes a BSON element with key @a name and array @a value
16958 */
16959 void write_bson_array(const string_t& name,
16960 const typename BasicJsonType::array_t& value)
16961 {
16962 write_bson_entry_header(name, 0x04); // array
16963 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16964
16965 std::size_t array_index = 0ul;
16966
16967 for (const auto& el : value)
16968 {
16969 write_bson_element(std::to_string(array_index++), el);
16970 }
16971
16972 oa->write_character(to_char_type(0x00));
16973 }
16974
16975 /*!
16976 @brief Writes a BSON element with key @a name and binary value @a value
16977 */
16978 void write_bson_binary(const string_t& name,
16979 const binary_t& value)
16980 {
16981 write_bson_entry_header(name, 0x05);
16982
16983 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16984 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16985
16986 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16987 }
16988
16989 /*!
16990 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
16991 @return The calculated size for the BSON document entry for @a j with the given @a name.
16992 */
16993 static std::size_t calc_bson_element_size(const string_t& name,
16994 const BasicJsonType& j)
16995 {
16996 const auto header_size = calc_bson_entry_header_size(name, j);
16997 switch (j.type())
16998 {
16999 case value_t::object:
17000 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
17001
17002 case value_t::array:
17003 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
17004
17005 case value_t::binary:
17006 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
17007
17008 case value_t::boolean:
17009 return header_size + 1ul;
17010
17011 case value_t::number_float:
17012 return header_size + 8ul;
17013
17014 case value_t::number_integer:
17015 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
17016
17017 case value_t::number_unsigned:
17018 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
17019
17020 case value_t::string:
17021 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
17022
17023 case value_t::null:
17024 return header_size + 0ul;
17025
17026 // LCOV_EXCL_START
17027 case value_t::discarded:
17028 default:
17029 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17030 return 0ul;
17031 // LCOV_EXCL_STOP
17032 }
17033 }
17034
17035 /*!
17036 @brief Serializes the JSON value @a j to BSON and associates it with the
17037 key @a name.
17038 @param name The name to associate with the JSON entity @a j within the
17039 current BSON document
17040 */
17042 const BasicJsonType& j)
17043 {
17044 switch (j.type())
17045 {
17046 case value_t::object:
17047 return write_bson_object_entry(name, *j.m_data.m_value.object);
17048
17049 case value_t::array:
17050 return write_bson_array(name, *j.m_data.m_value.array);
17051
17052 case value_t::binary:
17053 return write_bson_binary(name, *j.m_data.m_value.binary);
17054
17055 case value_t::boolean:
17056 return write_bson_boolean(name, j.m_data.m_value.boolean);
17057
17058 case value_t::number_float:
17059 return write_bson_double(name, j.m_data.m_value.number_float);
17060
17061 case value_t::number_integer:
17062 return write_bson_integer(name, j.m_data.m_value.number_integer);
17063
17064 case value_t::number_unsigned:
17065 return write_bson_unsigned(name, j);
17066
17067 case value_t::string:
17068 return write_bson_string(name, *j.m_data.m_value.string);
17069
17070 case value_t::null:
17071 return write_bson_null(name);
17072
17073 // LCOV_EXCL_START
17074 case value_t::discarded:
17075 default:
17076 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17077 return;
17078 // LCOV_EXCL_STOP
17079 }
17080 }
17081
17082 /*!
17083 @brief Calculates the size of the BSON serialization of the given
17084 JSON-object @a j.
17085 @param[in] value JSON value to serialize
17086 @pre value.type() == value_t::object
17087 */
17088 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
17089 {
17090 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
17091 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
17092 {
17093 return result += calc_bson_element_size(el.first, el.second);
17094 });
17095
17096 return sizeof(std::int32_t) + document_size + 1ul;
17097 }
17098
17099 /*!
17100 @param[in] value JSON value to serialize
17101 @pre value.type() == value_t::object
17102 */
17103 void write_bson_object(const typename BasicJsonType::object_t& value)
17104 {
17105 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
17106
17107 for (const auto& el : value)
17108 {
17109 write_bson_element(el.first, el.second);
17110 }
17111
17112 oa->write_character(to_char_type(0x00));
17113 }
17114
17115 //////////
17116 // CBOR //
17117 //////////
17118
17119 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
17120 {
17121 return to_char_type(0xFA); // Single-Precision Float
17122 }
17123
17124 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
17125 {
17126 return to_char_type(0xFB); // Double-Precision Float
17127 }
17128
17129 /////////////
17130 // MsgPack //
17131 /////////////
17132
17133 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
17134 {
17135 return to_char_type(0xCA); // float 32
17136 }
17137
17138 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
17139 {
17140 return to_char_type(0xCB); // float 64
17141 }
17142
17143 ////////////
17144 // UBJSON //
17145 ////////////
17146
17147 // UBJSON: write number (floating point)
17148 template<typename NumberType, typename std::enable_if<
17149 std::is_floating_point<NumberType>::value, int>::type = 0>
17150 void write_number_with_ubjson_prefix(const NumberType n,
17151 const bool add_prefix,
17152 const bool use_bjdata)
17153 {
17154 if (add_prefix)
17155 {
17156 oa->write_character(get_ubjson_float_prefix(n));
17157 }
17158 write_number(n, use_bjdata);
17159 }
17160
17161 // UBJSON: write number (unsigned integer)
17162 template<typename NumberType, typename std::enable_if<
17163 std::is_unsigned<NumberType>::value, int>::type = 0>
17164 void write_number_with_ubjson_prefix(const NumberType n,
17165 const bool add_prefix,
17166 const bool use_bjdata)
17167 {
17168 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17169 {
17170 if (add_prefix)
17171 {
17172 oa->write_character(to_char_type('i')); // int8
17173 }
17174 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17175 }
17176 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
17177 {
17178 if (add_prefix)
17179 {
17180 oa->write_character(to_char_type('U')); // uint8
17181 }
17182 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17183 }
17184 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17185 {
17186 if (add_prefix)
17187 {
17188 oa->write_character(to_char_type('I')); // int16
17189 }
17190 write_number(static_cast<std::int16_t>(n), use_bjdata);
17191 }
17192 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
17193 {
17194 if (add_prefix)
17195 {
17196 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17197 }
17198 write_number(static_cast<std::uint16_t>(n), use_bjdata);
17199 }
17200 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17201 {
17202 if (add_prefix)
17203 {
17204 oa->write_character(to_char_type('l')); // int32
17205 }
17206 write_number(static_cast<std::int32_t>(n), use_bjdata);
17207 }
17208 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
17209 {
17210 if (add_prefix)
17211 {
17212 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17213 }
17214 write_number(static_cast<std::uint32_t>(n), use_bjdata);
17215 }
17216 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17217 {
17218 if (add_prefix)
17219 {
17220 oa->write_character(to_char_type('L')); // int64
17221 }
17222 write_number(static_cast<std::int64_t>(n), use_bjdata);
17223 }
17224 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
17225 {
17226 if (add_prefix)
17227 {
17228 oa->write_character(to_char_type('M')); // uint64 - bjdata only
17229 }
17230 write_number(static_cast<std::uint64_t>(n), use_bjdata);
17231 }
17232 else
17233 {
17234 if (add_prefix)
17235 {
17236 oa->write_character(to_char_type('H')); // high-precision number
17237 }
17238
17239 const auto number = BasicJsonType(n).dump();
17240 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17241 for (std::size_t i = 0; i < number.size(); ++i)
17242 {
17243 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17244 }
17245 }
17246 }
17247
17248 // UBJSON: write number (signed integer)
17249 template < typename NumberType, typename std::enable_if <
17250 std::is_signed<NumberType>::value&&
17251 !std::is_floating_point<NumberType>::value, int >::type = 0 >
17252 void write_number_with_ubjson_prefix(const NumberType n,
17253 const bool add_prefix,
17254 const bool use_bjdata)
17255 {
17256 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
17257 {
17258 if (add_prefix)
17259 {
17260 oa->write_character(to_char_type('i')); // int8
17261 }
17262 write_number(static_cast<std::int8_t>(n), use_bjdata);
17263 }
17264 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)()))
17265 {
17266 if (add_prefix)
17267 {
17268 oa->write_character(to_char_type('U')); // uint8
17269 }
17270 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17271 }
17272 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
17273 {
17274 if (add_prefix)
17275 {
17276 oa->write_character(to_char_type('I')); // int16
17277 }
17278 write_number(static_cast<std::int16_t>(n), use_bjdata);
17279 }
17280 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)())))
17281 {
17282 if (add_prefix)
17283 {
17284 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17285 }
17286 write_number(static_cast<uint16_t>(n), use_bjdata);
17287 }
17288 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
17289 {
17290 if (add_prefix)
17291 {
17292 oa->write_character(to_char_type('l')); // int32
17293 }
17294 write_number(static_cast<std::int32_t>(n), use_bjdata);
17295 }
17296 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)())))
17297 {
17298 if (add_prefix)
17299 {
17300 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17301 }
17302 write_number(static_cast<uint32_t>(n), use_bjdata);
17303 }
17304 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
17305 {
17306 if (add_prefix)
17307 {
17308 oa->write_character(to_char_type('L')); // int64
17309 }
17310 write_number(static_cast<std::int64_t>(n), use_bjdata);
17311 }
17312 // LCOV_EXCL_START
17313 else
17314 {
17315 if (add_prefix)
17316 {
17317 oa->write_character(to_char_type('H')); // high-precision number
17318 }
17319
17320 const auto number = BasicJsonType(n).dump();
17321 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17322 for (std::size_t i = 0; i < number.size(); ++i)
17323 {
17324 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17325 }
17326 }
17327 // LCOV_EXCL_STOP
17328 }
17329
17330 /*!
17331 @brief determine the type prefix of container values
17332 */
17333 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
17334 {
17335 switch (j.type())
17336 {
17337 case value_t::null:
17338 return 'Z';
17339
17340 case value_t::boolean:
17341 return j.m_data.m_value.boolean ? 'T' : 'F';
17342
17343 case value_t::number_integer:
17344 {
17345 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)())
17346 {
17347 return 'i';
17348 }
17349 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)())
17350 {
17351 return 'U';
17352 }
17353 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)())
17354 {
17355 return 'I';
17356 }
17357 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)()))
17358 {
17359 return 'u';
17360 }
17361 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)())
17362 {
17363 return 'l';
17364 }
17365 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)()))
17366 {
17367 return 'm';
17368 }
17369 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)())
17370 {
17371 return 'L';
17372 }
17373 // anything else is treated as a high-precision number
17374 return 'H'; // LCOV_EXCL_LINE
17375 }
17376
17377 case value_t::number_unsigned:
17378 {
17379 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17380 {
17381 return 'i';
17382 }
17383 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
17384 {
17385 return 'U';
17386 }
17387 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17388 {
17389 return 'I';
17390 }
17391 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
17392 {
17393 return 'u';
17394 }
17395 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17396 {
17397 return 'l';
17398 }
17399 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
17400 {
17401 return 'm';
17402 }
17403 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17404 {
17405 return 'L';
17406 }
17407 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
17408 {
17409 return 'M';
17410 }
17411 // anything else is treated as a high-precision number
17412 return 'H'; // LCOV_EXCL_LINE
17413 }
17414
17415 case value_t::number_float:
17416 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
17417
17418 case value_t::string:
17419 return 'S';
17420
17421 case value_t::array: // fallthrough
17422 case value_t::binary:
17423 return '[';
17424
17425 case value_t::object:
17426 return '{';
17427
17428 case value_t::discarded:
17429 default: // discarded values
17430 return 'N';
17431 }
17432 }
17433
17434 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
17435 {
17436 return 'd'; // float 32
17437 }
17438
17439 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
17440 {
17441 return 'D'; // float 64
17442 }
17443
17444 /*!
17445 @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid
17446 */
17447 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
17448 {
17449 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
17450 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'},
17451 {"char", 'C'}, {"byte", 'B'}
17452 };
17453
17454 string_t key = "_ArrayType_";
17455 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
17456 if (it == bjdtype.end())
17457 {
17458 return true;
17459 }
17460 CharType dtype = it->second;
17461
17462 key = "_ArraySize_";
17463 std::size_t len = (value.at(key).empty() ? 0 : 1);
17464 for (const auto& el : value.at(key))
17465 {
17466 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
17467 }
17468
17469 key = "_ArrayData_";
17470 if (value.at(key).size() != len)
17471 {
17472 return true;
17473 }
17474
17475 oa->write_character('[');
17476 oa->write_character('$');
17477 oa->write_character(dtype);
17478 oa->write_character('#');
17479
17480 key = "_ArraySize_";
17481 write_ubjson(value.at(key), use_count, use_type, true, true, bjdata_version);
17482
17483 key = "_ArrayData_";
17484 if (dtype == 'U' || dtype == 'C' || dtype == 'B')
17485 {
17486 for (const auto& el : value.at(key))
17487 {
17488 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
17489 }
17490 }
17491 else if (dtype == 'i')
17492 {
17493 for (const auto& el : value.at(key))
17494 {
17495 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
17496 }
17497 }
17498 else if (dtype == 'u')
17499 {
17500 for (const auto& el : value.at(key))
17501 {
17502 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
17503 }
17504 }
17505 else if (dtype == 'I')
17506 {
17507 for (const auto& el : value.at(key))
17508 {
17509 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
17510 }
17511 }
17512 else if (dtype == 'm')
17513 {
17514 for (const auto& el : value.at(key))
17515 {
17516 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
17517 }
17518 }
17519 else if (dtype == 'l')
17520 {
17521 for (const auto& el : value.at(key))
17522 {
17523 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
17524 }
17525 }
17526 else if (dtype == 'M')
17527 {
17528 for (const auto& el : value.at(key))
17529 {
17530 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
17531 }
17532 }
17533 else if (dtype == 'L')
17534 {
17535 for (const auto& el : value.at(key))
17536 {
17537 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
17538 }
17539 }
17540 else if (dtype == 'd')
17541 {
17542 for (const auto& el : value.at(key))
17543 {
17544 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
17545 }
17546 }
17547 else if (dtype == 'D')
17548 {
17549 for (const auto& el : value.at(key))
17550 {
17551 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
17552 }
17553 }
17554 return false;
17555 }
17556
17557 ///////////////////////
17558 // Utility functions //
17559 ///////////////////////
17560
17561 /*
17562 @brief write a number to output input
17563 @param[in] n number of type @a NumberType
17564 @param[in] OutputIsLittleEndian Set to true if output data is
17565 required to be little endian
17566 @tparam NumberType the type of the number
17567
17568 @note This function needs to respect the system's endianness, because bytes
17569 in CBOR, MessagePack, and UBJSON are stored in network order (big
17570 endian) and therefore need reordering on little endian systems.
17571 On the other hand, BSON and BJData use little endian and should reorder
17572 on big endian systems.
17573 */
17574 template<typename NumberType>
17575 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
17576 {
17577 // step 1: write the number to an array of length NumberType
17578 std::array<CharType, sizeof(NumberType)> vec{};
17579 std::memcpy(vec.data(), &n, sizeof(NumberType));
17580
17581 // step 2: write the array to output (with possible reordering)
17582 if (is_little_endian != OutputIsLittleEndian)
17583 {
17584 // reverse byte order prior to conversion if necessary
17585 std::reverse(vec.begin(), vec.end());
17586 }
17587
17588 oa->write_characters(vec.data(), sizeof(NumberType));
17589 }
17590
17592 {
17593#ifdef __GNUC__
17594#pragma GCC diagnostic push
17595#pragma GCC diagnostic ignored "-Wfloat-equal"
17596#endif
17597 if (!std::isfinite(n) || ((static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
17598 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
17599 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))))
17600 {
17601 oa->write_character(format == detail::input_format_t::cbor
17602 ? get_cbor_float_prefix(static_cast<float>(n))
17603 : get_msgpack_float_prefix(static_cast<float>(n)));
17604 write_number(static_cast<float>(n));
17605 }
17606 else
17607 {
17608 oa->write_character(format == detail::input_format_t::cbor
17609 ? get_cbor_float_prefix(n)
17610 : get_msgpack_float_prefix(n));
17611 write_number(n);
17612 }
17613#ifdef __GNUC__
17614#pragma GCC diagnostic pop
17615#endif
17616 }
17617
17618 public:
17619 // The following to_char_type functions are implement the conversion
17620 // between uint8_t and CharType. In case CharType is not unsigned,
17621 // such a conversion is required to allow values greater than 128.
17622 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
17623 template < typename C = CharType,
17624 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
17625 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17626 {
17627 return *reinterpret_cast<char*>(&x);
17628 }
17629
17630 template < typename C = CharType,
17631 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
17632 static CharType to_char_type(std::uint8_t x) noexcept
17633 {
17634 // The std::is_trivial trait is deprecated in C++26. The replacement is to use
17635 // std::is_trivially_copyable and std::is_trivially_default_constructible.
17636 // However, some older library implementations support std::is_trivial
17637 // but not all the std::is_trivially_* traits.
17638 // Since detecting full support across all libraries is difficult,
17639 // we use std::is_trivial unless we are using a standard where it has been deprecated.
17640 // For more details, see: https://github.com/nlohmann/json/pull/4775#issuecomment-2884361627
17641#ifdef JSON_HAS_CPP_26
17642 static_assert(std::is_trivially_copyable<CharType>::value, "CharType must be trivially copyable");
17643 static_assert(std::is_trivially_default_constructible<CharType>::value, "CharType must be trivially default constructible");
17644#else
17645 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
17646#endif
17647
17648 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
17649 CharType result;
17650 std::memcpy(&result, &x, sizeof(x));
17651 return result;
17652 }
17653
17654 template<typename C = CharType,
17656 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17657 {
17658 return x;
17659 }
17660
17661 template < typename InputCharType, typename C = CharType,
17662 enable_if_t <
17663 std::is_signed<C>::value &&
17664 std::is_signed<char>::value &&
17665 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
17666 > * = nullptr >
17667 static constexpr CharType to_char_type(InputCharType x) noexcept
17668 {
17669 return x;
17670 }
17671
17672 private:
17673 /// whether we can assume little endianness
17674 const bool is_little_endian = little_endianness();
17675
17676 /// the output
17678};
17679
17680} // namespace detail
17682
17683// #include <nlohmann/detail/output/output_adapters.hpp>
17684
17685// #include <nlohmann/detail/output/serializer.hpp>
17686// __ _____ _____ _____
17687// __| | __| | | | JSON for Modern C++
17688// | | |__ | | | | | | version 3.12.0
17689// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17690//
17691// SPDX-FileCopyrightText: 2008 - 2009 Björn Hoehrmann <bjoern@hoehrmann.de>
17692// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17693// SPDX-License-Identifier: MIT
17694
17695
17696
17697#include <algorithm> // reverse, remove, fill, find, none_of
17698#include <array> // array
17699#include <clocale> // localeconv, lconv
17700#include <cmath> // labs, isfinite, isnan, signbit
17701#include <cstddef> // size_t, ptrdiff_t
17702#include <cstdint> // uint8_t
17703#include <cstdio> // snprintf
17704#include <limits> // numeric_limits
17705#include <string> // string, char_traits
17706#include <iomanip> // setfill, setw
17707#include <type_traits> // is_same
17708#include <utility> // move
17709
17710// #include <nlohmann/detail/conversions/to_chars.hpp>
17711// __ _____ _____ _____
17712// __| | __| | | | JSON for Modern C++
17713// | | |__ | | | | | | version 3.12.0
17714// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17715//
17716// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
17717// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17718// SPDX-License-Identifier: MIT
17719
17720
17721
17722#include <array> // array
17723#include <cmath> // signbit, isfinite
17724#include <cstdint> // intN_t, uintN_t
17725#include <cstring> // memcpy, memmove
17726#include <limits> // numeric_limits
17727#include <type_traits> // conditional
17728
17729// #include <nlohmann/detail/macro_scope.hpp>
17730
17731
17733namespace detail
17734{
17735
17736/*!
17737@brief implements the Grisu2 algorithm for binary to decimal floating-point
17738conversion.
17739
17740This implementation is a slightly modified version of the reference
17741implementation which may be obtained from
17742http://florian.loitsch.com/publications (bench.tar.gz).
17743
17744The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
17745
17746For a detailed description of the algorithm see:
17747
17748[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
17749 Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
17750 Language Design and Implementation, PLDI 2010
17751[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
17752 Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
17753 Design and Implementation, PLDI 1996
17754*/
17755namespace dtoa_impl
17756{
17757
17758template<typename Target, typename Source>
17759Target reinterpret_bits(const Source source)
17760{
17761 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
17762
17763 Target target;
17764 std::memcpy(&target, &source, sizeof(Source));
17765 return target;
17766}
17767
17768struct diyfp // f * 2^e
17769{
17770 static constexpr int kPrecision = 64; // = q
17771
17772 std::uint64_t f = 0;
17773 int e = 0;
17774
17775 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
17776
17777 /*!
17778 @brief returns x - y
17779 @pre x.e == y.e and x.f >= y.f
17780 */
17781 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
17782 {
17783 JSON_ASSERT(x.e == y.e);
17784 JSON_ASSERT(x.f >= y.f);
17785
17786 return {x.f - y.f, x.e};
17787 }
17788
17789 /*!
17790 @brief returns x * y
17791 @note The result is rounded. (Only the upper q bits are returned.)
17792 */
17793 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17794 {
17795 static_assert(kPrecision == 64, "internal error");
17796
17797 // Computes:
17798 // f = round((x.f * y.f) / 2^q)
17799 // e = x.e + y.e + q
17800
17801 // Emulate the 64-bit * 64-bit multiplication:
17802 //
17803 // p = u * v
17804 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17805 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17806 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17807 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17808 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17809 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17810 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17811 //
17812 // (Since Q might be larger than 2^32 - 1)
17813 //
17814 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17815 //
17816 // (Q_hi + H does not overflow a 64-bit int)
17817 //
17818 // = p_lo + 2^64 p_hi
17819
17820 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17821 const std::uint64_t u_hi = x.f >> 32u;
17822 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17823 const std::uint64_t v_hi = y.f >> 32u;
17824
17825 const std::uint64_t p0 = u_lo * v_lo;
17826 const std::uint64_t p1 = u_lo * v_hi;
17827 const std::uint64_t p2 = u_hi * v_lo;
17828 const std::uint64_t p3 = u_hi * v_hi;
17829
17830 const std::uint64_t p0_hi = p0 >> 32u;
17831 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17832 const std::uint64_t p1_hi = p1 >> 32u;
17833 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17834 const std::uint64_t p2_hi = p2 >> 32u;
17835
17836 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17837
17838 // The full product might now be computed as
17839 //
17840 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17841 // p_lo = p0_lo + (Q << 32)
17842 //
17843 // But in this particular case here, the full p_lo is not required.
17844 // Effectively, we only need to add the highest bit in p_lo to p_hi (and
17845 // Q_hi + 1 does not overflow).
17846
17847 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17848
17849 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17850
17851 return {h, x.e + y.e + 64};
17852 }
17853
17854 /*!
17855 @brief normalize x such that the significand is >= 2^(q-1)
17856 @pre x.f != 0
17857 */
17858 static diyfp normalize(diyfp x) noexcept
17859 {
17860 JSON_ASSERT(x.f != 0);
17861
17862 while ((x.f >> 63u) == 0)
17863 {
17864 x.f <<= 1u;
17865 x.e--;
17866 }
17867
17868 return x;
17869 }
17870
17871 /*!
17872 @brief normalize x such that the result has the exponent E
17873 @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
17874 */
17875 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17876 {
17877 const int delta = x.e - target_exponent;
17878
17879 JSON_ASSERT(delta >= 0);
17880 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17881
17882 return {x.f << delta, target_exponent};
17883 }
17884};
17885
17892
17893/*!
17894Compute the (normalized) diyfp representing the input number 'value' and its
17895boundaries.
17896
17897@pre value must be finite and positive
17898*/
17899template<typename FloatType>
17901{
17902 JSON_ASSERT(std::isfinite(value));
17903 JSON_ASSERT(value > 0);
17904
17905 // Convert the IEEE representation into a diyfp.
17906 //
17907 // If v is denormal:
17908 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17909 // If v is normalized:
17910 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17911
17912 static_assert(std::numeric_limits<FloatType>::is_iec559,
17913 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17914
17915 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17916 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17917 constexpr int kMinExp = 1 - kBias;
17918 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17919
17920 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17921
17922 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17923 const std::uint64_t E = bits >> (kPrecision - 1);
17924 const std::uint64_t F = bits & (kHiddenBit - 1);
17925
17926 const bool is_denormal = E == 0;
17927 const diyfp v = is_denormal
17928 ? diyfp(F, kMinExp)
17929 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17930
17931 // Compute the boundaries m- and m+ of the floating-point value
17932 // v = f * 2^e.
17933 //
17934 // Determine v- and v+, the floating-point predecessor and successor of v,
17935 // respectively.
17936 //
17937 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17938 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17939 //
17940 // v+ = v + 2^e
17941 //
17942 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17943 // between m- and m+ round to v, regardless of how the input rounding
17944 // algorithm breaks ties.
17945 //
17946 // ---+-------------+-------------+-------------+-------------+--- (A)
17947 // v- m- v m+ v+
17948 //
17949 // -----------------+------+------+-------------+-------------+--- (B)
17950 // v- m- v m+ v+
17951
17952 const bool lower_boundary_is_closer = F == 0 && E > 1;
17953 const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
17954 const diyfp m_minus = lower_boundary_is_closer
17955 ? diyfp((4 * v.f) - 1, v.e - 2) // (B)
17956 : diyfp((2 * v.f) - 1, v.e - 1); // (A)
17957
17958 // Determine the normalized w+ = m+.
17959 const diyfp w_plus = diyfp::normalize(m_plus);
17960
17961 // Determine w- = m- such that e_(w-) = e_(w+).
17962 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17963
17964 return {diyfp::normalize(v), w_minus, w_plus};
17965}
17966
17967// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17968// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17969// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17970//
17971// alpha <= e = e_c + e_w + q <= gamma
17972//
17973// or
17974//
17975// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17976// <= f_c * f_w * 2^gamma
17977//
17978// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17979//
17980// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17981//
17982// or
17983//
17984// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17985//
17986// The choice of (alpha,gamma) determines the size of the table and the form of
17987// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17988// in practice:
17989//
17990// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17991// processed independently: An integral part p1, and a fractional part p2:
17992//
17993// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17994// = (f div 2^-e) + (f mod 2^-e) * 2^e
17995// = p1 + p2 * 2^e
17996//
17997// The conversion of p1 into decimal form requires a series of divisions and
17998// modulos by (a power of) 10. These operations are faster for 32-bit than for
17999// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
18000// achieved by choosing
18001//
18002// -e >= 32 or e <= -32 := gamma
18003//
18004// In order to convert the fractional part
18005//
18006// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
18007//
18008// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
18009// d[-i] are extracted in order:
18010//
18011// (10 * p2) div 2^-e = d[-1]
18012// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
18013//
18014// The multiplication by 10 must not overflow. It is sufficient to choose
18015//
18016// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
18017//
18018// Since p2 = f mod 2^-e < 2^-e,
18019//
18020// -e <= 60 or e >= -60 := alpha
18021
18022constexpr int kAlpha = -60;
18023constexpr int kGamma = -32;
18024
18025struct cached_power // c = f * 2^e ~= 10^k
18026{
18027 std::uint64_t f;
18028 int e;
18029 int k;
18030};
18031
18032/*!
18033For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
18034power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
18035satisfies (Definition 3.2 from [1])
18036
18037 alpha <= e_c + e + q <= gamma.
18038*/
18040{
18041 // Now
18042 //
18043 // alpha <= e_c + e + q <= gamma (1)
18044 // ==> f_c * 2^alpha <= c * 2^e * 2^q
18045 //
18046 // and since the c's are normalized, 2^(q-1) <= f_c,
18047 //
18048 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
18049 // ==> 2^(alpha - e - 1) <= c
18050 //
18051 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
18052 //
18053 // k = ceil( log_10( 2^(alpha - e - 1) ) )
18054 // = ceil( (alpha - e - 1) * log_10(2) )
18055 //
18056 // From the paper:
18057 // "In theory the result of the procedure could be wrong since c is rounded,
18058 // and the computation itself is approximated [...]. In practice, however,
18059 // this simple function is sufficient."
18060 //
18061 // For IEEE double precision floating-point numbers converted into
18062 // normalized diyfp's w = f * 2^e, with q = 64,
18063 //
18064 // e >= -1022 (min IEEE exponent)
18065 // -52 (p - 1)
18066 // -52 (p - 1, possibly normalize denormal IEEE numbers)
18067 // -11 (normalize the diyfp)
18068 // = -1137
18069 //
18070 // and
18071 //
18072 // e <= +1023 (max IEEE exponent)
18073 // -52 (p - 1)
18074 // -11 (normalize the diyfp)
18075 // = 960
18076 //
18077 // This binary exponent range [-1137,960] results in a decimal exponent
18078 // range [-307,324]. One does not need to store a cached power for each
18079 // k in this range. For each such k it suffices to find a cached power
18080 // such that the exponent of the product lies in [alpha,gamma].
18081 // This implies that the difference of the decimal exponents of adjacent
18082 // table entries must be less than or equal to
18083 //
18084 // floor( (gamma - alpha) * log_10(2) ) = 8.
18085 //
18086 // (A smaller distance gamma-alpha would require a larger table.)
18087
18088 // NB:
18089 // Actually, this function returns c, such that -60 <= e_c + e + 64 <= -34.
18090
18091 constexpr int kCachedPowersMinDecExp = -300;
18092 constexpr int kCachedPowersDecStep = 8;
18093
18094 static constexpr std::array<cached_power, 79> kCachedPowers =
18095 {
18096 {
18097 { 0xAB70FE17C79AC6CA, -1060, -300 },
18098 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
18099 { 0xBE5691EF416BD60C, -1007, -284 },
18100 { 0x8DD01FAD907FFC3C, -980, -276 },
18101 { 0xD3515C2831559A83, -954, -268 },
18102 { 0x9D71AC8FADA6C9B5, -927, -260 },
18103 { 0xEA9C227723EE8BCB, -901, -252 },
18104 { 0xAECC49914078536D, -874, -244 },
18105 { 0x823C12795DB6CE57, -847, -236 },
18106 { 0xC21094364DFB5637, -821, -228 },
18107 { 0x9096EA6F3848984F, -794, -220 },
18108 { 0xD77485CB25823AC7, -768, -212 },
18109 { 0xA086CFCD97BF97F4, -741, -204 },
18110 { 0xEF340A98172AACE5, -715, -196 },
18111 { 0xB23867FB2A35B28E, -688, -188 },
18112 { 0x84C8D4DFD2C63F3B, -661, -180 },
18113 { 0xC5DD44271AD3CDBA, -635, -172 },
18114 { 0x936B9FCEBB25C996, -608, -164 },
18115 { 0xDBAC6C247D62A584, -582, -156 },
18116 { 0xA3AB66580D5FDAF6, -555, -148 },
18117 { 0xF3E2F893DEC3F126, -529, -140 },
18118 { 0xB5B5ADA8AAFF80B8, -502, -132 },
18119 { 0x87625F056C7C4A8B, -475, -124 },
18120 { 0xC9BCFF6034C13053, -449, -116 },
18121 { 0x964E858C91BA2655, -422, -108 },
18122 { 0xDFF9772470297EBD, -396, -100 },
18123 { 0xA6DFBD9FB8E5B88F, -369, -92 },
18124 { 0xF8A95FCF88747D94, -343, -84 },
18125 { 0xB94470938FA89BCF, -316, -76 },
18126 { 0x8A08F0F8BF0F156B, -289, -68 },
18127 { 0xCDB02555653131B6, -263, -60 },
18128 { 0x993FE2C6D07B7FAC, -236, -52 },
18129 { 0xE45C10C42A2B3B06, -210, -44 },
18130 { 0xAA242499697392D3, -183, -36 },
18131 { 0xFD87B5F28300CA0E, -157, -28 },
18132 { 0xBCE5086492111AEB, -130, -20 },
18133 { 0x8CBCCC096F5088CC, -103, -12 },
18134 { 0xD1B71758E219652C, -77, -4 },
18135 { 0x9C40000000000000, -50, 4 },
18136 { 0xE8D4A51000000000, -24, 12 },
18137 { 0xAD78EBC5AC620000, 3, 20 },
18138 { 0x813F3978F8940984, 30, 28 },
18139 { 0xC097CE7BC90715B3, 56, 36 },
18140 { 0x8F7E32CE7BEA5C70, 83, 44 },
18141 { 0xD5D238A4ABE98068, 109, 52 },
18142 { 0x9F4F2726179A2245, 136, 60 },
18143 { 0xED63A231D4C4FB27, 162, 68 },
18144 { 0xB0DE65388CC8ADA8, 189, 76 },
18145 { 0x83C7088E1AAB65DB, 216, 84 },
18146 { 0xC45D1DF942711D9A, 242, 92 },
18147 { 0x924D692CA61BE758, 269, 100 },
18148 { 0xDA01EE641A708DEA, 295, 108 },
18149 { 0xA26DA3999AEF774A, 322, 116 },
18150 { 0xF209787BB47D6B85, 348, 124 },
18151 { 0xB454E4A179DD1877, 375, 132 },
18152 { 0x865B86925B9BC5C2, 402, 140 },
18153 { 0xC83553C5C8965D3D, 428, 148 },
18154 { 0x952AB45CFA97A0B3, 455, 156 },
18155 { 0xDE469FBD99A05FE3, 481, 164 },
18156 { 0xA59BC234DB398C25, 508, 172 },
18157 { 0xF6C69A72A3989F5C, 534, 180 },
18158 { 0xB7DCBF5354E9BECE, 561, 188 },
18159 { 0x88FCF317F22241E2, 588, 196 },
18160 { 0xCC20CE9BD35C78A5, 614, 204 },
18161 { 0x98165AF37B2153DF, 641, 212 },
18162 { 0xE2A0B5DC971F303A, 667, 220 },
18163 { 0xA8D9D1535CE3B396, 694, 228 },
18164 { 0xFB9B7CD9A4A7443C, 720, 236 },
18165 { 0xBB764C4CA7A44410, 747, 244 },
18166 { 0x8BAB8EEFB6409C1A, 774, 252 },
18167 { 0xD01FEF10A657842C, 800, 260 },
18168 { 0x9B10A4E5E9913129, 827, 268 },
18169 { 0xE7109BFBA19C0C9D, 853, 276 },
18170 { 0xAC2820D9623BF429, 880, 284 },
18171 { 0x80444B5E7AA7CF85, 907, 292 },
18172 { 0xBF21E44003ACDD2D, 933, 300 },
18173 { 0x8E679C2F5E44FF8F, 960, 308 },
18174 { 0xD433179D9C8CB841, 986, 316 },
18175 { 0x9E19DB92B4E31BA9, 1013, 324 },
18176 }
18177 };
18178
18179 // This computation gives exactly the same results for k as
18180 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
18181 // for |e| <= 1500, but doesn't require floating-point operations.
18182 // NB: log_10(2) ~= 78913 / 2^18
18183 JSON_ASSERT(e >= -1500);
18184 JSON_ASSERT(e <= 1500);
18185 const int f = kAlpha - e - 1;
18186 const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
18187
18188 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
18189 JSON_ASSERT(index >= 0);
18190 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
18191
18192 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
18193 JSON_ASSERT(kAlpha <= cached.e + e + 64);
18194 JSON_ASSERT(kGamma >= cached.e + e + 64);
18195
18196 return cached;
18197}
18198
18199/*!
18200For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
18201For n == 0, returns 1 and sets pow10 := 1.
18202*/
18203inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
18204{
18205 // LCOV_EXCL_START
18206 if (n >= 1000000000)
18207 {
18208 pow10 = 1000000000;
18209 return 10;
18210 }
18211 // LCOV_EXCL_STOP
18212 if (n >= 100000000)
18213 {
18214 pow10 = 100000000;
18215 return 9;
18216 }
18217 if (n >= 10000000)
18218 {
18219 pow10 = 10000000;
18220 return 8;
18221 }
18222 if (n >= 1000000)
18223 {
18224 pow10 = 1000000;
18225 return 7;
18226 }
18227 if (n >= 100000)
18228 {
18229 pow10 = 100000;
18230 return 6;
18231 }
18232 if (n >= 10000)
18233 {
18234 pow10 = 10000;
18235 return 5;
18236 }
18237 if (n >= 1000)
18238 {
18239 pow10 = 1000;
18240 return 4;
18241 }
18242 if (n >= 100)
18243 {
18244 pow10 = 100;
18245 return 3;
18246 }
18247 if (n >= 10)
18248 {
18249 pow10 = 10;
18250 return 2;
18251 }
18252
18253 pow10 = 1;
18254 return 1;
18255}
18256
18257inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
18258 std::uint64_t rest, std::uint64_t ten_k)
18259{
18260 JSON_ASSERT(len >= 1);
18261 JSON_ASSERT(dist <= delta);
18262 JSON_ASSERT(rest <= delta);
18263 JSON_ASSERT(ten_k > 0);
18264
18265 // <--------------------------- delta ---->
18266 // <---- dist --------->
18267 // --------------[------------------+-------------------]--------------
18268 // M- w M+
18269 //
18270 // ten_k
18271 // <------>
18272 // <---- rest ---->
18273 // --------------[------------------+----+--------------]--------------
18274 // w V
18275 // = buf * 10^k
18276 //
18277 // ten_k represents a unit-in-the-last-place in the decimal representation
18278 // stored in buf.
18279 // Decrement buf by ten_k while this takes buf closer to w.
18280
18281 // The tests are written in this order to avoid overflow in unsigned
18282 // integer arithmetic.
18283
18284 while (rest < dist
18285 && delta - rest >= ten_k
18286 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
18287 {
18288 JSON_ASSERT(buf[len - 1] != '0');
18289 buf[len - 1]--;
18290 rest += ten_k;
18291 }
18292}
18293
18294/*!
18295Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
18296M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
18297*/
18298inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
18299 diyfp M_minus, diyfp w, diyfp M_plus)
18300{
18301 static_assert(kAlpha >= -60, "internal error");
18302 static_assert(kGamma <= -32, "internal error");
18303
18304 // Generates the digits (and the exponent) of a decimal floating-point
18305 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
18306 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
18307 //
18308 // <--------------------------- delta ---->
18309 // <---- dist --------->
18310 // --------------[------------------+-------------------]--------------
18311 // M- w M+
18312 //
18313 // Grisu2 generates the digits of M+ from left to right and stops as soon as
18314 // V is in [M-,M+].
18315
18316 JSON_ASSERT(M_plus.e >= kAlpha);
18317 JSON_ASSERT(M_plus.e <= kGamma);
18318
18319 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
18320 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
18321
18322 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
18323 //
18324 // M+ = f * 2^e
18325 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
18326 // = ((p1 ) * 2^-e + (p2 )) * 2^e
18327 // = p1 + p2 * 2^e
18328
18329 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
18330
18331 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.)
18332 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
18333
18334 // 1)
18335 //
18336 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
18337
18338 JSON_ASSERT(p1 > 0);
18339
18340 std::uint32_t pow10{};
18341 const int k = find_largest_pow10(p1, pow10);
18342
18343 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
18344 //
18345 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
18346 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
18347 //
18348 // M+ = p1 + p2 * 2^e
18349 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
18350 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
18351 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
18352 //
18353 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
18354 //
18355 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
18356 //
18357 // but stop as soon as
18358 //
18359 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
18360
18361 int n = k;
18362 while (n > 0)
18363 {
18364 // Invariants:
18365 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
18366 // pow10 = 10^(n-1) <= p1 < 10^n
18367 //
18368 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
18369 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
18370 //
18371 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
18372 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
18373 //
18374 JSON_ASSERT(d <= 9);
18375 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18376 //
18377 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
18378 //
18379 p1 = r;
18380 n--;
18381 //
18382 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
18383 // pow10 = 10^n
18384 //
18385
18386 // Now check if enough digits have been generated.
18387 // Compute
18388 //
18389 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
18390 //
18391 // Note:
18392 // Since rest and delta share the same exponent e, it suffices to
18393 // compare the significands.
18394 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
18395 if (rest <= delta)
18396 {
18397 // V = buffer * 10^n, with M- <= V <= M+.
18398
18399 decimal_exponent += n;
18400
18401 // We may now just stop. But instead, it looks as if the buffer
18402 // could be decremented to bring V closer to w.
18403 //
18404 // pow10 = 10^n is now 1 ulp in the decimal representation V.
18405 // The rounding procedure works with diyfp's with an implicit
18406 // exponent of e.
18407 //
18408 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
18409 //
18410 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
18411 grisu2_round(buffer, length, dist, delta, rest, ten_n);
18412
18413 return;
18414 }
18415
18416 pow10 /= 10;
18417 //
18418 // pow10 = 10^(n-1) <= p1 < 10^n
18419 // Invariants restored.
18420 }
18421
18422 // 2)
18423 //
18424 // The digits of the integral part have been generated:
18425 //
18426 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
18427 // = buffer + p2 * 2^e
18428 //
18429 // Now generate the digits of the fractional part p2 * 2^e.
18430 //
18431 // Note:
18432 // No decimal point is generated: the exponent is adjusted instead.
18433 //
18434 // p2 actually represents the fraction
18435 //
18436 // p2 * 2^e
18437 // = p2 / 2^-e
18438 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
18439 //
18440 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
18441 //
18442 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
18443 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
18444 //
18445 // using
18446 //
18447 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
18448 // = ( d) * 2^-e + ( r)
18449 //
18450 // or
18451 // 10^m * p2 * 2^e = d + r * 2^e
18452 //
18453 // i.e.
18454 //
18455 // M+ = buffer + p2 * 2^e
18456 // = buffer + 10^-m * (d + r * 2^e)
18457 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
18458 //
18459 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
18460
18461 JSON_ASSERT(p2 > delta);
18462
18463 int m = 0;
18464 for (;;)
18465 {
18466 // Invariant:
18467 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
18468 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
18469 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
18470 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
18471 //
18472 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
18473 p2 *= 10;
18474 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
18475 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
18476 //
18477 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
18478 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
18479 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
18480 //
18481 JSON_ASSERT(d <= 9);
18482 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18483 //
18484 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
18485 //
18486 p2 = r;
18487 m++;
18488 //
18489 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
18490 // Invariant restored.
18491
18492 // Check if enough digits have been generated.
18493 //
18494 // 10^-m * p2 * 2^e <= delta * 2^e
18495 // p2 * 2^e <= 10^m * delta * 2^e
18496 // p2 <= 10^m * delta
18497 delta *= 10;
18498 dist *= 10;
18499 if (p2 <= delta)
18500 {
18501 break;
18502 }
18503 }
18504
18505 // V = buffer * 10^-m, with M- <= V <= M+.
18506
18507 decimal_exponent -= m;
18508
18509 // 1 ulp in the decimal representation is now 10^-m.
18510 // Since delta and dist are now scaled by 10^m, we need to do the
18511 // same with ulp in order to keep the units in sync.
18512 //
18513 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
18514 //
18515 const std::uint64_t ten_m = one.f;
18516 grisu2_round(buffer, length, dist, delta, p2, ten_m);
18517
18518 // By construction this algorithm generates the shortest possible decimal
18519 // number (Loitsch, Theorem 6.2) which rounds back to w.
18520 // For an input number of precision p, at least
18521 //
18522 // N = 1 + ceil(p * log_10(2))
18523 //
18524 // decimal digits are sufficient to identify all binary floating-point
18525 // numbers (Matula, "In-and-Out conversions").
18526 // This implies that the algorithm does not produce more than N decimal
18527 // digits.
18528 //
18529 // N = 17 for p = 53 (IEEE double precision)
18530 // N = 9 for p = 24 (IEEE single precision)
18531}
18532
18533/*!
18534v = buf * 10^decimal_exponent
18535len is the length of the buffer (number of decimal digits)
18536The buffer must be large enough, i.e. >= max_digits10.
18537*/
18539inline void grisu2(char* buf, int& len, int& decimal_exponent,
18540 diyfp m_minus, diyfp v, diyfp m_plus)
18541{
18542 JSON_ASSERT(m_plus.e == m_minus.e);
18543 JSON_ASSERT(m_plus.e == v.e);
18544
18545 // --------(-----------------------+-----------------------)-------- (A)
18546 // m- v m+
18547 //
18548 // --------------------(-----------+-----------------------)-------- (B)
18549 // m- v m+
18550 //
18551 // First scale v (and m- and m+) such that the exponent is in the range
18552 // [alpha, gamma].
18553
18554 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
18555
18556 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
18557
18558 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
18559 const diyfp w = diyfp::mul(v, c_minus_k);
18560 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
18561 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
18562
18563 // ----(---+---)---------------(---+---)---------------(---+---)----
18564 // w- w w+
18565 // = c*m- = c*v = c*m+
18566 //
18567 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
18568 // w+ are now off by a small amount.
18569 // In fact:
18570 //
18571 // w - v * 10^k < 1 ulp
18572 //
18573 // To account for this inaccuracy, add resp. subtract 1 ulp.
18574 //
18575 // --------+---[---------------(---+---)---------------]---+--------
18576 // w- M- w M+ w+
18577 //
18578 // Now any number in [M-, M+] (bounds included) will round to w when input,
18579 // regardless of how the input rounding algorithm breaks ties.
18580 //
18581 // And digit_gen generates the shortest possible such number in [M-, M+].
18582 // Note that this does not mean that Grisu2 always generates the shortest
18583 // possible number in the interval (m-, m+).
18584 const diyfp M_minus(w_minus.f + 1, w_minus.e);
18585 const diyfp M_plus (w_plus.f - 1, w_plus.e );
18586
18587 decimal_exponent = -cached.k; // = -(-k) = k
18588
18589 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
18590}
18591
18592/*!
18593v = buf * 10^decimal_exponent
18594len is the length of the buffer (number of decimal digits)
18595The buffer must be large enough, i.e. >= max_digits10.
18596*/
18597template<typename FloatType>
18599void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
18600{
18601 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
18602 "internal error: not enough precision");
18603
18604 JSON_ASSERT(std::isfinite(value));
18605 JSON_ASSERT(value > 0);
18606
18607 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
18608 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
18609 // decimal representations are not exactly "short".
18610 //
18611 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
18612 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
18613 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
18614 // does.
18615 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
18616 // representation using the corresponding std::from_chars function recovers value exactly". That
18617 // indicates that single precision floating-point numbers should be recovered using
18618 // 'std::strtof'.
18619 //
18620 // NB: If the neighbors are computed for single-precision numbers, there is a single float
18621 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
18622 // value is off by 1 ulp.
18623#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
18624 const boundaries w = compute_boundaries(static_cast<double>(value));
18625#else
18626 const boundaries w = compute_boundaries(value);
18627#endif
18628
18629 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
18630}
18631
18632/*!
18633@brief appends a decimal representation of e to buf
18634@return a pointer to the element following the exponent.
18635@pre -1000 < e < 1000
18636*/
18639inline char* append_exponent(char* buf, int e)
18640{
18641 JSON_ASSERT(e > -1000);
18642 JSON_ASSERT(e < 1000);
18643
18644 if (e < 0)
18645 {
18646 e = -e;
18647 *buf++ = '-';
18648 }
18649 else
18650 {
18651 *buf++ = '+';
18652 }
18653
18654 auto k = static_cast<std::uint32_t>(e);
18655 if (k < 10)
18656 {
18657 // Always print at least two digits in the exponent.
18658 // This is for compatibility with printf("%g").
18659 *buf++ = '0';
18660 *buf++ = static_cast<char>('0' + k);
18661 }
18662 else if (k < 100)
18663 {
18664 *buf++ = static_cast<char>('0' + (k / 10));
18665 k %= 10;
18666 *buf++ = static_cast<char>('0' + k);
18667 }
18668 else
18669 {
18670 *buf++ = static_cast<char>('0' + (k / 100));
18671 k %= 100;
18672 *buf++ = static_cast<char>('0' + (k / 10));
18673 k %= 10;
18674 *buf++ = static_cast<char>('0' + k);
18675 }
18676
18677 return buf;
18678}
18679
18680/*!
18681@brief prettify v = buf * 10^decimal_exponent
18682
18683If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
18684notation. Otherwise it will be printed in exponential notation.
18685
18686@pre min_exp < 0
18687@pre max_exp > 0
18688*/
18691inline char* format_buffer(char* buf, int len, int decimal_exponent,
18692 int min_exp, int max_exp)
18693{
18694 JSON_ASSERT(min_exp < 0);
18695 JSON_ASSERT(max_exp > 0);
18696
18697 const int k = len;
18698 const int n = len + decimal_exponent;
18699
18700 // v = buf * 10^(n-k)
18701 // k is the length of the buffer (number of decimal digits)
18702 // n is the position of the decimal point relative to the start of the buffer.
18703
18704 if (k <= n && n <= max_exp)
18705 {
18706 // digits[000]
18707 // len <= max_exp + 2
18708
18709 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
18710 // Make it look like a floating-point number (#362, #378)
18711 buf[n + 0] = '.';
18712 buf[n + 1] = '0';
18713 return buf + (static_cast<size_t>(n) + 2);
18714 }
18715
18716 if (0 < n && n <= max_exp)
18717 {
18718 // dig.its
18719 // len <= max_digits10 + 1
18720
18721 JSON_ASSERT(k > n);
18722
18723 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
18724 buf[n] = '.';
18725 return buf + (static_cast<size_t>(k) + 1U);
18726 }
18727
18728 if (min_exp < n && n <= 0)
18729 {
18730 // 0.[000]digits
18731 // len <= 2 + (-min_exp - 1) + max_digits10
18732
18733 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
18734 buf[0] = '0';
18735 buf[1] = '.';
18736 std::memset(buf + 2, '0', static_cast<size_t>(-n));
18737 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
18738 }
18739
18740 if (k == 1)
18741 {
18742 // dE+123
18743 // len <= 1 + 5
18744
18745 buf += 1;
18746 }
18747 else
18748 {
18749 // d.igitsE+123
18750 // len <= max_digits10 + 1 + 5
18751
18752 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
18753 buf[1] = '.';
18754 buf += 1 + static_cast<size_t>(k);
18755 }
18756
18757 *buf++ = 'e';
18758 return append_exponent(buf, n - 1);
18759}
18760
18761} // namespace dtoa_impl
18762
18763/*!
18764@brief generates a decimal representation of the floating-point number value in [first, last).
18765
18766The format of the resulting decimal representation is similar to printf's %g
18767format. Returns an iterator pointing past-the-end of the decimal representation.
18768
18769@note The input number must be finite, i.e. NaN's and Inf's are not supported.
18770@note The buffer must be large enough.
18771@note The result is NOT null-terminated.
18772*/
18773template<typename FloatType>
18776char* to_chars(char* first, const char* last, FloatType value)
18777{
18778 static_cast<void>(last); // maybe unused - fix warning
18779 JSON_ASSERT(std::isfinite(value));
18780
18781 // Use signbit(value) instead of (value < 0) since signbit works for -0.
18782 if (std::signbit(value))
18783 {
18784 value = -value;
18785 *first++ = '-';
18786 }
18787
18788#ifdef __GNUC__
18789#pragma GCC diagnostic push
18790#pragma GCC diagnostic ignored "-Wfloat-equal"
18791#endif
18792 if (value == 0) // +-0
18793 {
18794 *first++ = '0';
18795 // Make it look like a floating-point number (#362, #378)
18796 *first++ = '.';
18797 *first++ = '0';
18798 return first;
18799 }
18800#ifdef __GNUC__
18801#pragma GCC diagnostic pop
18802#endif
18803
18804 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18805
18806 // Compute v = buffer * 10^decimal_exponent.
18807 // The decimal digits are stored in the buffer, which needs to be interpreted
18808 // as an unsigned decimal integer.
18809 // len is the length of the buffer, i.e., the number of decimal digits.
18810 int len = 0;
18811 int decimal_exponent = 0;
18812 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18813
18814 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18815
18816 // Format the buffer like printf("%.*g", prec, value)
18817 constexpr int kMinExp = -4;
18818 // Use digits10 here to increase compatibility with version 2.
18819 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18820
18821 JSON_ASSERT(last - first >= kMaxExp + 2);
18822 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18823 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18824
18825 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18826}
18827
18828} // namespace detail
18830
18831// #include <nlohmann/detail/exceptions.hpp>
18832
18833// #include <nlohmann/detail/macro_scope.hpp>
18834
18835// #include <nlohmann/detail/meta/cpp_future.hpp>
18836
18837// #include <nlohmann/detail/output/binary_writer.hpp>
18838
18839// #include <nlohmann/detail/output/output_adapters.hpp>
18840
18841// #include <nlohmann/detail/string_concat.hpp>
18842
18843// #include <nlohmann/detail/value_t.hpp>
18844
18845
18847namespace detail
18848{
18849
18850///////////////////
18851// serialization //
18852///////////////////
18853
18854/// how to treat decoding errors
18856{
18857 strict, ///< throw a type_error exception in case of invalid UTF-8
18858 replace, ///< replace invalid UTF-8 sequences with U+FFFD
18859 ignore ///< ignore invalid UTF-8 sequences
18860};
18861
18862template<typename BasicJsonType>
18864{
18865 using string_t = typename BasicJsonType::string_t;
18866 using number_float_t = typename BasicJsonType::number_float_t;
18867 using number_integer_t = typename BasicJsonType::number_integer_t;
18868 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18869 using binary_char_t = typename BasicJsonType::binary_t::value_type;
18870 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18871 static constexpr std::uint8_t UTF8_REJECT = 1;
18872
18873 public:
18874 /*!
18875 @param[in] s output stream to serialize to
18876 @param[in] ichar indentation character to use
18877 @param[in] error_handler_ how to react on decoding errors
18878 */
18880 error_handler_t error_handler_ = error_handler_t::strict)
18881 : o(std::move(s))
18882 , loc(std::localeconv())
18883 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18884 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18885 , indent_char(ichar)
18886 , indent_string(512, indent_char)
18887 , error_handler(error_handler_)
18888 {}
18889
18890 // deleted because of pointer members
18891 serializer(const serializer&) = delete;
18895 ~serializer() = default;
18896
18897 /*!
18898 @brief internal implementation of the serialization function
18899
18900 This function is called by the public member function dump and organizes
18901 the serialization internally. The indentation level is propagated as
18902 additional parameter. In case of arrays and objects, the function is
18903 called recursively.
18904
18905 - strings and object keys are escaped using `escape_string()`
18906 - integer numbers are converted implicitly via `operator<<`
18907 - floating-point numbers are converted to a string using `"%g"` format
18908 - binary values are serialized as objects containing the subtype and the
18909 byte array
18910
18911 @param[in] val value to serialize
18912 @param[in] pretty_print whether the output shall be pretty-printed
18913 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
18914 in the output are escaped with `\uXXXX` sequences, and the result consists
18915 of ASCII characters only.
18916 @param[in] indent_step the indent level
18917 @param[in] current_indent the current indent level (only used internally)
18918 */
18919 void dump(const BasicJsonType& val,
18920 const bool pretty_print,
18921 const bool ensure_ascii,
18922 const unsigned int indent_step,
18923 const unsigned int current_indent = 0)
18924 {
18925 switch (val.m_data.m_type)
18926 {
18927 case value_t::object:
18928 {
18929 if (val.m_data.m_value.object->empty())
18930 {
18931 o->write_characters("{}", 2);
18932 return;
18933 }
18934
18935 if (pretty_print)
18936 {
18937 o->write_characters("{\n", 2);
18938
18939 // variable to hold indentation for recursive calls
18940 const auto new_indent = current_indent + indent_step;
18941 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18942 {
18943 indent_string.resize(indent_string.size() * 2, ' ');
18944 }
18945
18946 // first n-1 elements
18947 auto i = val.m_data.m_value.object->cbegin();
18948 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18949 {
18950 o->write_characters(indent_string.c_str(), new_indent);
18951 o->write_character('\"');
18952 dump_escaped(i->first, ensure_ascii);
18953 o->write_characters("\": ", 3);
18954 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18955 o->write_characters(",\n", 2);
18956 }
18957
18958 // last element
18959 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18960 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18961 o->write_characters(indent_string.c_str(), new_indent);
18962 o->write_character('\"');
18963 dump_escaped(i->first, ensure_ascii);
18964 o->write_characters("\": ", 3);
18965 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18966
18967 o->write_character('\n');
18968 o->write_characters(indent_string.c_str(), current_indent);
18969 o->write_character('}');
18970 }
18971 else
18972 {
18973 o->write_character('{');
18974
18975 // first n-1 elements
18976 auto i = val.m_data.m_value.object->cbegin();
18977 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18978 {
18979 o->write_character('\"');
18980 dump_escaped(i->first, ensure_ascii);
18981 o->write_characters("\":", 2);
18982 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18983 o->write_character(',');
18984 }
18985
18986 // last element
18987 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18988 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18989 o->write_character('\"');
18990 dump_escaped(i->first, ensure_ascii);
18991 o->write_characters("\":", 2);
18992 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18993
18994 o->write_character('}');
18995 }
18996
18997 return;
18998 }
18999
19000 case value_t::array:
19001 {
19002 if (val.m_data.m_value.array->empty())
19003 {
19004 o->write_characters("[]", 2);
19005 return;
19006 }
19007
19008 if (pretty_print)
19009 {
19010 o->write_characters("[\n", 2);
19011
19012 // variable to hold indentation for recursive calls
19013 const auto new_indent = current_indent + indent_step;
19014 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
19015 {
19016 indent_string.resize(indent_string.size() * 2, ' ');
19017 }
19018
19019 // first n-1 elements
19020 for (auto i = val.m_data.m_value.array->cbegin();
19021 i != val.m_data.m_value.array->cend() - 1; ++i)
19022 {
19023 o->write_characters(indent_string.c_str(), new_indent);
19024 dump(*i, true, ensure_ascii, indent_step, new_indent);
19025 o->write_characters(",\n", 2);
19026 }
19027
19028 // last element
19029 JSON_ASSERT(!val.m_data.m_value.array->empty());
19030 o->write_characters(indent_string.c_str(), new_indent);
19031 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
19032
19033 o->write_character('\n');
19034 o->write_characters(indent_string.c_str(), current_indent);
19035 o->write_character(']');
19036 }
19037 else
19038 {
19039 o->write_character('[');
19040
19041 // first n-1 elements
19042 for (auto i = val.m_data.m_value.array->cbegin();
19043 i != val.m_data.m_value.array->cend() - 1; ++i)
19044 {
19045 dump(*i, false, ensure_ascii, indent_step, current_indent);
19046 o->write_character(',');
19047 }
19048
19049 // last element
19050 JSON_ASSERT(!val.m_data.m_value.array->empty());
19051 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
19052
19053 o->write_character(']');
19054 }
19055
19056 return;
19057 }
19058
19059 case value_t::string:
19060 {
19061 o->write_character('\"');
19062 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
19063 o->write_character('\"');
19064 return;
19065 }
19066
19067 case value_t::binary:
19068 {
19069 if (pretty_print)
19070 {
19071 o->write_characters("{\n", 2);
19072
19073 // variable to hold indentation for recursive calls
19074 const auto new_indent = current_indent + indent_step;
19075 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
19076 {
19077 indent_string.resize(indent_string.size() * 2, ' ');
19078 }
19079
19080 o->write_characters(indent_string.c_str(), new_indent);
19081
19082 o->write_characters("\"bytes\": [", 10);
19083
19084 if (!val.m_data.m_value.binary->empty())
19085 {
19086 for (auto i = val.m_data.m_value.binary->cbegin();
19087 i != val.m_data.m_value.binary->cend() - 1; ++i)
19088 {
19089 dump_integer(*i);
19090 o->write_characters(", ", 2);
19091 }
19092 dump_integer(val.m_data.m_value.binary->back());
19093 }
19094
19095 o->write_characters("],\n", 3);
19096 o->write_characters(indent_string.c_str(), new_indent);
19097
19098 o->write_characters("\"subtype\": ", 11);
19099 if (val.m_data.m_value.binary->has_subtype())
19100 {
19101 dump_integer(val.m_data.m_value.binary->subtype());
19102 }
19103 else
19104 {
19105 o->write_characters("null", 4);
19106 }
19107 o->write_character('\n');
19108 o->write_characters(indent_string.c_str(), current_indent);
19109 o->write_character('}');
19110 }
19111 else
19112 {
19113 o->write_characters("{\"bytes\":[", 10);
19114
19115 if (!val.m_data.m_value.binary->empty())
19116 {
19117 for (auto i = val.m_data.m_value.binary->cbegin();
19118 i != val.m_data.m_value.binary->cend() - 1; ++i)
19119 {
19120 dump_integer(*i);
19121 o->write_character(',');
19122 }
19123 dump_integer(val.m_data.m_value.binary->back());
19124 }
19125
19126 o->write_characters("],\"subtype\":", 12);
19127 if (val.m_data.m_value.binary->has_subtype())
19128 {
19129 dump_integer(val.m_data.m_value.binary->subtype());
19130 o->write_character('}');
19131 }
19132 else
19133 {
19134 o->write_characters("null}", 5);
19135 }
19136 }
19137 return;
19138 }
19139
19140 case value_t::boolean:
19141 {
19142 if (val.m_data.m_value.boolean)
19143 {
19144 o->write_characters("true", 4);
19145 }
19146 else
19147 {
19148 o->write_characters("false", 5);
19149 }
19150 return;
19151 }
19152
19153 case value_t::number_integer:
19154 {
19155 dump_integer(val.m_data.m_value.number_integer);
19156 return;
19157 }
19158
19159 case value_t::number_unsigned:
19160 {
19161 dump_integer(val.m_data.m_value.number_unsigned);
19162 return;
19163 }
19164
19165 case value_t::number_float:
19166 {
19167 dump_float(val.m_data.m_value.number_float);
19168 return;
19169 }
19170
19171 case value_t::discarded:
19172 {
19173 o->write_characters("<discarded>", 11);
19174 return;
19175 }
19176
19177 case value_t::null:
19178 {
19179 o->write_characters("null", 4);
19180 return;
19181 }
19182
19183 default: // LCOV_EXCL_LINE
19184 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19185 }
19186 }
19187
19189 /*!
19190 @brief dump escaped string
19191
19192 Escape a string by replacing certain special characters by a sequence of an
19193 escape character (backslash) and another character and other control
19194 characters by a sequence of "\u" followed by a four-digit hex
19195 representation. The escaped string is written to output stream @a o.
19196
19197 @param[in] s the string to escape
19198 @param[in] ensure_ascii whether to escape non-ASCII characters with
19199 \uXXXX sequences
19200
19201 @complexity Linear in the length of string @a s.
19202 */
19203 void dump_escaped(const string_t& s, const bool ensure_ascii)
19204 {
19205 std::uint32_t codepoint{};
19206 std::uint8_t state = UTF8_ACCEPT;
19207 std::size_t bytes = 0; // number of bytes written to string_buffer
19208
19209 // number of bytes written at the point of the last valid byte
19210 std::size_t bytes_after_last_accept = 0;
19211 std::size_t undumped_chars = 0;
19212
19213 for (std::size_t i = 0; i < s.size(); ++i)
19214 {
19215 const auto byte = static_cast<std::uint8_t>(s[i]);
19216
19217 switch (decode(state, codepoint, byte))
19218 {
19219 case UTF8_ACCEPT: // decode found a new code point
19220 {
19221 switch (codepoint)
19222 {
19223 case 0x08: // backspace
19224 {
19225 string_buffer[bytes++] = '\\';
19226 string_buffer[bytes++] = 'b';
19227 break;
19228 }
19229
19230 case 0x09: // horizontal tab
19231 {
19232 string_buffer[bytes++] = '\\';
19233 string_buffer[bytes++] = 't';
19234 break;
19235 }
19236
19237 case 0x0A: // newline
19238 {
19239 string_buffer[bytes++] = '\\';
19240 string_buffer[bytes++] = 'n';
19241 break;
19242 }
19243
19244 case 0x0C: // formfeed
19245 {
19246 string_buffer[bytes++] = '\\';
19247 string_buffer[bytes++] = 'f';
19248 break;
19249 }
19250
19251 case 0x0D: // carriage return
19252 {
19253 string_buffer[bytes++] = '\\';
19254 string_buffer[bytes++] = 'r';
19255 break;
19256 }
19257
19258 case 0x22: // quotation mark
19259 {
19260 string_buffer[bytes++] = '\\';
19261 string_buffer[bytes++] = '\"';
19262 break;
19263 }
19264
19265 case 0x5C: // reverse solidus
19266 {
19267 string_buffer[bytes++] = '\\';
19268 string_buffer[bytes++] = '\\';
19269 break;
19270 }
19271
19272 default:
19273 {
19274 // escape control characters (0x00..0x1F) or, if
19275 // ensure_ascii parameter is used, non-ASCII characters
19276 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
19277 {
19278 if (codepoint <= 0xFFFF)
19279 {
19280 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19281 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
19282 static_cast<std::uint16_t>(codepoint)));
19283 bytes += 6;
19284 }
19285 else
19286 {
19287 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19288 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
19289 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
19290 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
19291 bytes += 12;
19292 }
19293 }
19294 else
19295 {
19296 // copy byte to buffer (all previous bytes
19297 // been copied have in default case above)
19298 string_buffer[bytes++] = s[i];
19299 }
19300 break;
19301 }
19302 }
19303
19304 // write buffer and reset index; there must be 13 bytes
19305 // left, as this is the maximal number of bytes to be
19306 // written ("\uxxxx\uxxxx\0") for one code point
19307 if (string_buffer.size() - bytes < 13)
19308 {
19309 o->write_characters(string_buffer.data(), bytes);
19310 bytes = 0;
19311 }
19312
19313 // remember the byte position of this accept
19314 bytes_after_last_accept = bytes;
19315 undumped_chars = 0;
19316 break;
19317 }
19318
19319 case UTF8_REJECT: // decode found invalid UTF-8 byte
19320 {
19321 switch (error_handler)
19322 {
19323 case error_handler_t::strict:
19324 {
19325 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
19326 }
19327
19328 case error_handler_t::ignore:
19329 case error_handler_t::replace:
19330 {
19331 // in case we saw this character the first time, we
19332 // would like to read it again, because the byte
19333 // may be OK for itself, but just not OK for the
19334 // previous sequence
19335 if (undumped_chars > 0)
19336 {
19337 --i;
19338 }
19339
19340 // reset length buffer to the last accepted index;
19341 // thus removing/ignoring the invalid characters
19342 bytes = bytes_after_last_accept;
19343
19344 if (error_handler == error_handler_t::replace)
19345 {
19346 // add a replacement character
19347 if (ensure_ascii)
19348 {
19349 string_buffer[bytes++] = '\\';
19350 string_buffer[bytes++] = 'u';
19351 string_buffer[bytes++] = 'f';
19352 string_buffer[bytes++] = 'f';
19353 string_buffer[bytes++] = 'f';
19354 string_buffer[bytes++] = 'd';
19355 }
19356 else
19357 {
19358 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
19359 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
19360 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
19361 }
19362
19363 // write buffer and reset index; there must be 13 bytes
19364 // left, as this is the maximal number of bytes to be
19365 // written ("\uxxxx\uxxxx\0") for one code point
19366 if (string_buffer.size() - bytes < 13)
19367 {
19368 o->write_characters(string_buffer.data(), bytes);
19369 bytes = 0;
19370 }
19371
19372 bytes_after_last_accept = bytes;
19373 }
19374
19375 undumped_chars = 0;
19376
19377 // continue processing the string
19378 state = UTF8_ACCEPT;
19379 break;
19380 }
19381
19382 default: // LCOV_EXCL_LINE
19383 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19384 }
19385 break;
19386 }
19387
19388 default: // decode found yet incomplete multibyte code point
19389 {
19390 if (!ensure_ascii)
19391 {
19392 // code point will not be escaped - copy byte to buffer
19393 string_buffer[bytes++] = s[i];
19394 }
19395 ++undumped_chars;
19396 break;
19397 }
19398 }
19399 }
19400
19401 // we finished processing the string
19402 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
19403 {
19404 // write buffer
19405 if (bytes > 0)
19406 {
19407 o->write_characters(string_buffer.data(), bytes);
19408 }
19409 }
19410 else
19411 {
19412 // we finish reading, but do not accept: string was incomplete
19413 switch (error_handler)
19414 {
19415 case error_handler_t::strict:
19416 {
19417 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));
19418 }
19419
19420 case error_handler_t::ignore:
19421 {
19422 // write all accepted bytes
19423 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19424 break;
19425 }
19426
19427 case error_handler_t::replace:
19428 {
19429 // write all accepted bytes
19430 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19431 // add a replacement character
19432 if (ensure_ascii)
19433 {
19434 o->write_characters("\\ufffd", 6);
19435 }
19436 else
19437 {
19438 o->write_characters("\xEF\xBF\xBD", 3);
19439 }
19440 break;
19441 }
19442
19443 default: // LCOV_EXCL_LINE
19444 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19445 }
19446 }
19447 }
19448
19449 private:
19450 /*!
19451 @brief count digits
19452
19453 Count the number of decimal (base 10) digits for an input unsigned integer.
19454
19455 @param[in] x unsigned integer number to count its digits
19456 @return number of decimal digits
19457 */
19458 unsigned int count_digits(number_unsigned_t x) noexcept
19459 {
19460 unsigned int n_digits = 1;
19461 for (;;)
19462 {
19463 if (x < 10)
19464 {
19465 return n_digits;
19466 }
19467 if (x < 100)
19468 {
19469 return n_digits + 1;
19470 }
19471 if (x < 1000)
19472 {
19473 return n_digits + 2;
19474 }
19475 if (x < 10000)
19476 {
19477 return n_digits + 3;
19478 }
19479 x = x / 10000u;
19480 n_digits += 4;
19481 }
19482 }
19483
19484 /*!
19485 * @brief convert a byte to a uppercase hex representation
19486 * @param[in] byte byte to represent
19487 * @return representation ("00".."FF")
19488 */
19489 static std::string hex_bytes(std::uint8_t byte)
19490 {
19491 std::string result = "FF";
19492 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
19493 result[0] = nibble_to_hex[byte / 16];
19494 result[1] = nibble_to_hex[byte % 16];
19495 return result;
19496 }
19497
19498 // templates to avoid warnings about useless casts
19499 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
19500 bool is_negative_number(NumberType x)
19501 {
19502 return x < 0;
19503 }
19504
19505 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
19506 bool is_negative_number(NumberType /*unused*/)
19507 {
19508 return false;
19509 }
19510
19511 /*!
19512 @brief dump an integer
19513
19514 Dump a given integer to output stream @a o. Works internally with
19515 @a number_buffer.
19516
19517 @param[in] x integer number (signed or unsigned) to dump
19518 @tparam NumberType either @a number_integer_t or @a number_unsigned_t
19519 */
19520 template < typename NumberType, detail::enable_if_t <
19521 std::is_integral<NumberType>::value ||
19522 std::is_same<NumberType, number_unsigned_t>::value ||
19523 std::is_same<NumberType, number_integer_t>::value ||
19524 std::is_same<NumberType, binary_char_t>::value,
19525 int > = 0 >
19526 void dump_integer(NumberType x)
19527 {
19528 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
19529 {
19530 {
19531 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
19532 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
19533 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
19534 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
19535 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
19536 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
19537 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
19538 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
19539 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
19540 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
19541 }
19542 };
19543
19544 // special case for "0"
19545 if (x == 0)
19546 {
19547 o->write_character('0');
19548 return;
19549 }
19550
19551 // use a pointer to fill the buffer
19552 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19553
19554 number_unsigned_t abs_value;
19555
19556 unsigned int n_chars{};
19557
19558 if (is_negative_number(x))
19559 {
19560 *buffer_ptr = '-';
19561 abs_value = remove_sign(static_cast<number_integer_t>(x));
19562
19563 // account one more byte for the minus sign
19564 n_chars = 1 + count_digits(abs_value);
19565 }
19566 else
19567 {
19568 abs_value = static_cast<number_unsigned_t>(x);
19569 n_chars = count_digits(abs_value);
19570 }
19571
19572 // spare 1 byte for '\0'
19573 JSON_ASSERT(n_chars < number_buffer.size() - 1);
19574
19575 // jump to the end to generate the string from backward,
19576 // so we later avoid reversing the result
19577 buffer_ptr += static_cast<typename decltype(number_buffer)::difference_type>(n_chars);
19578
19579 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
19580 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
19581 while (abs_value >= 100)
19582 {
19583 const auto digits_index = static_cast<unsigned>((abs_value % 100));
19584 abs_value /= 100;
19585 *(--buffer_ptr) = digits_to_99[digits_index][1];
19586 *(--buffer_ptr) = digits_to_99[digits_index][0];
19587 }
19588
19589 if (abs_value >= 10)
19590 {
19591 const auto digits_index = static_cast<unsigned>(abs_value);
19592 *(--buffer_ptr) = digits_to_99[digits_index][1];
19593 *(--buffer_ptr) = digits_to_99[digits_index][0];
19594 }
19595 else
19596 {
19597 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
19598 }
19599
19600 o->write_characters(number_buffer.data(), n_chars);
19601 }
19602
19603 /*!
19604 @brief dump a floating-point number
19605
19606 Dump a given floating-point number to output stream @a o. Works internally
19607 with @a number_buffer.
19608
19609 @param[in] x floating-point number to dump
19610 */
19611 void dump_float(number_float_t x)
19612 {
19613 // NaN / inf
19614 if (!std::isfinite(x))
19615 {
19616 o->write_characters("null", 4);
19617 return;
19618 }
19619
19620 // If number_float_t is an IEEE-754 single or double precision number,
19621 // use the Grisu2 algorithm to produce short numbers which are
19622 // guaranteed to round-trip, using strtof and strtod, resp.
19623 //
19624 // NB: The test below works if <long double> == <double>.
19625 static constexpr bool is_ieee_single_or_double
19626 = (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) ||
19627 (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);
19628
19629 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
19630 }
19631
19632 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
19633 {
19634 auto* begin = number_buffer.data();
19635 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
19636
19637 o->write_characters(begin, static_cast<size_t>(end - begin));
19638 }
19639
19640 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
19641 {
19642 // get the number of digits for a float -> text -> float round-trip
19643 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
19644
19645 // the actual conversion
19646 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19647 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
19648
19649 // negative value indicates an error
19650 JSON_ASSERT(len > 0);
19651 // check if the buffer was large enough
19652 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
19653
19654 // erase thousands separators
19655 if (thousands_sep != '\0')
19656 {
19657 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
19658 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
19659 std::fill(end, number_buffer.end(), '\0');
19660 JSON_ASSERT((end - number_buffer.begin()) <= len);
19661 len = (end - number_buffer.begin());
19662 }
19663
19664 // convert decimal point to '.'
19665 if (decimal_point != '\0' && decimal_point != '.')
19666 {
19667 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
19668 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
19669 if (dec_pos != number_buffer.end())
19670 {
19671 *dec_pos = '.';
19672 }
19673 }
19674
19675 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
19676
19677 // determine if we need to append ".0"
19678 const bool value_is_int_like =
19679 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
19680 [](char c)
19681 {
19682 return c == '.' || c == 'e';
19683 });
19684
19685 if (value_is_int_like)
19686 {
19687 o->write_characters(".0", 2);
19688 }
19689 }
19690
19691 /*!
19692 @brief check whether a string is UTF-8 encoded
19693
19694 The function checks each byte of a string whether it is UTF-8 encoded. The
19695 result of the check is stored in the @a state parameter. The function must
19696 be called initially with state 0 (accept). State 1 means the string must
19697 be rejected, because the current byte is not allowed. If the string is
19698 completely processed, but the state is non-zero, the string ended
19699 prematurely; that is, the last byte indicated more bytes should have
19700 followed.
19701
19702 @param[in,out] state the state of the decoding
19703 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
19704 @param[in] byte next byte to decode
19705 @return new state
19706
19707 @note The function has been edited: a std::array is used.
19708
19709 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
19710 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
19711 */
19712 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
19713 {
19714 static const std::array<std::uint8_t, 400> utf8d =
19715 {
19716 {
19717 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
19718 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
19719 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
19720 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
19721 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
19722 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
19723 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
19724 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
19725 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
19726 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
19727 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
19728 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
19729 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
19730 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
19731 }
19732 };
19733
19734 JSON_ASSERT(byte < utf8d.size());
19735 const std::uint8_t type = utf8d[byte];
19736
19737 codep = (state != UTF8_ACCEPT)
19738 ? (byte & 0x3fu) | (codep << 6u)
19739 : (0xFFu >> type) & (byte);
19740
19741 const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
19742 JSON_ASSERT(index < utf8d.size());
19743 state = utf8d[index];
19744 return state;
19745 }
19746
19747 /*
19748 * Overload to make the compiler happy while it is instantiating
19749 * dump_integer for number_unsigned_t.
19750 * Must never be called.
19751 */
19752 number_unsigned_t remove_sign(number_unsigned_t x)
19753 {
19754 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19755 return x; // LCOV_EXCL_LINE
19756 }
19757
19758 /*
19759 * Helper function for dump_integer
19760 *
19761 * This function takes a negative signed integer and returns its absolute
19762 * value as an unsigned integer. The plus/minus shuffling is necessary as we
19763 * cannot directly remove the sign of an arbitrary signed integer as the
19764 * absolute values of INT_MIN and INT_MAX are usually not the same. See
19765 * #1708 for details.
19766 */
19767 number_unsigned_t remove_sign(number_integer_t x) noexcept
19768 {
19769 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
19770 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
19771 }
19772
19773 private:
19774 /// the output of the serializer
19775 output_adapter_t<char> o = nullptr;
19776
19777 /// a (hopefully) large enough character buffer
19778 std::array<char, 64> number_buffer{{}};
19779
19780 /// the locale
19781 const std::lconv* loc = nullptr;
19782 /// the locale's thousand separator character
19783 const char thousands_sep = '\0';
19784 /// the locale's decimal point character
19785 const char decimal_point = '\0';
19786
19787 /// string buffer
19788 std::array<char, 512> string_buffer{{}};
19789
19790 /// the indentation character
19791 const char indent_char;
19792 /// the indentation string
19794
19795 /// error_handler how to react on decoding errors
19797};
19798
19799} // namespace detail
19801
19802// #include <nlohmann/detail/value_t.hpp>
19803
19804// #include <nlohmann/json_fwd.hpp>
19805
19806// #include <nlohmann/ordered_map.hpp>
19807// __ _____ _____ _____
19808// __| | __| | | | JSON for Modern C++
19809// | | |__ | | | | | | version 3.12.0
19810// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19811//
19812// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
19813// SPDX-License-Identifier: MIT
19814
19815
19816
19817#include <functional> // equal_to, less
19818#include <initializer_list> // initializer_list
19819#include <iterator> // input_iterator_tag, iterator_traits
19820#include <memory> // allocator
19821#include <stdexcept> // for out_of_range
19822#include <type_traits> // enable_if, is_convertible
19823#include <utility> // pair
19824#include <vector> // vector
19825
19826// #include <nlohmann/detail/macro_scope.hpp>
19827
19828// #include <nlohmann/detail/meta/type_traits.hpp>
19829
19830
19832
19833/// ordered_map: a minimal map-like container that preserves insertion order
19834/// for use within nlohmann::basic_json<ordered_map>
19835template <class Key, class T, class IgnoredLess = std::less<Key>,
19836 class Allocator = std::allocator<std::pair<const Key, T>>>
19837 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19838{
19839 using key_type = Key;
19840 using mapped_type = T;
19841 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19842 using iterator = typename Container::iterator;
19843 using const_iterator = typename Container::const_iterator;
19844 using size_type = typename Container::size_type;
19845 using value_type = typename Container::value_type;
19846#ifdef JSON_HAS_CPP_14
19847 using key_compare = std::equal_to<>;
19848#else
19849 using key_compare = std::equal_to<Key>;
19850#endif
19851
19852 // Explicit constructors instead of `using Container::Container`
19853 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19854 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19855 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19856 template <class It>
19857 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19858 : Container{first, last, alloc} {}
19859 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19860 : Container{init, alloc} {}
19861
19862 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19863 {
19864 for (auto it = this->begin(); it != this->end(); ++it)
19865 {
19866 if (m_compare(it->first, key))
19867 {
19868 return {it, false};
19869 }
19870 }
19871 Container::emplace_back(key, std::forward<T>(t));
19872 return {std::prev(this->end()), true};
19873 }
19874
19875 template<class KeyType, detail::enable_if_t<
19877 std::pair<iterator, bool> emplace(KeyType && key, T && t)
19878 {
19879 for (auto it = this->begin(); it != this->end(); ++it)
19880 {
19881 if (m_compare(it->first, key))
19882 {
19883 return {it, false};
19884 }
19885 }
19886 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19887 return {std::prev(this->end()), true};
19888 }
19889
19890 T& operator[](const key_type& key)
19891 {
19892 return emplace(key, T{}).first->second;
19893 }
19894
19895 template<class KeyType, detail::enable_if_t<
19897 T & operator[](KeyType && key)
19898 {
19899 return emplace(std::forward<KeyType>(key), T{}).first->second;
19900 }
19901
19902 const T& operator[](const key_type& key) const
19903 {
19904 return at(key);
19905 }
19906
19907 template<class KeyType, detail::enable_if_t<
19909 const T & operator[](KeyType && key) const
19910 {
19911 return at(std::forward<KeyType>(key));
19912 }
19913
19914 T& at(const key_type& key)
19915 {
19916 for (auto it = this->begin(); it != this->end(); ++it)
19917 {
19918 if (m_compare(it->first, key))
19919 {
19920 return it->second;
19921 }
19922 }
19923
19924 JSON_THROW(std::out_of_range("key not found"));
19925 }
19926
19927 template<class KeyType, detail::enable_if_t<
19929 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19930 {
19931 for (auto it = this->begin(); it != this->end(); ++it)
19932 {
19933 if (m_compare(it->first, key))
19934 {
19935 return it->second;
19936 }
19937 }
19938
19939 JSON_THROW(std::out_of_range("key not found"));
19940 }
19941
19942 const T& at(const key_type& key) const
19943 {
19944 for (auto it = this->begin(); it != this->end(); ++it)
19945 {
19946 if (m_compare(it->first, key))
19947 {
19948 return it->second;
19949 }
19950 }
19951
19952 JSON_THROW(std::out_of_range("key not found"));
19953 }
19954
19955 template<class KeyType, detail::enable_if_t<
19957 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19958 {
19959 for (auto it = this->begin(); it != this->end(); ++it)
19960 {
19961 if (m_compare(it->first, key))
19962 {
19963 return it->second;
19964 }
19965 }
19966
19967 JSON_THROW(std::out_of_range("key not found"));
19968 }
19969
19971 {
19972 for (auto it = this->begin(); it != this->end(); ++it)
19973 {
19974 if (m_compare(it->first, key))
19975 {
19976 // Since we cannot move const Keys, re-construct them in place
19977 for (auto next = it; ++next != this->end(); ++it)
19978 {
19979 it->~value_type(); // Destroy but keep allocation
19980 new (&*it) value_type{std::move(*next)};
19981 }
19982 Container::pop_back();
19983 return 1;
19984 }
19985 }
19986 return 0;
19987 }
19988
19989 template<class KeyType, detail::enable_if_t<
19991 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19992 {
19993 for (auto it = this->begin(); it != this->end(); ++it)
19994 {
19995 if (m_compare(it->first, key))
19996 {
19997 // Since we cannot move const Keys, re-construct them in place
19998 for (auto next = it; ++next != this->end(); ++it)
19999 {
20000 it->~value_type(); // Destroy but keep allocation
20001 new (&*it) value_type{std::move(*next)};
20002 }
20003 Container::pop_back();
20004 return 1;
20005 }
20006 }
20007 return 0;
20008 }
20009
20011 {
20012 return erase(pos, std::next(pos));
20013 }
20014
20016 {
20017 if (first == last)
20018 {
20019 return first;
20020 }
20021
20022 const auto elements_affected = std::distance(first, last);
20023 const auto offset = std::distance(Container::begin(), first);
20024
20025 // This is the start situation. We need to delete elements_affected
20026 // elements (3 in this example: e, f, g), and need to return an
20027 // iterator past the last deleted element (h in this example).
20028 // Note that offset is the distance from the start of the vector
20029 // to first. We will need this later.
20030
20031 // [ a, b, c, d, e, f, g, h, i, j ]
20032 // ^ ^
20033 // first last
20034
20035 // Since we cannot move const Keys, we re-construct them in place.
20036 // We start at first and re-construct (viz. copy) the elements from
20037 // the back of the vector. Example for the first iteration:
20038
20039 // ,--------.
20040 // v | destroy e and re-construct with h
20041 // [ a, b, c, d, e, f, g, h, i, j ]
20042 // ^ ^
20043 // it it + elements_affected
20044
20045 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
20046 {
20047 it->~value_type(); // destroy but keep allocation
20048 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
20049 }
20050
20051 // [ a, b, c, d, h, i, j, h, i, j ]
20052 // ^ ^
20053 // first last
20054
20055 // remove the unneeded elements at the end of the vector
20056 Container::resize(this->size() - static_cast<size_type>(elements_affected));
20057
20058 // [ a, b, c, d, h, i, j ]
20059 // ^ ^
20060 // first last
20061
20062 // first is now pointing past the last deleted element, but we cannot
20063 // use this iterator, because it may have been invalidated by the
20064 // resize call. Instead, we can return begin() + offset.
20065 return Container::begin() + offset;
20066 }
20067
20068 size_type count(const key_type& key) const
20069 {
20070 for (auto it = this->begin(); it != this->end(); ++it)
20071 {
20072 if (m_compare(it->first, key))
20073 {
20074 return 1;
20075 }
20076 }
20077 return 0;
20078 }
20079
20080 template<class KeyType, detail::enable_if_t<
20082 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
20083 {
20084 for (auto it = this->begin(); it != this->end(); ++it)
20085 {
20086 if (m_compare(it->first, key))
20087 {
20088 return 1;
20089 }
20090 }
20091 return 0;
20092 }
20093
20095 {
20096 for (auto it = this->begin(); it != this->end(); ++it)
20097 {
20098 if (m_compare(it->first, key))
20099 {
20100 return it;
20101 }
20102 }
20103 return Container::end();
20104 }
20105
20106 template<class KeyType, detail::enable_if_t<
20108 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
20109 {
20110 for (auto it = this->begin(); it != this->end(); ++it)
20111 {
20112 if (m_compare(it->first, key))
20113 {
20114 return it;
20115 }
20116 }
20117 return Container::end();
20118 }
20119
20120 const_iterator find(const key_type& key) const
20121 {
20122 for (auto it = this->begin(); it != this->end(); ++it)
20123 {
20124 if (m_compare(it->first, key))
20125 {
20126 return it;
20127 }
20128 }
20129 return Container::end();
20130 }
20131
20132 std::pair<iterator, bool> insert( value_type&& value )
20133 {
20134 return emplace(value.first, std::move(value.second));
20135 }
20136
20137 std::pair<iterator, bool> insert( const value_type& value )
20138 {
20139 for (auto it = this->begin(); it != this->end(); ++it)
20140 {
20141 if (m_compare(it->first, value.first))
20142 {
20143 return {it, false};
20144 }
20145 }
20146 Container::push_back(value);
20147 return {--this->end(), true};
20148 }
20149
20150 template<typename InputIt>
20151 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
20152 std::input_iterator_tag>::value>::type;
20153
20154 template<typename InputIt, typename = require_input_iter<InputIt>>
20155 void insert(InputIt first, InputIt last)
20156 {
20157 for (auto it = first; it != last; ++it)
20158 {
20159 insert(*it);
20160 }
20161 }
20162
20163private:
20165};
20166
20168
20169
20170#if defined(JSON_HAS_CPP_17)
20171 #if JSON_HAS_STATIC_RTTI
20172 #include <any>
20173 #endif
20174 #include <string_view>
20175#endif
20176
20177/*!
20178@brief namespace for Niels Lohmann
20179@see https://github.com/nlohmann
20180@since version 1.0.0
20181*/
20183
20184/*!
20185@brief a class to store JSON values
20186
20187@internal
20188@invariant The member variables @a m_value and @a m_type have the following
20189relationship:
20190- If `m_type == value_t::object`, then `m_value.object != nullptr`.
20191- If `m_type == value_t::array`, then `m_value.array != nullptr`.
20192- If `m_type == value_t::string`, then `m_value.string != nullptr`.
20193The invariants are checked by member function assert_invariant().
20194
20195@note ObjectType trick from https://stackoverflow.com/a/9860911
20196@endinternal
20197
20198@since version 1.0.0
20199
20200@nosubgrouping
20201*/
20203class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
20204 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
20205{
20206 private:
20207 template<detail::value_t> friend struct detail::external_constructor;
20208
20209 template<typename>
20210 friend class ::nlohmann::json_pointer;
20211 // can be restored when json_pointer backwards compatibility is removed
20212 // friend ::nlohmann::json_pointer<StringType>;
20213
20214 template<typename BasicJsonType, typename InputType>
20215 friend class ::nlohmann::detail::parser;
20216 friend ::nlohmann::detail::serializer<basic_json>;
20217 template<typename BasicJsonType>
20218 friend class ::nlohmann::detail::iter_impl;
20219 template<typename BasicJsonType, typename CharType>
20220 friend class ::nlohmann::detail::binary_writer;
20221 template<typename BasicJsonType, typename InputType, typename SAX>
20222 friend class ::nlohmann::detail::binary_reader;
20223 template<typename BasicJsonType, typename InputAdapterType>
20224 friend class ::nlohmann::detail::json_sax_dom_parser;
20225 template<typename BasicJsonType, typename InputAdapterType>
20226 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
20227 friend class ::nlohmann::detail::exception;
20228
20229 /// workaround type for MSVC
20231 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
20232
20234 // convenience aliases for types residing in namespace detail;
20235 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
20236
20237 template<typename InputAdapterType>
20238 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
20239 InputAdapterType adapter,
20241 const bool allow_exceptions = true,
20242 const bool ignore_comments = false,
20243 const bool ignore_trailing_commas = false
20244 )
20245 {
20246 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
20247 std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
20248 }
20249
20250 private:
20251 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
20252 template<typename BasicJsonType>
20253 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
20254 template<typename BasicJsonType>
20255 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
20256 template<typename Iterator>
20257 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
20258 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
20259
20260 template<typename CharType>
20261 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
20262
20263 template<typename InputType>
20264 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
20265 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
20266
20268 using serializer = ::nlohmann::detail::serializer<basic_json>;
20269
20270 public:
20272 /// JSON Pointer, see @ref nlohmann::json_pointer
20273 using json_pointer = ::nlohmann::json_pointer<StringType>;
20274 template<typename T, typename SFINAE>
20275 using json_serializer = JSONSerializer<T, SFINAE>;
20276 /// how to treat decoding errors
20278 /// how to treat CBOR tags
20280 /// how to encode BJData
20282 /// helper type for initializer lists of basic_json values
20283 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
20284
20286 /// SAX interface type, see @ref nlohmann::json_sax
20288
20289 ////////////////
20290 // exceptions //
20291 ////////////////
20292
20293 /// @name exceptions
20294 /// Classes to implement user-defined exceptions.
20295 /// @{
20296
20303
20304 /// @}
20305
20306 /////////////////////
20307 // container types //
20308 /////////////////////
20309
20310 /// @name container types
20311 /// The canonic container types to use @ref basic_json like any other STL
20312 /// container.
20313 /// @{
20314
20315 /// the type of elements in a basic_json container
20317
20318 /// the type of an element reference
20320 /// the type of an element const reference
20322
20323 /// a type to represent differences between iterators
20324 using difference_type = std::ptrdiff_t;
20325 /// a type to represent container sizes
20326 using size_type = std::size_t;
20327
20328 /// the allocator type
20329 using allocator_type = AllocatorType<basic_json>;
20330
20331 /// the type of an element pointer
20332 using pointer = typename std::allocator_traits<allocator_type>::pointer;
20333 /// the type of an element const pointer
20334 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
20335
20336 /// an iterator for a basic_json container
20338 /// a const iterator for a basic_json container
20340 /// a reverse iterator for a basic_json container
20342 /// a const reverse iterator for a basic_json container
20344
20345 /// @}
20346
20347 /// @brief returns the allocator associated with the container
20348 /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
20350 {
20351 return allocator_type();
20352 }
20353
20354 /// @brief returns version information on the library
20355 /// @sa https://json.nlohmann.me/api/basic_json/meta/
20358 {
20359 basic_json result;
20360
20361 result["copyright"] = "(C) 2013-2025 Niels Lohmann";
20362 result["name"] = "JSON for Modern C++";
20363 result["url"] = "https://github.com/nlohmann/json";
20364 result["version"]["string"] =
20365 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
20366 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
20367 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
20368 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
20369 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
20370 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
20371
20372#ifdef _WIN32
20373 result["platform"] = "win32";
20374#elif defined __linux__
20375 result["platform"] = "linux";
20376#elif defined __APPLE__
20377 result["platform"] = "apple";
20378#elif defined __unix__
20379 result["platform"] = "unix";
20380#else
20381 result["platform"] = "unknown";
20382#endif
20383
20384#if defined(__ICC) || defined(__INTEL_COMPILER)
20385 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
20386#elif defined(__clang__)
20387 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
20388#elif defined(__GNUC__) || defined(__GNUG__)
20389 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
20390 std::to_string(__GNUC__), '.',
20391 std::to_string(__GNUC_MINOR__), '.',
20392 std::to_string(__GNUC_PATCHLEVEL__))
20393 }
20394 };
20395#elif defined(__HP_cc) || defined(__HP_aCC)
20396 result["compiler"] = "hp"
20397#elif defined(__IBMCPP__)
20398 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
20399#elif defined(_MSC_VER)
20400 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
20401#elif defined(__PGI)
20402 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
20403#elif defined(__SUNPRO_CC)
20404 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
20405#else
20406 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
20407#endif
20408
20409#if defined(_MSVC_LANG)
20410 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
20411#elif defined(__cplusplus)
20412 result["compiler"]["c++"] = std::to_string(__cplusplus);
20413#else
20414 result["compiler"]["c++"] = "unknown";
20415#endif
20416 return result;
20417 }
20418
20419 ///////////////////////////
20420 // JSON value data types //
20421 ///////////////////////////
20422
20423 /// @name JSON value data types
20424 /// The data types to store a JSON value. These types are derived from
20425 /// the template arguments passed to class @ref basic_json.
20426 /// @{
20427
20428 /// @brief default object key comparator type
20429 /// The actual object key comparator type (@ref object_comparator_t) may be
20430 /// different.
20431 /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
20432#if defined(JSON_HAS_CPP_14)
20433 // use of transparent comparator avoids unnecessary repeated construction of temporaries
20434 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
20435 using default_object_comparator_t = std::less<>;
20436#else
20437 using default_object_comparator_t = std::less<StringType>;
20438#endif
20439
20440 /// @brief a type for an object
20441 /// @sa https://json.nlohmann.me/api/basic_json/object_t/
20442 using object_t = ObjectType<StringType,
20443 basic_json,
20445 AllocatorType<std::pair<const StringType,
20446 basic_json>>>;
20447
20448 /// @brief a type for an array
20449 /// @sa https://json.nlohmann.me/api/basic_json/array_t/
20450 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
20451
20452 /// @brief a type for a string
20453 /// @sa https://json.nlohmann.me/api/basic_json/string_t/
20454 using string_t = StringType;
20455
20456 /// @brief a type for a boolean
20457 /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
20458 using boolean_t = BooleanType;
20459
20460 /// @brief a type for a number (integer)
20461 /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
20462 using number_integer_t = NumberIntegerType;
20463
20464 /// @brief a type for a number (unsigned)
20465 /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
20466 using number_unsigned_t = NumberUnsignedType;
20467
20468 /// @brief a type for a number (floating-point)
20469 /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
20470 using number_float_t = NumberFloatType;
20471
20472 /// @brief a type for a packed binary type
20473 /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
20474 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
20475
20476 /// @brief object key comparator type
20477 /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
20479
20480 /// @}
20481
20482 private:
20483
20484 /// helper for exception-safe object creation
20485 template<typename T, typename... Args>
20487 static T* create(Args&& ... args)
20488 {
20489 AllocatorType<T> alloc;
20490 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
20491
20492 auto deleter = [&](T * obj)
20493 {
20494 AllocatorTraits::deallocate(alloc, obj, 1);
20495 };
20496 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
20497 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
20498 JSON_ASSERT(obj != nullptr);
20499 return obj.release();
20500 }
20501
20502 ////////////////////////
20503 // JSON value storage //
20504 ////////////////////////
20505
20507 /*!
20508 @brief a JSON value
20509
20510 The actual storage for a JSON value of the @ref basic_json class. This
20511 union combines the different storage types for the JSON value types
20512 defined in @ref value_t.
20513
20514 JSON type | value_t type | used type
20515 --------- | --------------- | ------------------------
20516 object | object | pointer to @ref object_t
20517 array | array | pointer to @ref array_t
20518 string | string | pointer to @ref string_t
20519 boolean | boolean | @ref boolean_t
20520 number | number_integer | @ref number_integer_t
20521 number | number_unsigned | @ref number_unsigned_t
20522 number | number_float | @ref number_float_t
20523 binary | binary | pointer to @ref binary_t
20524 null | null | *no value is stored*
20525
20526 @note Variable-length types (objects, arrays, and strings) are stored as
20527 pointers. The size of the union should not exceed 64 bits if the default
20528 value types are used.
20529
20530 @since version 1.0.0
20531 */
20532 union json_value
20533 {
20534 /// object (stored with pointer to save storage)
20536 /// array (stored with pointer to save storage)
20538 /// string (stored with pointer to save storage)
20540 /// binary (stored with pointer to save storage)
20542 /// boolean
20544 /// number (integer)
20546 /// number (unsigned integer)
20548 /// number (floating-point)
20550
20551 /// default constructor (for null values)
20552 json_value() = default;
20553 /// constructor for booleans
20554 json_value(boolean_t v) noexcept : boolean(v) {}
20555 /// constructor for numbers (integer)
20556 json_value(number_integer_t v) noexcept : number_integer(v) {}
20557 /// constructor for numbers (unsigned)
20558 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
20559 /// constructor for numbers (floating-point)
20560 json_value(number_float_t v) noexcept : number_float(v) {}
20561 /// constructor for empty values of a given type
20563 {
20564 switch (t)
20565 {
20566 case value_t::object:
20567 {
20568 object = create<object_t>();
20569 break;
20570 }
20571
20572 case value_t::array:
20573 {
20574 array = create<array_t>();
20575 break;
20576 }
20577
20578 case value_t::string:
20579 {
20580 string = create<string_t>("");
20581 break;
20582 }
20583
20584 case value_t::binary:
20585 {
20586 binary = create<binary_t>();
20587 break;
20588 }
20589
20590 case value_t::boolean:
20591 {
20592 boolean = static_cast<boolean_t>(false);
20593 break;
20594 }
20595
20596 case value_t::number_integer:
20597 {
20598 number_integer = static_cast<number_integer_t>(0);
20599 break;
20600 }
20601
20602 case value_t::number_unsigned:
20603 {
20604 number_unsigned = static_cast<number_unsigned_t>(0);
20605 break;
20606 }
20607
20608 case value_t::number_float:
20609 {
20610 number_float = static_cast<number_float_t>(0.0);
20611 break;
20612 }
20613
20614 case value_t::null:
20615 {
20616 object = nullptr; // silence warning, see #821
20617 break;
20618 }
20619
20620 case value_t::discarded:
20621 default:
20622 {
20623 object = nullptr; // silence warning, see #821
20624 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
20625 {
20626 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.12.0", nullptr)); // LCOV_EXCL_LINE
20627 }
20628 break;
20629 }
20630 }
20631 }
20632
20633 /// constructor for strings
20634 json_value(const string_t& value) : string(create<string_t>(value)) {}
20635
20636 /// constructor for rvalue strings
20637 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
20638
20639 /// constructor for objects
20640 json_value(const object_t& value) : object(create<object_t>(value)) {}
20641
20642 /// constructor for rvalue objects
20643 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
20644
20645 /// constructor for arrays
20646 json_value(const array_t& value) : array(create<array_t>(value)) {}
20647
20648 /// constructor for rvalue arrays
20649 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
20650
20651 /// constructor for binary arrays
20652 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
20653
20654 /// constructor for rvalue binary arrays
20655 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
20656
20657 /// constructor for binary arrays (internal type)
20658 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
20659
20660 /// constructor for rvalue binary arrays (internal type)
20661 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
20662
20664 {
20665 if (
20666 (t == value_t::object && object == nullptr) ||
20667 (t == value_t::array && array == nullptr) ||
20668 (t == value_t::string && string == nullptr) ||
20669 (t == value_t::binary && binary == nullptr)
20670 )
20671 {
20672 // not initialized (e.g., due to exception in the ctor)
20673 return;
20674 }
20675 if (t == value_t::array || t == value_t::object)
20676 {
20677 // flatten the current json_value to a heap-allocated stack
20678 std::vector<basic_json> stack;
20679
20680 // move the top-level items to stack
20681 if (t == value_t::array)
20682 {
20683 stack.reserve(array->size());
20684 std::move(array->begin(), array->end(), std::back_inserter(stack));
20685 }
20686 else
20687 {
20688 stack.reserve(object->size());
20689 for (auto&& it : *object)
20690 {
20691 stack.push_back(std::move(it.second));
20692 }
20693 }
20694
20695 while (!stack.empty())
20696 {
20697 // move the last item to a local variable to be processed
20698 basic_json current_item(std::move(stack.back()));
20699 stack.pop_back();
20700
20701 // if current_item is array/object, move
20702 // its children to the stack to be processed later
20703 if (current_item.is_array())
20704 {
20705 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
20706
20707 current_item.m_data.m_value.array->clear();
20708 }
20709 else if (current_item.is_object())
20710 {
20711 for (auto&& it : *current_item.m_data.m_value.object)
20712 {
20713 stack.push_back(std::move(it.second));
20714 }
20715
20716 current_item.m_data.m_value.object->clear();
20717 }
20718
20719 // it's now safe that current_item gets destructed
20720 // since it doesn't have any children
20721 }
20722 }
20723
20724 switch (t)
20725 {
20726 case value_t::object:
20727 {
20728 AllocatorType<object_t> alloc;
20729 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
20730 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
20731 break;
20732 }
20733
20734 case value_t::array:
20735 {
20736 AllocatorType<array_t> alloc;
20737 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
20738 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
20739 break;
20740 }
20741
20742 case value_t::string:
20743 {
20744 AllocatorType<string_t> alloc;
20745 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
20746 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
20747 break;
20748 }
20749
20750 case value_t::binary:
20751 {
20752 AllocatorType<binary_t> alloc;
20753 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
20754 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
20755 break;
20756 }
20757
20758 case value_t::null:
20759 case value_t::boolean:
20760 case value_t::number_integer:
20761 case value_t::number_unsigned:
20762 case value_t::number_float:
20763 case value_t::discarded:
20764 default:
20765 {
20766 break;
20767 }
20768 }
20769 }
20770 };
20771
20772 private:
20773 /*!
20774 @brief checks the class invariants
20775
20776 This function asserts the class invariants. It needs to be called at the
20777 end of every constructor to make sure that created objects respect the
20778 invariant. Furthermore, it has to be called each time the type of a JSON
20779 value is changed, because the invariant expresses a relationship between
20780 @a m_type and @a m_value.
20781
20782 Furthermore, the parent relation is checked for arrays and objects: If
20783 @a check_parents true and the value is an array or object, then the
20784 container's elements must have the current value as parent.
20785
20786 @param[in] check_parents whether the parent relation should be checked.
20787 The value is true by default and should only be set to false
20788 during destruction of objects when the invariant does not
20789 need to hold.
20790 */
20791 void assert_invariant(bool check_parents = true) const noexcept
20792 {
20793 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20794 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20795 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20796 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20797
20798#if JSON_DIAGNOSTICS
20799 JSON_TRY
20800 {
20801 // cppcheck-suppress assertWithSideEffect
20802 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20803 {
20804 return j.m_parent == this;
20805 }));
20806 }
20807 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20808#endif
20809 static_cast<void>(check_parents);
20810 }
20811
20813 {
20814#if JSON_DIAGNOSTICS
20815 switch (m_data.m_type)
20816 {
20817 case value_t::array:
20818 {
20819 for (auto& element : *m_data.m_value.array)
20820 {
20821 element.m_parent = this;
20822 }
20823 break;
20824 }
20825
20826 case value_t::object:
20827 {
20828 for (auto& element : *m_data.m_value.object)
20829 {
20830 element.second.m_parent = this;
20831 }
20832 break;
20833 }
20834
20835 case value_t::null:
20836 case value_t::string:
20837 case value_t::boolean:
20838 case value_t::number_integer:
20839 case value_t::number_unsigned:
20840 case value_t::number_float:
20841 case value_t::binary:
20842 case value_t::discarded:
20843 default:
20844 break;
20845 }
20846#endif
20847 }
20848
20849 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20850 {
20851#if JSON_DIAGNOSTICS
20852 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20853 {
20854 (it + i)->m_parent = this;
20855 }
20856#else
20857 static_cast<void>(count_set_parents);
20858#endif
20859 return it;
20860 }
20861
20862 reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size())
20863 {
20864#if JSON_DIAGNOSTICS
20865 if (old_capacity != detail::unknown_size())
20866 {
20867 // see https://github.com/nlohmann/json/issues/2838
20868 JSON_ASSERT(type() == value_t::array);
20869 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20870 {
20871 // capacity has changed: update all parents
20872 set_parents();
20873 return j;
20874 }
20875 }
20876
20877 // ordered_json uses a vector internally, so pointers could have
20878 // been invalidated; see https://github.com/nlohmann/json/issues/2962
20879#ifdef JSON_HEDLEY_MSVC_VERSION
20880#pragma warning(push )
20881#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20882#endif
20884 {
20885 set_parents();
20886 return j;
20887 }
20888#ifdef JSON_HEDLEY_MSVC_VERSION
20889#pragma warning( pop )
20890#endif
20891
20892 j.m_parent = this;
20893#else
20894 static_cast<void>(j);
20895 static_cast<void>(old_capacity);
20896#endif
20897 return j;
20898 }
20899
20900 public:
20901 //////////////////////////
20902 // JSON parser callback //
20903 //////////////////////////
20904
20905 /// @brief parser event types
20906 /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
20908
20909 /// @brief per-element parser callback type
20910 /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
20912
20913 //////////////////
20914 // constructors //
20915 //////////////////
20916
20917 /// @name constructors and destructors
20918 /// Constructors of class @ref basic_json, copy/move constructor, copy
20919 /// assignment, static functions creating objects, and the destructor.
20920 /// @{
20921
20922 /// @brief create an empty value with a given type
20923 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20925 : m_data(v)
20926 {
20927 assert_invariant();
20928 }
20929
20930 /// @brief create a null object
20931 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20932 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20933 : basic_json(value_t::null)
20934 {
20935 assert_invariant();
20936 }
20937
20938 /// @brief create a JSON value from compatible types
20939 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20940 template < typename CompatibleType,
20944 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20945 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20946 std::forward<CompatibleType>(val))))
20947 {
20948 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20949 set_parents();
20950 assert_invariant();
20951 }
20952
20953 /// @brief create a JSON value from an existing one
20954 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20955 template < typename BasicJsonType,
20957 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20958 basic_json(const BasicJsonType& val)
20959#if JSON_DIAGNOSTIC_POSITIONS
20960 : start_position(val.start_pos()),
20961 end_position(val.end_pos())
20962#endif
20963 {
20964 using other_boolean_t = typename BasicJsonType::boolean_t;
20965 using other_number_float_t = typename BasicJsonType::number_float_t;
20966 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20967 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20968 using other_string_t = typename BasicJsonType::string_t;
20969 using other_object_t = typename BasicJsonType::object_t;
20970 using other_array_t = typename BasicJsonType::array_t;
20971 using other_binary_t = typename BasicJsonType::binary_t;
20972
20973 switch (val.type())
20974 {
20975 case value_t::boolean:
20976 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20977 break;
20978 case value_t::number_float:
20979 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20980 break;
20981 case value_t::number_integer:
20982 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20983 break;
20984 case value_t::number_unsigned:
20985 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20986 break;
20987 case value_t::string:
20988 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20989 break;
20990 case value_t::object:
20991 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20992 break;
20993 case value_t::array:
20994 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20995 break;
20996 case value_t::binary:
20997 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20998 break;
20999 case value_t::null:
21000 *this = nullptr;
21001 break;
21002 case value_t::discarded:
21003 m_data.m_type = value_t::discarded;
21004 break;
21005 default: // LCOV_EXCL_LINE
21006 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
21007 }
21008 JSON_ASSERT(m_data.m_type == val.type());
21009
21010 set_parents();
21011 assert_invariant();
21012 }
21013
21014 /// @brief create a container (array or object) from an initializer list
21015 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
21017 bool type_deduction = true,
21018 value_t manual_type = value_t::array)
21019 {
21020 // check if each element is an array with two elements whose first
21021 // element is a string
21022 bool is_an_object = std::all_of(init.begin(), init.end(),
21023 [](const detail::json_ref<basic_json>& element_ref)
21024 {
21025 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
21026 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
21027 // broken call to op[key_type], the wrong semantics, and a 4804 warning on Windows)
21028 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
21029 });
21030
21031 // adjust type if type deduction is not wanted
21032 if (!type_deduction)
21033 {
21034 // if an array is wanted, do not create an object though possible
21035 if (manual_type == value_t::array)
21036 {
21037 is_an_object = false;
21038 }
21039
21040 // if an object is wanted but impossible, throw an exception
21041 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
21042 {
21043 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
21044 }
21045 }
21046
21047 if (is_an_object)
21048 {
21049 // the initializer list is a list of pairs -> create an object
21050 m_data.m_type = value_t::object;
21051 m_data.m_value = value_t::object;
21052
21053 for (auto& element_ref : init)
21054 {
21055 auto element = element_ref.moved_or_copied();
21056 m_data.m_value.object->emplace(
21057 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
21058 std::move((*element.m_data.m_value.array)[1]));
21059 }
21060 }
21061 else
21062 {
21063 // the initializer list describes an array -> create an array
21064 m_data.m_type = value_t::array;
21065 m_data.m_value.array = create<array_t>(init.begin(), init.end());
21066 }
21067
21068 set_parents();
21069 assert_invariant();
21070 }
21071
21072 /// @brief explicitly create a binary array (without subtype)
21073 /// @sa https://json.nlohmann.me/api/basic_json/binary/
21075 static basic_json binary(const typename binary_t::container_type& init)
21076 {
21077 auto res = basic_json();
21078 res.m_data.m_type = value_t::binary;
21079 res.m_data.m_value = init;
21080 return res;
21081 }
21082
21083 /// @brief explicitly create a binary array (with subtype)
21084 /// @sa https://json.nlohmann.me/api/basic_json/binary/
21086 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
21087 {
21088 auto res = basic_json();
21089 res.m_data.m_type = value_t::binary;
21090 res.m_data.m_value = binary_t(init, subtype);
21091 return res;
21092 }
21093
21094 /// @brief explicitly create a binary array
21095 /// @sa https://json.nlohmann.me/api/basic_json/binary/
21097 static basic_json binary(typename binary_t::container_type&& init)
21098 {
21099 auto res = basic_json();
21100 res.m_data.m_type = value_t::binary;
21101 res.m_data.m_value = std::move(init);
21102 return res;
21103 }
21104
21105 /// @brief explicitly create a binary array (with subtype)
21106 /// @sa https://json.nlohmann.me/api/basic_json/binary/
21108 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
21109 {
21110 auto res = basic_json();
21111 res.m_data.m_type = value_t::binary;
21112 res.m_data.m_value = binary_t(std::move(init), subtype);
21113 return res;
21114 }
21115
21116 /// @brief explicitly create an array from an initializer list
21117 /// @sa https://json.nlohmann.me/api/basic_json/array/
21120 {
21121 return basic_json(init, false, value_t::array);
21122 }
21123
21124 /// @brief explicitly create an object from an initializer list
21125 /// @sa https://json.nlohmann.me/api/basic_json/object/
21128 {
21129 return basic_json(init, false, value_t::object);
21130 }
21131
21132 /// @brief construct an array with count copies of given value
21133 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
21135 m_data{cnt, val}
21136 {
21137 set_parents();
21138 assert_invariant();
21139 }
21140
21141 /// @brief construct a JSON container given an iterator range
21142 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
21143 template < class InputIT, typename std::enable_if <
21144 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
21145 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
21146 basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
21147 {
21148 JSON_ASSERT(first.m_object != nullptr);
21149 JSON_ASSERT(last.m_object != nullptr);
21150
21151 // make sure the iterator fits the current value
21152 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
21153 {
21154 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
21155 }
21156
21157 // copy type from the first iterator
21158 m_data.m_type = first.m_object->m_data.m_type;
21159
21160 // check if the iterator range is complete for primitive values
21161 switch (m_data.m_type)
21162 {
21163 case value_t::boolean:
21164 case value_t::number_float:
21165 case value_t::number_integer:
21166 case value_t::number_unsigned:
21167 case value_t::string:
21168 {
21169 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
21170 || !last.m_it.primitive_iterator.is_end()))
21171 {
21172 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
21173 }
21174 break;
21175 }
21176
21177 case value_t::null:
21178 case value_t::object:
21179 case value_t::array:
21180 case value_t::binary:
21181 case value_t::discarded:
21182 default:
21183 break;
21184 }
21185
21186 switch (m_data.m_type)
21187 {
21188 case value_t::number_integer:
21189 {
21190 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
21191 break;
21192 }
21193
21194 case value_t::number_unsigned:
21195 {
21196 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
21197 break;
21198 }
21199
21200 case value_t::number_float:
21201 {
21202 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
21203 break;
21204 }
21205
21206 case value_t::boolean:
21207 {
21208 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
21209 break;
21210 }
21211
21212 case value_t::string:
21213 {
21214 m_data.m_value = *first.m_object->m_data.m_value.string;
21215 break;
21216 }
21217
21218 case value_t::object:
21219 {
21220 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
21221 last.m_it.object_iterator);
21222 break;
21223 }
21224
21225 case value_t::array:
21226 {
21227 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
21228 last.m_it.array_iterator);
21229 break;
21230 }
21231
21232 case value_t::binary:
21233 {
21234 m_data.m_value = *first.m_object->m_data.m_value.binary;
21235 break;
21236 }
21237
21238 case value_t::null:
21239 case value_t::discarded:
21240 default:
21241 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
21242 }
21243
21244 set_parents();
21245 assert_invariant();
21246 }
21247
21248 ///////////////////////////////////////
21249 // other constructors and destructor //
21250 ///////////////////////////////////////
21251
21252 template<typename JsonRef,
21254 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
21255 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
21256
21257 /// @brief copy constructor
21258 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
21260 : json_base_class_t(other)
21262 , start_position(other.start_position)
21263 , end_position(other.end_position)
21264#endif
21265 {
21266 m_data.m_type = other.m_data.m_type;
21267 // check of passed value is valid
21268 other.assert_invariant();
21269
21270 switch (m_data.m_type)
21271 {
21272 case value_t::object:
21273 {
21274 m_data.m_value = *other.m_data.m_value.object;
21275 break;
21276 }
21277
21278 case value_t::array:
21279 {
21280 m_data.m_value = *other.m_data.m_value.array;
21281 break;
21282 }
21283
21284 case value_t::string:
21285 {
21286 m_data.m_value = *other.m_data.m_value.string;
21287 break;
21288 }
21289
21290 case value_t::boolean:
21291 {
21292 m_data.m_value = other.m_data.m_value.boolean;
21293 break;
21294 }
21295
21296 case value_t::number_integer:
21297 {
21298 m_data.m_value = other.m_data.m_value.number_integer;
21299 break;
21300 }
21301
21302 case value_t::number_unsigned:
21303 {
21304 m_data.m_value = other.m_data.m_value.number_unsigned;
21305 break;
21306 }
21307
21308 case value_t::number_float:
21309 {
21310 m_data.m_value = other.m_data.m_value.number_float;
21311 break;
21312 }
21313
21314 case value_t::binary:
21315 {
21316 m_data.m_value = *other.m_data.m_value.binary;
21317 break;
21318 }
21319
21320 case value_t::null:
21321 case value_t::discarded:
21322 default:
21323 break;
21324 }
21325
21326 set_parents();
21327 assert_invariant();
21328 }
21329
21330 /// @brief move constructor
21331 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
21332 basic_json(basic_json&& other) noexcept
21333 : json_base_class_t(std::forward<json_base_class_t>(other)),
21334 m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
21335#if JSON_DIAGNOSTIC_POSITIONS
21336 , start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
21337 , end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
21338#endif
21339 {
21340 // check that the passed value is valid
21341 other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
21342
21343 // invalidate payload
21344 other.m_data.m_type = value_t::null;
21345 other.m_data.m_value = {};
21346
21347#if JSON_DIAGNOSTIC_POSITIONS
21348 other.start_position = std::string::npos;
21349 other.end_position = std::string::npos;
21350#endif
21351
21352 set_parents();
21353 assert_invariant();
21354 }
21355
21356 /// @brief copy assignment
21357 /// @sa https://json.nlohmann.me/api/basic_json/operator=/
21359 std::is_nothrow_move_constructible<value_t>::value&&
21360 std::is_nothrow_move_assignable<value_t>::value&&
21361 std::is_nothrow_move_constructible<json_value>::value&&
21362 std::is_nothrow_move_assignable<json_value>::value&&
21363 std::is_nothrow_move_assignable<json_base_class_t>::value
21364 )
21365 {
21366 // check that the passed value is valid
21367 other.assert_invariant();
21368
21369 using std::swap;
21370 swap(m_data.m_type, other.m_data.m_type);
21371 swap(m_data.m_value, other.m_data.m_value);
21372
21373#if JSON_DIAGNOSTIC_POSITIONS
21374 swap(start_position, other.start_position);
21375 swap(end_position, other.end_position);
21376#endif
21377
21378 json_base_class_t::operator=(std::move(other));
21379
21380 set_parents();
21381 assert_invariant();
21382 return *this;
21383 }
21384
21385 /// @brief destructor
21386 /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
21387 ~basic_json() noexcept
21388 {
21389 assert_invariant(false);
21390 }
21391
21392 /// @}
21393
21394 public:
21395 ///////////////////////
21396 // object inspection //
21397 ///////////////////////
21398
21399 /// @name object inspection
21400 /// Functions to inspect the type of a JSON value.
21401 /// @{
21402
21403 /// @brief serialization
21404 /// @sa https://json.nlohmann.me/api/basic_json/dump/
21405 string_t dump(const int indent = -1,
21406 const char indent_char = ' ',
21407 const bool ensure_ascii = false,
21408 const error_handler_t error_handler = error_handler_t::strict) const
21409 {
21410 string_t result;
21411 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
21412
21413 if (indent >= 0)
21414 {
21415 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
21416 }
21417 else
21418 {
21419 s.dump(*this, false, ensure_ascii, 0);
21420 }
21421
21422 return result;
21423 }
21424
21425 /// @brief return the type of the JSON value (explicit)
21426 /// @sa https://json.nlohmann.me/api/basic_json/type/
21427 constexpr value_t type() const noexcept
21428 {
21429 return m_data.m_type;
21430 }
21431
21432 /// @brief return whether type is primitive
21433 /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
21434 constexpr bool is_primitive() const noexcept
21435 {
21436 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
21437 }
21438
21439 /// @brief return whether type is structured
21440 /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
21441 constexpr bool is_structured() const noexcept
21442 {
21443 return is_array() || is_object();
21444 }
21445
21446 /// @brief return whether value is null
21447 /// @sa https://json.nlohmann.me/api/basic_json/is_null/
21448 constexpr bool is_null() const noexcept
21449 {
21450 return m_data.m_type == value_t::null;
21451 }
21452
21453 /// @brief return whether value is a boolean
21454 /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
21455 constexpr bool is_boolean() const noexcept
21456 {
21457 return m_data.m_type == value_t::boolean;
21458 }
21459
21460 /// @brief return whether value is a number
21461 /// @sa https://json.nlohmann.me/api/basic_json/is_number/
21462 constexpr bool is_number() const noexcept
21463 {
21464 return is_number_integer() || is_number_float();
21465 }
21466
21467 /// @brief return whether value is an integer number
21468 /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
21469 constexpr bool is_number_integer() const noexcept
21470 {
21471 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
21472 }
21473
21474 /// @brief return whether value is an unsigned integer number
21475 /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
21476 constexpr bool is_number_unsigned() const noexcept
21477 {
21478 return m_data.m_type == value_t::number_unsigned;
21479 }
21480
21481 /// @brief return whether value is a floating-point number
21482 /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
21483 constexpr bool is_number_float() const noexcept
21484 {
21485 return m_data.m_type == value_t::number_float;
21486 }
21487
21488 /// @brief return whether value is an object
21489 /// @sa https://json.nlohmann.me/api/basic_json/is_object/
21490 constexpr bool is_object() const noexcept
21491 {
21492 return m_data.m_type == value_t::object;
21493 }
21494
21495 /// @brief return whether value is an array
21496 /// @sa https://json.nlohmann.me/api/basic_json/is_array/
21497 constexpr bool is_array() const noexcept
21498 {
21499 return m_data.m_type == value_t::array;
21500 }
21501
21502 /// @brief return whether value is a string
21503 /// @sa https://json.nlohmann.me/api/basic_json/is_string/
21504 constexpr bool is_string() const noexcept
21505 {
21506 return m_data.m_type == value_t::string;
21507 }
21508
21509 /// @brief return whether value is a binary array
21510 /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
21511 constexpr bool is_binary() const noexcept
21512 {
21513 return m_data.m_type == value_t::binary;
21514 }
21515
21516 /// @brief return whether value is discarded
21517 /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
21518 constexpr bool is_discarded() const noexcept
21519 {
21520 return m_data.m_type == value_t::discarded;
21521 }
21522
21523 /// @brief return the type of the JSON value (implicit)
21524 /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
21525 constexpr operator value_t() const noexcept
21526 {
21527 return m_data.m_type;
21528 }
21529
21530 /// @}
21531
21532 private:
21533 //////////////////
21534 // value access //
21535 //////////////////
21536
21537 /// get a boolean (explicit)
21538 boolean_t get_impl(boolean_t* /*unused*/) const
21539 {
21540 if (JSON_HEDLEY_LIKELY(is_boolean()))
21541 {
21542 return m_data.m_value.boolean;
21543 }
21544
21545 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
21546 }
21547
21548 /// get a pointer to the value (object)
21549 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
21550 {
21551 return is_object() ? m_data.m_value.object : nullptr;
21552 }
21553
21554 /// get a pointer to the value (object)
21555 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
21556 {
21557 return is_object() ? m_data.m_value.object : nullptr;
21558 }
21559
21560 /// get a pointer to the value (array)
21561 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
21562 {
21563 return is_array() ? m_data.m_value.array : nullptr;
21564 }
21565
21566 /// get a pointer to the value (array)
21567 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
21568 {
21569 return is_array() ? m_data.m_value.array : nullptr;
21570 }
21571
21572 /// get a pointer to the value (string)
21573 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
21574 {
21575 return is_string() ? m_data.m_value.string : nullptr;
21576 }
21577
21578 /// get a pointer to the value (string)
21579 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
21580 {
21581 return is_string() ? m_data.m_value.string : nullptr;
21582 }
21583
21584 /// get a pointer to the value (boolean)
21585 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
21586 {
21587 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21588 }
21589
21590 /// get a pointer to the value (boolean)
21591 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
21592 {
21593 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21594 }
21595
21596 /// get a pointer to the value (integer number)
21598 {
21599 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21600 }
21601
21602 /// get a pointer to the value (integer number)
21603 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
21604 {
21605 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21606 }
21607
21608 /// get a pointer to the value (unsigned number)
21610 {
21611 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21612 }
21613
21614 /// get a pointer to the value (unsigned number)
21615 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
21616 {
21617 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21618 }
21619
21620 /// get a pointer to the value (floating-point number)
21622 {
21623 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21624 }
21625
21626 /// get a pointer to the value (floating-point number)
21627 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
21628 {
21629 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21630 }
21631
21632 /// get a pointer to the value (binary)
21633 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
21634 {
21635 return is_binary() ? m_data.m_value.binary : nullptr;
21636 }
21637
21638 /// get a pointer to the value (binary)
21639 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
21640 {
21641 return is_binary() ? m_data.m_value.binary : nullptr;
21642 }
21643
21644 /*!
21645 @brief helper function to implement get_ref()
21646
21647 This function helps to implement get_ref() without code duplication for
21648 const and non-const overloads
21649
21650 @tparam ThisType will be deduced as `basic_json` or `const basic_json`
21651
21652 @throw type_error.303 if ReferenceType does not match underlying value
21653 type of the current JSON
21654 */
21655 template<typename ReferenceType, typename ThisType>
21656 static ReferenceType get_ref_impl(ThisType& obj)
21657 {
21658 // delegate the call to get_ptr<>()
21659 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
21660
21661 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
21662 {
21663 return *ptr;
21664 }
21665
21666 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
21667 }
21668
21669 public:
21670 /// @name value access
21671 /// Direct access to the stored value of a JSON value.
21672 /// @{
21673
21674 /// @brief get a pointer value (implicit)
21675 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
21676 template<typename PointerType, typename std::enable_if<
21677 std::is_pointer<PointerType>::value, int>::type = 0>
21678 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21679 {
21680 // delegate the call to get_impl_ptr<>()
21681 return get_impl_ptr(static_cast<PointerType>(nullptr));
21682 }
21683
21684 /// @brief get a pointer value (implicit)
21685 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
21686 template < typename PointerType, typename std::enable_if <
21687 std::is_pointer<PointerType>::value&&
21688 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
21689 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21690 {
21691 // delegate the call to get_impl_ptr<>() const
21692 return get_impl_ptr(static_cast<PointerType>(nullptr));
21693 }
21694
21695 private:
21696 /*!
21697 @brief get a value (explicit)
21698
21699 Explicit type conversion between the JSON value and a compatible value
21700 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
21701 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
21702 The value is converted by calling the @ref json_serializer<ValueType>
21703 `from_json()` method.
21704
21705 The function is equivalent to executing
21706 @code {.cpp}
21707 ValueType ret;
21708 JSONSerializer<ValueType>::from_json(*this, ret);
21709 return ret;
21710 @endcode
21711
21712 This overloads is chosen if:
21713 - @a ValueType is not @ref basic_json,
21714 - @ref json_serializer<ValueType> has a `from_json()` method of the form
21715 `void from_json(const basic_json&, ValueType&)`, and
21716 - @ref json_serializer<ValueType> does not have a `from_json()` method of
21717 the form `ValueType from_json(const basic_json&)`
21718
21719 @tparam ValueType the returned value type
21720
21721 @return copy of the JSON value, converted to @a ValueType
21722
21723 @throw what @ref json_serializer<ValueType> `from_json()` method throws
21724
21725 @liveexample{The example below shows several conversions from JSON values
21726 to other types. There a few things to note: (1) Floating-point numbers can
21727 be converted to integers\, (2) A JSON array can be converted to a standard
21728 `std::vector<short>`\, (3) A JSON object can be converted to C++
21729 associative containers such as `std::unordered_map<std::string\,
21730 json>`.,get__ValueType_const}
21731
21732 @since version 2.1.0
21733 */
21734 template < typename ValueType,
21738 int > = 0 >
21739 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
21740 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
21741 {
21742 auto ret = ValueType();
21743 JSONSerializer<ValueType>::from_json(*this, ret);
21744 return ret;
21745 }
21746
21747 /*!
21748 @brief get a value (explicit); special case
21749
21750 Explicit type conversion between the JSON value and a compatible value
21751 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
21752 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
21753 The value is converted by calling the @ref json_serializer<ValueType>
21754 `from_json()` method.
21755
21756 The function is equivalent to executing
21757 @code {.cpp}
21758 return JSONSerializer<ValueType>::from_json(*this);
21759 @endcode
21760
21761 This overloads is chosen if:
21762 - @a ValueType is not @ref basic_json and
21763 - @ref json_serializer<ValueType> has a `from_json()` method of the form
21764 `ValueType from_json(const basic_json&)`
21765
21766 @note If @ref json_serializer<ValueType> has both overloads of
21767 `from_json()`, this one is chosen.
21768
21769 @tparam ValueType the returned value type
21770
21771 @return copy of the JSON value, converted to @a ValueType
21772
21773 @throw what @ref json_serializer<ValueType> `from_json()` method throws
21774
21775 @since version 2.1.0
21776 */
21777 template < typename ValueType,
21780 int > = 0 >
21781 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
21782 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
21783 {
21784 return JSONSerializer<ValueType>::from_json(*this);
21785 }
21786
21787 /*!
21788 @brief get special-case overload
21789
21790 This overloads converts the current @ref basic_json in a different
21791 @ref basic_json type
21792
21793 @tparam BasicJsonType == @ref basic_json
21794
21795 @return a copy of *this, converted into @a BasicJsonType
21796
21797 @complexity Depending on the implementation of the called `from_json()`
21798 method.
21799
21800 @since version 3.2.0
21801 */
21802 template < typename BasicJsonType,
21805 int > = 0 >
21806 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
21807 {
21808 return *this;
21809 }
21810
21811 /*!
21812 @brief get special-case overload
21813
21814 This overloads avoids a lot of template boilerplate, it can be seen as the
21815 identity method
21816
21817 @tparam BasicJsonType == @ref basic_json
21818
21819 @return a copy of *this
21820
21821 @complexity Constant.
21822
21823 @since version 2.1.0
21824 */
21825 template<typename BasicJsonType,
21827 std::is_same<BasicJsonType, basic_json_t>::value,
21828 int> = 0>
21830 {
21831 return *this;
21832 }
21833
21834 /*!
21835 @brief get a pointer value (explicit)
21836 @copydoc get()
21837 */
21838 template<typename PointerType,
21840 std::is_pointer<PointerType>::value,
21841 int> = 0>
21842 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21843 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21844 {
21845 // delegate the call to get_ptr
21846 return get_ptr<PointerType>();
21847 }
21848
21849 public:
21850 /*!
21851 @brief get a (pointer) value (explicit)
21852
21853 Performs explicit type conversion between the JSON value and a compatible value if required.
21854
21855 - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
21856 No copies are made.
21857
21858 - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
21859 from the current @ref basic_json.
21860
21861 - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
21862 method.
21863
21864 @tparam ValueTypeCV the provided value type
21865 @tparam ValueType the returned value type
21866
21867 @return copy of the JSON value, converted to @tparam ValueType if necessary
21868
21869 @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
21870
21871 @since version 2.1.0
21872 */
21873 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21874#if defined(JSON_HAS_CPP_14)
21875 constexpr
21876#endif
21877 auto get() const noexcept(
21878 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21879 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21880 {
21881 // we cannot static_assert on ValueTypeCV being non-const, because
21882 // there is support for get<const basic_json_t>(), which is why we
21883 // still need the uncvref
21884 static_assert(!std::is_reference<ValueTypeCV>::value,
21885 "get() cannot be used with reference types, you might want to use get_ref()");
21886 return get_impl<ValueType>(detail::priority_tag<4> {});
21887 }
21888
21889 /*!
21890 @brief get a pointer value (explicit)
21891
21892 Explicit pointer access to the internally stored JSON value. No copies are
21893 made.
21894
21895 @warning The pointer becomes invalid if the underlying JSON object
21896 changes.
21897
21898 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
21899 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
21900 @ref number_unsigned_t, or @ref number_float_t.
21901
21902 @return pointer to the internally stored JSON value if the requested
21903 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
21904
21905 @complexity Constant.
21906
21907 @liveexample{The example below shows how pointers to internal values of a
21908 JSON value can be requested. Note that no type conversions are made and a
21909 `nullptr` is returned if the value and the requested pointer type does not
21910 match.,get__PointerType}
21911
21912 @sa see @ref get_ptr() for explicit pointer-member access
21913
21914 @since version 1.0.0
21915 */
21916 template<typename PointerType, typename std::enable_if<
21917 std::is_pointer<PointerType>::value, int>::type = 0>
21918 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21919 {
21920 // delegate the call to get_ptr
21921 return get_ptr<PointerType>();
21922 }
21923
21924 /// @brief get a value (explicit)
21925 /// @sa https://json.nlohmann.me/api/basic_json/get_to/
21926 template < typename ValueType,
21930 int > = 0 >
21931 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21932 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21933 {
21934 JSONSerializer<ValueType>::from_json(*this, v);
21935 return v;
21936 }
21937
21938 // specialization to allow calling get_to with a basic_json value
21939 // see https://github.com/nlohmann/json/issues/2175
21940 template<typename ValueType,
21943 int> = 0>
21944 ValueType & get_to(ValueType& v) const
21945 {
21946 v = *this;
21947 return v;
21948 }
21949
21950 template <
21951 typename T, std::size_t N,
21952 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21955 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21956 noexcept(noexcept(JSONSerializer<Array>::from_json(
21957 std::declval<const basic_json_t&>(), v)))
21958 {
21959 JSONSerializer<Array>::from_json(*this, v);
21960 return v;
21961 }
21962
21963 /// @brief get a reference value (implicit)
21964 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
21965 template<typename ReferenceType, typename std::enable_if<
21966 std::is_reference<ReferenceType>::value, int>::type = 0>
21967 ReferenceType get_ref()
21968 {
21969 // delegate call to get_ref_impl
21970 return get_ref_impl<ReferenceType>(*this);
21971 }
21972
21973 /// @brief get a reference value (implicit)
21974 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
21975 template < typename ReferenceType, typename std::enable_if <
21976 std::is_reference<ReferenceType>::value&&
21977 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21978 ReferenceType get_ref() const
21979 {
21980 // delegate call to get_ref_impl
21981 return get_ref_impl<ReferenceType>(*this);
21982 }
21983
21984 /*!
21985 @brief get a value (implicit)
21986
21987 Implicit type conversion between the JSON value and a compatible value.
21988 The call is realized by calling @ref get() const.
21989
21990 @tparam ValueType non-pointer type compatible to the JSON value, for
21991 instance `int` for JSON integer numbers, `bool` for JSON booleans, or
21992 `std::vector` types for JSON arrays. The character type of @ref string_t
21993 as well as an initializer list of this type is excluded to avoid
21994 ambiguities as these types implicitly convert to `std::string`.
21995
21996 @return copy of the JSON value, converted to type @a ValueType
21997
21998 @throw type_error.302 in case passed type @a ValueType is incompatible
21999 to the JSON value type (e.g., the JSON value is of type boolean, but a
22000 string is requested); see example below
22001
22002 @complexity Linear in the size of the JSON value.
22003
22004 @liveexample{The example below shows several conversions from JSON values
22005 to other types. There a few things to note: (1) Floating-point numbers can
22006 be converted to integers\, (2) A JSON array can be converted to a standard
22007 `std::vector<short>`\, (3) A JSON object can be converted to C++
22008 associative containers such as `std::unordered_map<std::string\,
22009 json>`.,operator__ValueType}
22010
22011 @since version 1.0.0
22012 */
22013 template < typename ValueType, typename std::enable_if <
22021#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
22023#endif
22024#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
22026#endif
22028 >::value, int >::type = 0 >
22029 JSON_EXPLICIT operator ValueType() const
22030 {
22031 // delegate the call to get<>() const
22032 return get<ValueType>();
22033 }
22034
22035 /// @brief get a binary value
22036 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
22038 {
22039 if (!is_binary())
22040 {
22041 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
22042 }
22043
22044 return *get_ptr<binary_t*>();
22045 }
22046
22047 /// @brief get a binary value
22048 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
22049 const binary_t& get_binary() const
22050 {
22051 if (!is_binary())
22052 {
22053 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
22054 }
22055
22056 return *get_ptr<const binary_t*>();
22057 }
22058
22059 /// @}
22060
22061 ////////////////////
22062 // element access //
22063 ////////////////////
22064
22065 /// @name element access
22066 /// Access to the JSON value.
22067 /// @{
22068
22069 /// @brief access specified array element with bounds checking
22070 /// @sa https://json.nlohmann.me/api/basic_json/at/
22072 {
22073 // at only works for arrays
22074 if (JSON_HEDLEY_LIKELY(is_array()))
22075 {
22076 JSON_TRY
22077 {
22078 return set_parent(m_data.m_value.array->at(idx));
22079 }
22080 JSON_CATCH (std::out_of_range&)
22081 {
22082 // create a better exception explanation
22083 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22084 } // cppcheck-suppress[missingReturn]
22085 }
22086 else
22087 {
22088 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22089 }
22090 }
22091
22092 /// @brief access specified array element with bounds checking
22093 /// @sa https://json.nlohmann.me/api/basic_json/at/
22095 {
22096 // at only works for arrays
22097 if (JSON_HEDLEY_LIKELY(is_array()))
22098 {
22099 JSON_TRY
22100 {
22101 return m_data.m_value.array->at(idx);
22102 }
22103 JSON_CATCH (std::out_of_range&)
22104 {
22105 // create a better exception explanation
22106 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22107 } // cppcheck-suppress[missingReturn]
22108 }
22109 else
22110 {
22111 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22112 }
22113 }
22114
22115 /// @brief access specified object element with bounds checking
22116 /// @sa https://json.nlohmann.me/api/basic_json/at/
22117 reference at(const typename object_t::key_type& key)
22118 {
22119 // at only works for objects
22120 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22121 {
22122 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22123 }
22124
22125 auto it = m_data.m_value.object->find(key);
22126 if (it == m_data.m_value.object->end())
22127 {
22128 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22129 }
22130 return set_parent(it->second);
22131 }
22132
22133 /// @brief access specified object element with bounds checking
22134 /// @sa https://json.nlohmann.me/api/basic_json/at/
22135 template<class KeyType, detail::enable_if_t<
22137 reference at(KeyType && key)
22138 {
22139 // at only works for objects
22140 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22141 {
22142 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22143 }
22144
22145 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22146 if (it == m_data.m_value.object->end())
22147 {
22148 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22149 }
22150 return set_parent(it->second);
22151 }
22152
22153 /// @brief access specified object element with bounds checking
22154 /// @sa https://json.nlohmann.me/api/basic_json/at/
22155 const_reference at(const typename object_t::key_type& key) const
22156 {
22157 // at only works for objects
22158 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22159 {
22160 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22161 }
22162
22163 auto it = m_data.m_value.object->find(key);
22164 if (it == m_data.m_value.object->end())
22165 {
22166 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22167 }
22168 return it->second;
22169 }
22170
22171 /// @brief access specified object element with bounds checking
22172 /// @sa https://json.nlohmann.me/api/basic_json/at/
22173 template<class KeyType, detail::enable_if_t<
22175 const_reference at(KeyType && key) const
22176 {
22177 // at only works for objects
22178 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22179 {
22180 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22181 }
22182
22183 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22184 if (it == m_data.m_value.object->end())
22185 {
22186 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22187 }
22188 return it->second;
22189 }
22190
22191 /// @brief access specified array element
22192 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22194 {
22195 // implicitly convert a null value to an empty array
22196 if (is_null())
22197 {
22198 m_data.m_type = value_t::array;
22199 m_data.m_value.array = create<array_t>();
22200 assert_invariant();
22201 }
22202
22203 // operator[] only works for arrays
22204 if (JSON_HEDLEY_LIKELY(is_array()))
22205 {
22206 // fill up the array with null values if given idx is outside the range
22207 if (idx >= m_data.m_value.array->size())
22208 {
22209#if JSON_DIAGNOSTICS
22210 // remember array size & capacity before resizing
22211 const auto old_size = m_data.m_value.array->size();
22212 const auto old_capacity = m_data.m_value.array->capacity();
22213#endif
22214 m_data.m_value.array->resize(idx + 1);
22215
22216#if JSON_DIAGNOSTICS
22217 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
22218 {
22219 // capacity has changed: update all parents
22220 set_parents();
22221 }
22222 else
22223 {
22224 // set parent for values added above
22225 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
22226 }
22227#endif
22228 assert_invariant();
22229 }
22230
22231 return m_data.m_value.array->operator[](idx);
22232 }
22233
22234 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22235 }
22236
22237 /// @brief access specified array element
22238 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22240 {
22241 // const operator[] only works for arrays
22242 if (JSON_HEDLEY_LIKELY(is_array()))
22243 {
22244 return m_data.m_value.array->operator[](idx);
22245 }
22246
22247 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22248 }
22249
22250 /// @brief access specified object element
22251 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22252 reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
22253 {
22254 // implicitly convert a null value to an empty object
22255 if (is_null())
22256 {
22257 m_data.m_type = value_t::object;
22258 m_data.m_value.object = create<object_t>();
22259 assert_invariant();
22260 }
22261
22262 // operator[] only works for objects
22263 if (JSON_HEDLEY_LIKELY(is_object()))
22264 {
22265 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
22266 return set_parent(result.first->second);
22267 }
22268
22269 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22270 }
22271
22272 /// @brief access specified object element
22273 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22274 const_reference operator[](const typename object_t::key_type& key) const
22275 {
22276 // const operator[] only works for objects
22277 if (JSON_HEDLEY_LIKELY(is_object()))
22278 {
22279 auto it = m_data.m_value.object->find(key);
22280 JSON_ASSERT(it != m_data.m_value.object->end());
22281 return it->second;
22282 }
22283
22284 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22285 }
22286
22287 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
22288 // (they seemingly cannot be constrained to resolve the ambiguity)
22289 template<typename T>
22291 {
22292 return operator[](typename object_t::key_type(key));
22293 }
22294
22295 template<typename T>
22297 {
22298 return operator[](typename object_t::key_type(key));
22299 }
22300
22301 /// @brief access specified object element
22302 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22303 template<class KeyType, detail::enable_if_t<
22305 reference operator[](KeyType && key)
22306 {
22307 // implicitly convert a null value to an empty object
22308 if (is_null())
22309 {
22310 m_data.m_type = value_t::object;
22311 m_data.m_value.object = create<object_t>();
22312 assert_invariant();
22313 }
22314
22315 // operator[] only works for objects
22316 if (JSON_HEDLEY_LIKELY(is_object()))
22317 {
22318 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
22319 return set_parent(result.first->second);
22320 }
22321
22322 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22323 }
22324
22325 /// @brief access specified object element
22326 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22327 template<class KeyType, detail::enable_if_t<
22329 const_reference operator[](KeyType && key) const
22330 {
22331 // const operator[] only works for objects
22332 if (JSON_HEDLEY_LIKELY(is_object()))
22333 {
22334 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22335 JSON_ASSERT(it != m_data.m_value.object->end());
22336 return it->second;
22337 }
22338
22339 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22340 }
22341
22342 private:
22343 template<typename KeyType>
22345 object_comparator_t, const typename object_t::key_type&, KeyType >;
22346
22347 template<typename ValueType>
22348 using value_return_type = std::conditional <
22350 string_t, typename std::decay<ValueType>::type >;
22351
22352 public:
22353 /// @brief access specified object element with default value
22354 /// @sa https://json.nlohmann.me/api/basic_json/value/
22355 template < class ValueType, detail::enable_if_t <
22358 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22359 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
22360 {
22361 // value only works for objects
22362 if (JSON_HEDLEY_LIKELY(is_object()))
22363 {
22364 // If 'key' is found, return its value. Otherwise, return `default_value'.
22365 const auto it = find(key);
22366 if (it != end())
22367 {
22368 return it->template get<ValueType>();
22369 }
22370
22371 return default_value;
22372 }
22373
22374 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22375 }
22376
22377 /// @brief access specified object element with default value
22378 /// @sa https://json.nlohmann.me/api/basic_json/value/
22379 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22383 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22384 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
22385 {
22386 // value only works for objects
22387 if (JSON_HEDLEY_LIKELY(is_object()))
22388 {
22389 // If 'key' is found, return its value. Otherwise, return `default_value'.
22390 const auto it = find(key);
22391 if (it != end())
22392 {
22393 return it->template get<ReturnType>();
22394 }
22395
22396 return std::forward<ValueType>(default_value);
22397 }
22398
22399 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22400 }
22401
22402 /// @brief access specified object element with default value
22403 /// @sa https://json.nlohmann.me/api/basic_json/value/
22404 template < class ValueType, class KeyType, detail::enable_if_t <
22407 && is_comparable_with_object_key<KeyType>::value
22409 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22410 ValueType value(KeyType && key, const ValueType& default_value) const
22411 {
22412 // value only works for objects
22413 if (JSON_HEDLEY_LIKELY(is_object()))
22414 {
22415 // If 'key' is found, return its value. Otherwise, return `default_value'.
22416 const auto it = find(std::forward<KeyType>(key));
22417 if (it != end())
22418 {
22419 return it->template get<ValueType>();
22420 }
22421
22422 return default_value;
22423 }
22424
22425 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22426 }
22427
22428 /// @brief access specified object element via JSON Pointer with default value
22429 /// @sa https://json.nlohmann.me/api/basic_json/value/
22430 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
22434 && is_comparable_with_object_key<KeyType>::value
22436 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22437 ReturnType value(KeyType && key, ValueType && default_value) const
22438 {
22439 // value only works for objects
22440 if (JSON_HEDLEY_LIKELY(is_object()))
22441 {
22442 // If 'key' is found, return its value. Otherwise, return `default_value'.
22443 const auto it = find(std::forward<KeyType>(key));
22444 if (it != end())
22445 {
22446 return it->template get<ReturnType>();
22447 }
22448
22449 return std::forward<ValueType>(default_value);
22450 }
22451
22452 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22453 }
22454
22455 /// @brief access specified object element via JSON Pointer with default value
22456 /// @sa https://json.nlohmann.me/api/basic_json/value/
22457 template < class ValueType, detail::enable_if_t <
22459 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22460 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
22461 {
22462 // value only works for objects
22463 if (JSON_HEDLEY_LIKELY(is_object()))
22464 {
22465 // If the pointer resolves to a value, return it. Otherwise, return
22466 // 'default_value'.
22467 JSON_TRY
22468 {
22469 return ptr.get_checked(this).template get<ValueType>();
22470 }
22472 {
22473 return default_value;
22474 }
22475 }
22476
22477 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22478 }
22479
22480 /// @brief access specified object element via JSON Pointer with default value
22481 /// @sa https://json.nlohmann.me/api/basic_json/value/
22482 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22485 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22486 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
22487 {
22488 // value only works for objects
22489 if (JSON_HEDLEY_LIKELY(is_object()))
22490 {
22491 // If the pointer resolves to a value, return it. Otherwise, return
22492 // 'default_value'.
22493 JSON_TRY
22494 {
22495 return ptr.get_checked(this).template get<ReturnType>();
22496 }
22498 {
22499 return std::forward<ValueType>(default_value);
22500 }
22501 }
22502
22503 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22504 }
22505
22506 template < class ValueType, class BasicJsonType, detail::enable_if_t <
22509 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22510 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22511 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
22512 {
22513 return value(ptr.convert(), default_value);
22514 }
22515
22516 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
22520 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22521 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22522 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
22523 {
22524 return value(ptr.convert(), std::forward<ValueType>(default_value));
22525 }
22526
22527 /// @brief access the first element
22528 /// @sa https://json.nlohmann.me/api/basic_json/front/
22530 {
22531 return *begin();
22532 }
22533
22534 /// @brief access the first element
22535 /// @sa https://json.nlohmann.me/api/basic_json/front/
22537 {
22538 return *cbegin();
22539 }
22540
22541 /// @brief access the last element
22542 /// @sa https://json.nlohmann.me/api/basic_json/back/
22544 {
22545 auto tmp = end();
22546 --tmp;
22547 return *tmp;
22548 }
22549
22550 /// @brief access the last element
22551 /// @sa https://json.nlohmann.me/api/basic_json/back/
22553 {
22554 auto tmp = cend();
22555 --tmp;
22556 return *tmp;
22557 }
22558
22559 /// @brief remove element given an iterator
22560 /// @sa https://json.nlohmann.me/api/basic_json/erase/
22561 template < class IteratorType, detail::enable_if_t <
22562 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22563 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22564 IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
22565 {
22566 // make sure the iterator fits the current value
22567 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
22568 {
22569 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22570 }
22571
22572 IteratorType result = end();
22573
22574 switch (m_data.m_type)
22575 {
22576 case value_t::boolean:
22577 case value_t::number_float:
22578 case value_t::number_integer:
22579 case value_t::number_unsigned:
22580 case value_t::string:
22581 case value_t::binary:
22582 {
22583 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
22584 {
22585 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
22586 }
22587
22588 if (is_string())
22589 {
22590 AllocatorType<string_t> alloc;
22591 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22592 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22593 m_data.m_value.string = nullptr;
22594 }
22595 else if (is_binary())
22596 {
22597 AllocatorType<binary_t> alloc;
22598 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22599 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22600 m_data.m_value.binary = nullptr;
22601 }
22602
22603 m_data.m_type = value_t::null;
22604 assert_invariant();
22605 break;
22606 }
22607
22608 case value_t::object:
22609 {
22610 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
22611 break;
22612 }
22613
22614 case value_t::array:
22615 {
22616 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
22617 break;
22618 }
22619
22620 case value_t::null:
22621 case value_t::discarded:
22622 default:
22623 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22624 }
22625
22626 return result;
22627 }
22628
22629 /// @brief remove elements given an iterator range
22630 /// @sa https://json.nlohmann.me/api/basic_json/erase/
22631 template < class IteratorType, detail::enable_if_t <
22632 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22633 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22634 IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
22635 {
22636 // make sure the iterator fits the current value
22637 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
22638 {
22639 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
22640 }
22641
22642 IteratorType result = end();
22643
22644 switch (m_data.m_type)
22645 {
22646 case value_t::boolean:
22647 case value_t::number_float:
22648 case value_t::number_integer:
22649 case value_t::number_unsigned:
22650 case value_t::string:
22651 case value_t::binary:
22652 {
22653 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
22654 || !last.m_it.primitive_iterator.is_end()))
22655 {
22656 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
22657 }
22658
22659 if (is_string())
22660 {
22661 AllocatorType<string_t> alloc;
22662 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22663 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22664 m_data.m_value.string = nullptr;
22665 }
22666 else if (is_binary())
22667 {
22668 AllocatorType<binary_t> alloc;
22669 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22670 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22671 m_data.m_value.binary = nullptr;
22672 }
22673
22674 m_data.m_type = value_t::null;
22675 assert_invariant();
22676 break;
22677 }
22678
22679 case value_t::object:
22680 {
22681 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
22682 last.m_it.object_iterator);
22683 break;
22684 }
22685
22686 case value_t::array:
22687 {
22688 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
22689 last.m_it.array_iterator);
22690 break;
22691 }
22692
22693 case value_t::null:
22694 case value_t::discarded:
22695 default:
22696 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22697 }
22698
22699 return result;
22700 }
22701
22702 private:
22703 template < typename KeyType, detail::enable_if_t <
22706 {
22707 // this erase only works for objects
22708 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22709 {
22710 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22711 }
22712
22713 return m_data.m_value.object->erase(std::forward<KeyType>(key));
22714 }
22715
22716 template < typename KeyType, detail::enable_if_t <
22719 {
22720 // this erase only works for objects
22721 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22722 {
22723 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22724 }
22725
22726 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22727 if (it != m_data.m_value.object->end())
22728 {
22729 m_data.m_value.object->erase(it);
22730 return 1;
22731 }
22732 return 0;
22733 }
22734
22735 public:
22736
22737 /// @brief remove element from a JSON object given a key
22738 /// @sa https://json.nlohmann.me/api/basic_json/erase/
22739 size_type erase(const typename object_t::key_type& key)
22740 {
22741 // the indirection via erase_internal() is added to avoid making this
22742 // function a template and thus de-rank it during overload resolution
22743 return erase_internal(key);
22744 }
22745
22746 /// @brief remove element from a JSON object given a key
22747 /// @sa https://json.nlohmann.me/api/basic_json/erase/
22748 template<class KeyType, detail::enable_if_t<
22750 size_type erase(KeyType && key)
22751 {
22752 return erase_internal(std::forward<KeyType>(key));
22753 }
22754
22755 /// @brief remove element from a JSON array given an index
22756 /// @sa https://json.nlohmann.me/api/basic_json/erase/
22757 void erase(const size_type idx)
22758 {
22759 // this erase only works for arrays
22760 if (JSON_HEDLEY_LIKELY(is_array()))
22761 {
22762 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
22763 {
22764 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22765 }
22766
22767 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
22768 }
22769 else
22770 {
22771 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22772 }
22773 }
22774
22775 /// @}
22776
22777 ////////////
22778 // lookup //
22779 ////////////
22780
22781 /// @name lookup
22782 /// @{
22783
22784 /// @brief find an element in a JSON object
22785 /// @sa https://json.nlohmann.me/api/basic_json/find/
22786 iterator find(const typename object_t::key_type& key)
22787 {
22788 auto result = end();
22789
22790 if (is_object())
22791 {
22792 result.m_it.object_iterator = m_data.m_value.object->find(key);
22793 }
22794
22795 return result;
22796 }
22797
22798 /// @brief find an element in a JSON object
22799 /// @sa https://json.nlohmann.me/api/basic_json/find/
22800 const_iterator find(const typename object_t::key_type& key) const
22801 {
22802 auto result = cend();
22803
22804 if (is_object())
22805 {
22806 result.m_it.object_iterator = m_data.m_value.object->find(key);
22807 }
22808
22809 return result;
22810 }
22811
22812 /// @brief find an element in a JSON object
22813 /// @sa https://json.nlohmann.me/api/basic_json/find/
22814 template<class KeyType, detail::enable_if_t<
22816 iterator find(KeyType && key)
22817 {
22818 auto result = end();
22819
22820 if (is_object())
22821 {
22822 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22823 }
22824
22825 return result;
22826 }
22827
22828 /// @brief find an element in a JSON object
22829 /// @sa https://json.nlohmann.me/api/basic_json/find/
22830 template<class KeyType, detail::enable_if_t<
22832 const_iterator find(KeyType && key) const
22833 {
22834 auto result = cend();
22835
22836 if (is_object())
22837 {
22838 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22839 }
22840
22841 return result;
22842 }
22843
22844 /// @brief returns the number of occurrences of a key in a JSON object
22845 /// @sa https://json.nlohmann.me/api/basic_json/count/
22846 size_type count(const typename object_t::key_type& key) const
22847 {
22848 // return 0 for all nonobject types
22849 return is_object() ? m_data.m_value.object->count(key) : 0;
22850 }
22851
22852 /// @brief returns the number of occurrences of a key in a JSON object
22853 /// @sa https://json.nlohmann.me/api/basic_json/count/
22854 template<class KeyType, detail::enable_if_t<
22856 size_type count(KeyType && key) const
22857 {
22858 // return 0 for all nonobject types
22859 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22860 }
22861
22862 /// @brief check the existence of an element in a JSON object
22863 /// @sa https://json.nlohmann.me/api/basic_json/contains/
22864 bool contains(const typename object_t::key_type& key) const
22865 {
22866 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22867 }
22868
22869 /// @brief check the existence of an element in a JSON object
22870 /// @sa https://json.nlohmann.me/api/basic_json/contains/
22871 template<class KeyType, detail::enable_if_t<
22873 bool contains(KeyType && key) const
22874 {
22875 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22876 }
22877
22878 /// @brief check the existence of an element in a JSON object given a JSON pointer
22879 /// @sa https://json.nlohmann.me/api/basic_json/contains/
22880 bool contains(const json_pointer& ptr) const
22881 {
22882 return ptr.contains(this);
22883 }
22884
22885 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22886 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22887 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22888 {
22889 return ptr.contains(this);
22890 }
22891
22892 /// @}
22893
22894 ///////////////
22895 // iterators //
22896 ///////////////
22897
22898 /// @name iterators
22899 /// @{
22900
22901 /// @brief returns an iterator to the first element
22902 /// @sa https://json.nlohmann.me/api/basic_json/begin/
22903 iterator begin() noexcept
22904 {
22905 iterator result(this);
22906 result.set_begin();
22907 return result;
22908 }
22909
22910 /// @brief returns an iterator to the first element
22911 /// @sa https://json.nlohmann.me/api/basic_json/begin/
22912 const_iterator begin() const noexcept
22913 {
22914 return cbegin();
22915 }
22916
22917 /// @brief returns a const iterator to the first element
22918 /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
22919 const_iterator cbegin() const noexcept
22920 {
22921 const_iterator result(this);
22922 result.set_begin();
22923 return result;
22924 }
22925
22926 /// @brief returns an iterator to one past the last element
22927 /// @sa https://json.nlohmann.me/api/basic_json/end/
22928 iterator end() noexcept
22929 {
22930 iterator result(this);
22931 result.set_end();
22932 return result;
22933 }
22934
22935 /// @brief returns an iterator to one past the last element
22936 /// @sa https://json.nlohmann.me/api/basic_json/end/
22937 const_iterator end() const noexcept
22938 {
22939 return cend();
22940 }
22941
22942 /// @brief returns an iterator to one past the last element
22943 /// @sa https://json.nlohmann.me/api/basic_json/cend/
22944 const_iterator cend() const noexcept
22945 {
22946 const_iterator result(this);
22947 result.set_end();
22948 return result;
22949 }
22950
22951 /// @brief returns an iterator to the reverse-beginning
22952 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
22954 {
22955 return reverse_iterator(end());
22956 }
22957
22958 /// @brief returns an iterator to the reverse-beginning
22959 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
22961 {
22962 return crbegin();
22963 }
22964
22965 /// @brief returns an iterator to the reverse-end
22966 /// @sa https://json.nlohmann.me/api/basic_json/rend/
22968 {
22969 return reverse_iterator(begin());
22970 }
22971
22972 /// @brief returns an iterator to the reverse-end
22973 /// @sa https://json.nlohmann.me/api/basic_json/rend/
22975 {
22976 return crend();
22977 }
22978
22979 /// @brief returns a const reverse iterator to the last element
22980 /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
22982 {
22983 return const_reverse_iterator(cend());
22984 }
22985
22986 /// @brief returns a const reverse iterator to one before the first
22987 /// @sa https://json.nlohmann.me/api/basic_json/crend/
22989 {
22990 return const_reverse_iterator(cbegin());
22991 }
22992
22993 public:
22994 /// @brief wrapper to access iterator member functions in range-based for
22995 /// @sa https://json.nlohmann.me/api/basic_json/items/
22996 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
22997 /// version 4.0.0 of the library. Please use @ref items() instead;
22998 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
22999 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
23000 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
23001 {
23002 return ref.items();
23003 }
23004
23005 /// @brief wrapper to access iterator member functions in range-based for
23006 /// @sa https://json.nlohmann.me/api/basic_json/items/
23007 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
23008 /// version 4.0.0 of the library. Please use @ref items() instead;
23009 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
23010 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
23011 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
23012 {
23013 return ref.items();
23014 }
23015
23016 /// @brief helper to access iterator member functions in range-based for
23017 /// @sa https://json.nlohmann.me/api/basic_json/items/
23019 {
23020 return iteration_proxy<iterator>(*this);
23021 }
23022
23023 /// @brief helper to access iterator member functions in range-based for
23024 /// @sa https://json.nlohmann.me/api/basic_json/items/
23026 {
23027 return iteration_proxy<const_iterator>(*this);
23028 }
23029
23030 /// @}
23031
23032 //////////////
23033 // capacity //
23034 //////////////
23035
23036 /// @name capacity
23037 /// @{
23038
23039 /// @brief checks whether the container is empty.
23040 /// @sa https://json.nlohmann.me/api/basic_json/empty/
23041 bool empty() const noexcept
23042 {
23043 switch (m_data.m_type)
23044 {
23045 case value_t::null:
23046 {
23047 // null values are empty
23048 return true;
23049 }
23050
23051 case value_t::array:
23052 {
23053 // delegate call to array_t::empty()
23054 return m_data.m_value.array->empty();
23055 }
23056
23057 case value_t::object:
23058 {
23059 // delegate call to object_t::empty()
23060 return m_data.m_value.object->empty();
23061 }
23062
23063 case value_t::string:
23064 case value_t::boolean:
23065 case value_t::number_integer:
23066 case value_t::number_unsigned:
23067 case value_t::number_float:
23068 case value_t::binary:
23069 case value_t::discarded:
23070 default:
23071 {
23072 // all other types are nonempty
23073 return false;
23074 }
23075 }
23076 }
23077
23078 /// @brief returns the number of elements
23079 /// @sa https://json.nlohmann.me/api/basic_json/size/
23080 size_type size() const noexcept
23081 {
23082 switch (m_data.m_type)
23083 {
23084 case value_t::null:
23085 {
23086 // null values are empty
23087 return 0;
23088 }
23089
23090 case value_t::array:
23091 {
23092 // delegate call to array_t::size()
23093 return m_data.m_value.array->size();
23094 }
23095
23096 case value_t::object:
23097 {
23098 // delegate call to object_t::size()
23099 return m_data.m_value.object->size();
23100 }
23101
23102 case value_t::string:
23103 case value_t::boolean:
23104 case value_t::number_integer:
23105 case value_t::number_unsigned:
23106 case value_t::number_float:
23107 case value_t::binary:
23108 case value_t::discarded:
23109 default:
23110 {
23111 // all other types have size 1
23112 return 1;
23113 }
23114 }
23115 }
23116
23117 /// @brief returns the maximum possible number of elements
23118 /// @sa https://json.nlohmann.me/api/basic_json/max_size/
23119 size_type max_size() const noexcept
23120 {
23121 switch (m_data.m_type)
23122 {
23123 case value_t::array:
23124 {
23125 // delegate call to array_t::max_size()
23126 return m_data.m_value.array->max_size();
23127 }
23128
23129 case value_t::object:
23130 {
23131 // delegate call to object_t::max_size()
23132 return m_data.m_value.object->max_size();
23133 }
23134
23135 case value_t::null:
23136 case value_t::string:
23137 case value_t::boolean:
23138 case value_t::number_integer:
23139 case value_t::number_unsigned:
23140 case value_t::number_float:
23141 case value_t::binary:
23142 case value_t::discarded:
23143 default:
23144 {
23145 // all other types have max_size() == size()
23146 return size();
23147 }
23148 }
23149 }
23150
23151 /// @}
23152
23153 ///////////////
23154 // modifiers //
23155 ///////////////
23156
23157 /// @name modifiers
23158 /// @{
23159
23160 /// @brief clears the contents
23161 /// @sa https://json.nlohmann.me/api/basic_json/clear/
23162 void clear() noexcept
23163 {
23164 switch (m_data.m_type)
23165 {
23166 case value_t::number_integer:
23167 {
23168 m_data.m_value.number_integer = 0;
23169 break;
23170 }
23171
23172 case value_t::number_unsigned:
23173 {
23174 m_data.m_value.number_unsigned = 0;
23175 break;
23176 }
23177
23178 case value_t::number_float:
23179 {
23180 m_data.m_value.number_float = 0.0;
23181 break;
23182 }
23183
23184 case value_t::boolean:
23185 {
23186 m_data.m_value.boolean = false;
23187 break;
23188 }
23189
23190 case value_t::string:
23191 {
23192 m_data.m_value.string->clear();
23193 break;
23194 }
23195
23196 case value_t::binary:
23197 {
23198 m_data.m_value.binary->clear();
23199 break;
23200 }
23201
23202 case value_t::array:
23203 {
23204 m_data.m_value.array->clear();
23205 break;
23206 }
23207
23208 case value_t::object:
23209 {
23210 m_data.m_value.object->clear();
23211 break;
23212 }
23213
23214 case value_t::null:
23215 case value_t::discarded:
23216 default:
23217 break;
23218 }
23219 }
23220
23221 /// @brief add an object to an array
23222 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
23224 {
23225 // push_back only works for null objects or arrays
23226 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23227 {
23228 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23229 }
23230
23231 // transform a null object into an array
23232 if (is_null())
23233 {
23234 m_data.m_type = value_t::array;
23235 m_data.m_value = value_t::array;
23236 assert_invariant();
23237 }
23238
23239 // add the element to the array (move semantics)
23240 const auto old_capacity = m_data.m_value.array->capacity();
23241 m_data.m_value.array->push_back(std::move(val));
23242 set_parent(m_data.m_value.array->back(), old_capacity);
23243 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
23244 }
23245
23246 /// @brief add an object to an array
23247 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
23249 {
23250 push_back(std::move(val));
23251 return *this;
23252 }
23253
23254 /// @brief add an object to an array
23255 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
23256 void push_back(const basic_json& val)
23257 {
23258 // push_back only works for null objects or arrays
23259 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23260 {
23261 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23262 }
23263
23264 // transform a null object into an array
23265 if (is_null())
23266 {
23267 m_data.m_type = value_t::array;
23268 m_data.m_value = value_t::array;
23269 assert_invariant();
23270 }
23271
23272 // add the element to the array
23273 const auto old_capacity = m_data.m_value.array->capacity();
23274 m_data.m_value.array->push_back(val);
23275 set_parent(m_data.m_value.array->back(), old_capacity);
23276 }
23277
23278 /// @brief add an object to an array
23279 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
23281 {
23282 push_back(val);
23283 return *this;
23284 }
23285
23286 /// @brief add an object to an object
23287 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
23288 void push_back(const typename object_t::value_type& val)
23289 {
23290 // push_back only works for null objects or objects
23291 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23292 {
23293 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23294 }
23295
23296 // transform a null object into an object
23297 if (is_null())
23298 {
23299 m_data.m_type = value_t::object;
23300 m_data.m_value = value_t::object;
23301 assert_invariant();
23302 }
23303
23304 // add the element to the object
23305 auto res = m_data.m_value.object->insert(val);
23306 set_parent(res.first->second);
23307 }
23308
23309 /// @brief add an object to an object
23310 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
23311 reference operator+=(const typename object_t::value_type& val)
23312 {
23313 push_back(val);
23314 return *this;
23315 }
23316
23317 /// @brief add an object to an object
23318 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
23320 {
23321 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
23322 {
23323 basic_json&& key = init.begin()->moved_or_copied();
23324 push_back(typename object_t::value_type(
23325 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
23326 }
23327 else
23328 {
23329 push_back(basic_json(init));
23330 }
23331 }
23332
23333 /// @brief add an object to an object
23334 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
23336 {
23337 push_back(init);
23338 return *this;
23339 }
23340
23341 /// @brief add an object to an array
23342 /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
23343 template<class... Args>
23344 reference emplace_back(Args&& ... args)
23345 {
23346 // emplace_back only works for null objects or arrays
23347 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23348 {
23349 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
23350 }
23351
23352 // transform a null object into an array
23353 if (is_null())
23354 {
23355 m_data.m_type = value_t::array;
23356 m_data.m_value = value_t::array;
23357 assert_invariant();
23358 }
23359
23360 // add the element to the array (perfect forwarding)
23361 const auto old_capacity = m_data.m_value.array->capacity();
23362 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
23363 return set_parent(m_data.m_value.array->back(), old_capacity);
23364 }
23365
23366 /// @brief add an object to an object if key does not exist
23367 /// @sa https://json.nlohmann.me/api/basic_json/emplace/
23368 template<class... Args>
23369 std::pair<iterator, bool> emplace(Args&& ... args)
23370 {
23371 // emplace only works for null objects or arrays
23372 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23373 {
23374 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
23375 }
23376
23377 // transform a null object into an object
23378 if (is_null())
23379 {
23380 m_data.m_type = value_t::object;
23381 m_data.m_value = value_t::object;
23382 assert_invariant();
23383 }
23384
23385 // add the element to the array (perfect forwarding)
23386 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
23387 set_parent(res.first->second);
23388
23389 // create a result iterator and set iterator to the result of emplace
23390 auto it = begin();
23391 it.m_it.object_iterator = res.first;
23392
23393 // return pair of iterator and boolean
23394 return {it, res.second};
23395 }
23396
23397 /// Helper for insertion of an iterator
23398 /// @note: This uses std::distance to support GCC 4.8,
23399 /// see https://github.com/nlohmann/json/pull/1257
23400 template<typename... Args>
23401 iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
23402 {
23403 iterator result(this);
23404 JSON_ASSERT(m_data.m_value.array != nullptr);
23405
23406 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
23407 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
23408 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
23409
23410 // This could have been written as:
23411 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
23412 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
23413
23414 set_parents();
23415 return result;
23416 }
23417
23418 /// @brief inserts element into array
23419 /// @sa https://json.nlohmann.me/api/basic_json/insert/
23420 iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23421 {
23422 // insert only works for arrays
23423 if (JSON_HEDLEY_LIKELY(is_array()))
23424 {
23425 // check if iterator pos fits to this JSON value
23426 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23427 {
23428 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23429 }
23430
23431 // insert to array and return iterator
23432 return insert_iterator(pos, val);
23433 }
23434
23435 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23436 }
23437
23438 /// @brief inserts element into array
23439 /// @sa https://json.nlohmann.me/api/basic_json/insert/
23440 iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
23441 {
23442 return insert(pos, val);
23443 }
23444
23445 /// @brief inserts copies of element into array
23446 /// @sa https://json.nlohmann.me/api/basic_json/insert/
23447 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23448 {
23449 // insert only works for arrays
23450 if (JSON_HEDLEY_LIKELY(is_array()))
23451 {
23452 // check if iterator pos fits to this JSON value
23453 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23454 {
23455 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23456 }
23457
23458 // insert to array and return iterator
23459 return insert_iterator(pos, cnt, val);
23460 }
23461
23462 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23463 }
23464
23465 /// @brief inserts range of elements into array
23466 /// @sa https://json.nlohmann.me/api/basic_json/insert/
23467 iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23468 {
23469 // insert only works for arrays
23470 if (JSON_HEDLEY_UNLIKELY(!is_array()))
23471 {
23472 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23473 }
23474
23475 // check if iterator pos fits to this JSON value
23476 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23477 {
23478 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23479 }
23480
23481 // check if range iterators belong to the same JSON object
23482 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23483 {
23484 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23485 }
23486
23487 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
23488 {
23489 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
23490 }
23491
23492 // insert to array and return iterator
23493 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
23494 }
23495
23496 /// @brief inserts elements from initializer list into array
23497 /// @sa https://json.nlohmann.me/api/basic_json/insert/
23498 iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
23499 {
23500 // insert only works for arrays
23501 if (JSON_HEDLEY_UNLIKELY(!is_array()))
23502 {
23503 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23504 }
23505
23506 // check if iterator pos fits to this JSON value
23507 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23508 {
23509 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23510 }
23511
23512 // insert to array and return iterator
23513 return insert_iterator(pos, ilist.begin(), ilist.end());
23514 }
23515
23516 /// @brief inserts range of elements into object
23517 /// @sa https://json.nlohmann.me/api/basic_json/insert/
23518 void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23519 {
23520 // insert only works for objects
23521 if (JSON_HEDLEY_UNLIKELY(!is_object()))
23522 {
23523 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23524 }
23525
23526 // check if range iterators belong to the same JSON object
23527 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23528 {
23529 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23530 }
23531
23532 // passed iterators must belong to objects
23533 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23534 {
23535 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
23536 }
23537
23538 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
23539 set_parents();
23540 }
23541
23542 /// @brief updates a JSON object from another object, overwriting existing keys
23543 /// @sa https://json.nlohmann.me/api/basic_json/update/
23544 void update(const_reference j, bool merge_objects = false)
23545 {
23546 update(j.begin(), j.end(), merge_objects);
23547 }
23548
23549 /// @brief updates a JSON object from another object, overwriting existing keys
23550 /// @sa https://json.nlohmann.me/api/basic_json/update/
23551 void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
23552 {
23553 // implicitly convert a null value to an empty object
23554 if (is_null())
23555 {
23556 m_data.m_type = value_t::object;
23557 m_data.m_value.object = create<object_t>();
23558 assert_invariant();
23559 }
23560
23561 if (JSON_HEDLEY_UNLIKELY(!is_object()))
23562 {
23563 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
23564 }
23565
23566 // check if range iterators belong to the same JSON object
23567 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23568 {
23569 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23570 }
23571
23572 // passed iterators must belong to objects
23573 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23574 {
23575 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
23576 }
23577
23578 for (auto it = first; it != last; ++it)
23579 {
23580 if (merge_objects && it.value().is_object())
23581 {
23582 auto it2 = m_data.m_value.object->find(it.key());
23583 if (it2 != m_data.m_value.object->end())
23584 {
23585 it2->second.update(it.value(), true);
23586 continue;
23587 }
23588 }
23589 m_data.m_value.object->operator[](it.key()) = it.value();
23590#if JSON_DIAGNOSTICS
23591 m_data.m_value.object->operator[](it.key()).m_parent = this;
23592#endif
23593 }
23594 }
23595
23596 /// @brief exchanges the values
23597 /// @sa https://json.nlohmann.me/api/basic_json/swap/
23598 void swap(reference other) noexcept (
23599 std::is_nothrow_move_constructible<value_t>::value&&
23600 std::is_nothrow_move_assignable<value_t>::value&&
23601 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23602 std::is_nothrow_move_assignable<json_value>::value
23603 )
23604 {
23605 std::swap(m_data.m_type, other.m_data.m_type);
23606 std::swap(m_data.m_value, other.m_data.m_value);
23607
23608 set_parents();
23609 other.set_parents();
23610 assert_invariant();
23611 }
23612
23613 /// @brief exchanges the values
23614 /// @sa https://json.nlohmann.me/api/basic_json/swap/
23615 friend void swap(reference left, reference right) noexcept (
23616 std::is_nothrow_move_constructible<value_t>::value&&
23617 std::is_nothrow_move_assignable<value_t>::value&&
23618 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23619 std::is_nothrow_move_assignable<json_value>::value
23620 )
23621 {
23622 left.swap(right);
23623 }
23624
23625 /// @brief exchanges the values
23626 /// @sa https://json.nlohmann.me/api/basic_json/swap/
23627 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23628 {
23629 // swap only works for arrays
23630 if (JSON_HEDLEY_LIKELY(is_array()))
23631 {
23632 using std::swap;
23633 swap(*(m_data.m_value.array), other);
23634 }
23635 else
23636 {
23637 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
23638 }
23639 }
23640
23641 /// @brief exchanges the values
23642 /// @sa https://json.nlohmann.me/api/basic_json/swap/
23643 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23644 {
23645 // swap only works for objects
23646 if (JSON_HEDLEY_LIKELY(is_object()))
23647 {
23648 using std::swap;
23649 swap(*(m_data.m_value.object), other);
23650 }
23651 else
23652 {
23653 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
23654 }
23655 }
23656
23657 /// @brief exchanges the values
23658 /// @sa https://json.nlohmann.me/api/basic_json/swap/
23659 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23660 {
23661 // swap only works for strings
23662 if (JSON_HEDLEY_LIKELY(is_string()))
23663 {
23664 using std::swap;
23665 swap(*(m_data.m_value.string), other);
23666 }
23667 else
23668 {
23669 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
23670 }
23671 }
23672
23673 /// @brief exchanges the values
23674 /// @sa https://json.nlohmann.me/api/basic_json/swap/
23675 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23676 {
23677 // swap only works for strings
23678 if (JSON_HEDLEY_LIKELY(is_binary()))
23679 {
23680 using std::swap;
23681 swap(*(m_data.m_value.binary), other);
23682 }
23683 else
23684 {
23685 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
23686 }
23687 }
23688
23689 /// @brief exchanges the values
23690 /// @sa https://json.nlohmann.me/api/basic_json/swap/
23691 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
23692 {
23693 // swap only works for strings
23694 if (JSON_HEDLEY_LIKELY(is_binary()))
23695 {
23696 using std::swap;
23697 swap(*(m_data.m_value.binary), other);
23698 }
23699 else
23700 {
23701 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
23702 }
23703 }
23704
23705 /// @}
23706
23707 //////////////////////////////////////////
23708 // lexicographical comparison operators //
23709 //////////////////////////////////////////
23710
23711 /// @name lexicographical comparison operators
23712 /// @{
23713
23714 // note parentheses around operands are necessary; see
23715 // https://github.com/nlohmann/json/issues/1530
23716#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
23717 const auto lhs_type = lhs.type(); \
23718 const auto rhs_type = rhs.type(); \
23719 \
23720 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
23721 { \
23722 switch (lhs_type) \
23723 { \
23724 case value_t::array: \
23725 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
23726 \
23727 case value_t::object: \
23728 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
23729 \
23730 case value_t::null: \
23731 return (null_result); \
23732 \
23733 case value_t::string: \
23734 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
23735 \
23736 case value_t::boolean: \
23737 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
23738 \
23739 case value_t::number_integer: \
23740 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
23741 \
23742 case value_t::number_unsigned: \
23743 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
23744 \
23745 case value_t::number_float: \
23746 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
23747 \
23748 case value_t::binary: \
23749 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
23750 \
23751 case value_t::discarded: \
23752 default: \
23753 return (unordered_result); \
23754 } \
23755 } \
23756 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
23757 { \
23758 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
23759 } \
23760 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
23761 { \
23762 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
23763 } \
23764 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
23765 { \
23766 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
23767 } \
23768 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
23769 { \
23770 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
23771 } \
23772 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
23773 { \
23774 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
23775 } \
23776 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
23777 { \
23778 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
23779 } \
23780 else if(compares_unordered(lhs, rhs))\
23781 {\
23782 return (unordered_result);\
23783 }\
23784 \
23785 return (default_result);
23786
23788 // returns true if:
23789 // - any operand is NaN and the other operand is of number type
23790 // - any operand is discarded
23791 // in legacy mode, discarded values are considered ordered if
23792 // an operation is computed as an odd number of inverses of others
23793 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
23794 {
23795 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
23796 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
23797 {
23798 return true;
23799 }
23800#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23801 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
23802#else
23803 static_cast<void>(inverse);
23804 return lhs.is_discarded() || rhs.is_discarded();
23805#endif
23806 }
23807
23808 private:
23809 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
23810 {
23811 return compares_unordered(*this, rhs, inverse);
23812 }
23813
23814 public:
23815#if JSON_HAS_THREE_WAY_COMPARISON
23816 /// @brief comparison: equal
23817 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23818 bool operator==(const_reference rhs) const noexcept
23819 {
23820#ifdef __GNUC__
23821#pragma GCC diagnostic push
23822#pragma GCC diagnostic ignored "-Wfloat-equal"
23823#endif
23824 const_reference lhs = *this;
23825 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23826#ifdef __GNUC__
23827#pragma GCC diagnostic pop
23828#endif
23829 }
23830
23831 /// @brief comparison: equal
23832 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23833 template<typename ScalarType>
23834 requires std::is_scalar_v<ScalarType>
23835 bool operator==(ScalarType rhs) const noexcept
23836 {
23837 return *this == basic_json(rhs);
23838 }
23839
23840 /// @brief comparison: not equal
23841 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23842 bool operator!=(const_reference rhs) const noexcept
23843 {
23844 if (compares_unordered(rhs, true))
23845 {
23846 return false;
23847 }
23848 return !operator==(rhs);
23849 }
23850
23851 /// @brief comparison: 3-way
23852 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
23853 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23854 {
23855 const_reference lhs = *this;
23856 // default_result is used if we cannot compare values. In that case,
23857 // we compare types.
23858 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23859 std::partial_ordering::equivalent,
23860 std::partial_ordering::unordered,
23861 lhs_type <=> rhs_type) // *NOPAD*
23862 }
23863
23864 /// @brief comparison: 3-way
23865 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
23866 template<typename ScalarType>
23867 requires std::is_scalar_v<ScalarType>
23868 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23869 {
23870 return *this <=> basic_json(rhs); // *NOPAD*
23871 }
23872
23873#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23874 // all operators that are computed as an odd number of inverses of others
23875 // need to be overloaded to emulate the legacy comparison behavior
23876
23877 /// @brief comparison: less than or equal
23878 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23880 bool operator<=(const_reference rhs) const noexcept
23881 {
23882 if (compares_unordered(rhs, true))
23883 {
23884 return false;
23885 }
23886 return !(rhs < *this);
23887 }
23888
23889 /// @brief comparison: less than or equal
23890 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23891 template<typename ScalarType>
23892 requires std::is_scalar_v<ScalarType>
23893 bool operator<=(ScalarType rhs) const noexcept
23894 {
23895 return *this <= basic_json(rhs);
23896 }
23897
23898 /// @brief comparison: greater than or equal
23899 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23901 bool operator>=(const_reference rhs) const noexcept
23902 {
23903 if (compares_unordered(rhs, true))
23904 {
23905 return false;
23906 }
23907 return !(*this < rhs);
23908 }
23909
23910 /// @brief comparison: greater than or equal
23911 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23912 template<typename ScalarType>
23913 requires std::is_scalar_v<ScalarType>
23914 bool operator>=(ScalarType rhs) const noexcept
23915 {
23916 return *this >= basic_json(rhs);
23917 }
23918#endif
23919#else
23920 /// @brief comparison: equal
23921 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23922 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23923 {
23924#ifdef __GNUC__
23925#pragma GCC diagnostic push
23926#pragma GCC diagnostic ignored "-Wfloat-equal"
23927#endif
23928 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23929#ifdef __GNUC__
23930#pragma GCC diagnostic pop
23931#endif
23932 }
23933
23934 /// @brief comparison: equal
23935 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23936 template<typename ScalarType, typename std::enable_if<
23937 std::is_scalar<ScalarType>::value, int>::type = 0>
23938 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23939 {
23940 return lhs == basic_json(rhs);
23941 }
23942
23943 /// @brief comparison: equal
23944 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23945 template<typename ScalarType, typename std::enable_if<
23946 std::is_scalar<ScalarType>::value, int>::type = 0>
23947 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23948 {
23949 return basic_json(lhs) == rhs;
23950 }
23951
23952 /// @brief comparison: not equal
23953 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23954 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23955 {
23956 if (compares_unordered(lhs, rhs, true))
23957 {
23958 return false;
23959 }
23960 return !(lhs == rhs);
23961 }
23962
23963 /// @brief comparison: not equal
23964 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23965 template<typename ScalarType, typename std::enable_if<
23966 std::is_scalar<ScalarType>::value, int>::type = 0>
23967 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23968 {
23969 return lhs != basic_json(rhs);
23970 }
23971
23972 /// @brief comparison: not equal
23973 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23974 template<typename ScalarType, typename std::enable_if<
23975 std::is_scalar<ScalarType>::value, int>::type = 0>
23976 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23977 {
23978 return basic_json(lhs) != rhs;
23979 }
23980
23981 /// @brief comparison: less than
23982 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23983 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23984 {
23985 // default_result is used if we cannot compare values. In that case,
23986 // we compare types. Note we have to call the operator explicitly,
23987 // because MSVC has problems otherwise.
23988 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23989 }
23990
23991 /// @brief comparison: less than
23992 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23993 template<typename ScalarType, typename std::enable_if<
23994 std::is_scalar<ScalarType>::value, int>::type = 0>
23995 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23996 {
23997 return lhs < basic_json(rhs);
23998 }
23999
24000 /// @brief comparison: less than
24001 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
24002 template<typename ScalarType, typename std::enable_if<
24003 std::is_scalar<ScalarType>::value, int>::type = 0>
24004 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
24005 {
24006 return basic_json(lhs) < rhs;
24007 }
24008
24009 /// @brief comparison: less than or equal
24010 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
24011 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
24012 {
24013 if (compares_unordered(lhs, rhs, true))
24014 {
24015 return false;
24016 }
24017 return !(rhs < lhs);
24018 }
24019
24020 /// @brief comparison: less than or equal
24021 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
24022 template<typename ScalarType, typename std::enable_if<
24023 std::is_scalar<ScalarType>::value, int>::type = 0>
24024 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
24025 {
24026 return lhs <= basic_json(rhs);
24027 }
24028
24029 /// @brief comparison: less than or equal
24030 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
24031 template<typename ScalarType, typename std::enable_if<
24032 std::is_scalar<ScalarType>::value, int>::type = 0>
24033 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
24034 {
24035 return basic_json(lhs) <= rhs;
24036 }
24037
24038 /// @brief comparison: greater than
24039 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
24040 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
24041 {
24042 // double inverse
24043 if (compares_unordered(lhs, rhs))
24044 {
24045 return false;
24046 }
24047 return !(lhs <= rhs);
24048 }
24049
24050 /// @brief comparison: greater than
24051 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
24052 template<typename ScalarType, typename std::enable_if<
24053 std::is_scalar<ScalarType>::value, int>::type = 0>
24054 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
24055 {
24056 return lhs > basic_json(rhs);
24057 }
24058
24059 /// @brief comparison: greater than
24060 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
24061 template<typename ScalarType, typename std::enable_if<
24062 std::is_scalar<ScalarType>::value, int>::type = 0>
24063 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
24064 {
24065 return basic_json(lhs) > rhs;
24066 }
24067
24068 /// @brief comparison: greater than or equal
24069 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
24070 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
24071 {
24072 if (compares_unordered(lhs, rhs, true))
24073 {
24074 return false;
24075 }
24076 return !(lhs < rhs);
24077 }
24078
24079 /// @brief comparison: greater than or equal
24080 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
24081 template<typename ScalarType, typename std::enable_if<
24082 std::is_scalar<ScalarType>::value, int>::type = 0>
24083 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
24084 {
24085 return lhs >= basic_json(rhs);
24086 }
24087
24088 /// @brief comparison: greater than or equal
24089 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
24090 template<typename ScalarType, typename std::enable_if<
24091 std::is_scalar<ScalarType>::value, int>::type = 0>
24092 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
24093 {
24094 return basic_json(lhs) >= rhs;
24095 }
24096#endif
24097
24098#undef JSON_IMPLEMENT_OPERATOR
24099
24100 /// @}
24101
24102 ///////////////////
24103 // serialization //
24104 ///////////////////
24105
24106 /// @name serialization
24107 /// @{
24108#ifndef JSON_NO_IO
24109 /// @brief serialize to stream
24110 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
24111 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
24112 {
24113 // read width member and use it as the indentation parameter if nonzero
24114 const bool pretty_print = o.width() > 0;
24115 const auto indentation = pretty_print ? o.width() : 0;
24116
24117 // reset width to 0 for subsequent calls to this stream
24118 o.width(0);
24119
24120 // do the actual serialization
24121 serializer s(detail::output_adapter<char>(o), o.fill());
24122 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
24123 return o;
24124 }
24125
24126 /// @brief serialize to stream
24127 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
24128 /// @deprecated This function is deprecated since 3.0.0 and will be removed in
24129 /// version 4.0.0 of the library. Please use
24130 /// operator<<(std::ostream&, const basic_json&) instead; that is,
24131 /// replace calls like `j >> o;` with `o << j;`.
24132 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
24133 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
24134 {
24135 return o << j;
24136 }
24137#endif // JSON_NO_IO
24138 /// @}
24139
24140 /////////////////////
24141 // deserialization //
24142 /////////////////////
24143
24144 /// @name deserialization
24145 /// @{
24146
24147 /// @brief deserialize from a compatible input
24148 /// @sa https://json.nlohmann.me/api/basic_json/parse/
24149 template<typename InputType>
24151 static basic_json parse(InputType&& i,
24152 parser_callback_t cb = nullptr,
24153 const bool allow_exceptions = true,
24154 const bool ignore_comments = false,
24155 const bool ignore_trailing_commas = false)
24156 {
24157 basic_json result;
24158 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]
24159 return result;
24160 }
24161
24162 /// @brief deserialize from a pair of character iterators
24163 /// @sa https://json.nlohmann.me/api/basic_json/parse/
24164 template<typename IteratorType>
24166 static basic_json parse(IteratorType first,
24167 IteratorType last,
24168 parser_callback_t cb = nullptr,
24169 const bool allow_exceptions = true,
24170 const bool ignore_comments = false,
24171 const bool ignore_trailing_commas = false)
24172 {
24173 basic_json result;
24174 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]
24175 return result;
24176 }
24177
24179 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
24180 static basic_json parse(detail::span_input_adapter&& i,
24181 parser_callback_t cb = nullptr,
24182 const bool allow_exceptions = true,
24183 const bool ignore_comments = false,
24184 const bool ignore_trailing_commas = false)
24185 {
24186 basic_json result;
24187 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
24188 return result;
24189 }
24190
24191 /// @brief check if the input is valid JSON
24192 /// @sa https://json.nlohmann.me/api/basic_json/accept/
24193 template<typename InputType>
24194 static bool accept(InputType&& i,
24195 const bool ignore_comments = false,
24196 const bool ignore_trailing_commas = false)
24197 {
24198 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24199 }
24200
24201 /// @brief check if the input is valid JSON
24202 /// @sa https://json.nlohmann.me/api/basic_json/accept/
24203 template<typename IteratorType>
24204 static bool accept(IteratorType first, IteratorType last,
24205 const bool ignore_comments = false,
24206 const bool ignore_trailing_commas = false)
24207 {
24208 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24209 }
24210
24212 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
24213 static bool accept(detail::span_input_adapter&& i,
24214 const bool ignore_comments = false,
24215 const bool ignore_trailing_commas = false)
24216 {
24217 return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24218 }
24219
24220 /// @brief generate SAX events
24221 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
24222 template <typename InputType, typename SAX>
24224 static bool sax_parse(InputType&& i, SAX* sax,
24226 const bool strict = true,
24227 const bool ignore_comments = false,
24228 const bool ignore_trailing_commas = false)
24229 {
24230 auto ia = detail::input_adapter(std::forward<InputType>(i));
24231 return format == input_format_t::json
24232 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24233 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24234 }
24235
24236 /// @brief generate SAX events
24237 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
24238 template<class IteratorType, class SAX>
24240 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
24242 const bool strict = true,
24243 const bool ignore_comments = false,
24244 const bool ignore_trailing_commas = false)
24245 {
24246 auto ia = detail::input_adapter(std::move(first), std::move(last));
24247 return format == input_format_t::json
24248 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24249 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24250 }
24251
24252 /// @brief generate SAX events
24253 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
24254 /// @deprecated This function is deprecated since 3.8.0 and will be removed in
24255 /// version 4.0.0 of the library. Please use
24256 /// sax_parse(ptr, ptr + len) instead.
24257 template <typename SAX>
24258 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
24260 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
24262 const bool strict = true,
24263 const bool ignore_comments = false,
24264 const bool ignore_trailing_commas = false)
24265 {
24266 auto ia = i.get();
24267 return format == input_format_t::json
24268 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24269 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24270 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24271 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24272 }
24273#ifndef JSON_NO_IO
24274 /// @brief deserialize from stream
24275 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
24276 /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
24277 /// version 4.0.0 of the library. Please use
24278 /// operator>>(std::istream&, basic_json&) instead; that is,
24279 /// replace calls like `j << i;` with `i >> j;`.
24280 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
24281 friend std::istream& operator<<(basic_json& j, std::istream& i)
24282 {
24283 return operator>>(i, j);
24284 }
24285
24286 /// @brief deserialize from stream
24287 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
24288 friend std::istream& operator>>(std::istream& i, basic_json& j)
24289 {
24290 parser(detail::input_adapter(i)).parse(false, j);
24291 return i;
24292 }
24293#endif // JSON_NO_IO
24294 /// @}
24295
24296 ///////////////////////////
24297 // convenience functions //
24298 ///////////////////////////
24299
24300 /// @brief return the type as string
24301 /// @sa https://json.nlohmann.me/api/basic_json/type_name/
24303 const char* type_name() const noexcept
24304 {
24305 switch (m_data.m_type)
24306 {
24307 case value_t::null:
24308 return "null";
24309 case value_t::object:
24310 return "object";
24311 case value_t::array:
24312 return "array";
24313 case value_t::string:
24314 return "string";
24315 case value_t::boolean:
24316 return "boolean";
24317 case value_t::binary:
24318 return "binary";
24319 case value_t::discarded:
24320 return "discarded";
24321 case value_t::number_integer:
24322 case value_t::number_unsigned:
24323 case value_t::number_float:
24324 return "number";
24325 default:
24326 return "invalid";
24327 }
24328 }
24329
24331 //////////////////////
24332 // member variables //
24333 //////////////////////
24334
24335 struct data
24336 {
24337 /// the type of the current element
24338 value_t m_type = value_t::null;
24339
24340 /// the value of the current element
24341 json_value m_value = {};
24342
24343 data(const value_t v)
24344 : m_type(v), m_value(v)
24345 {
24346 }
24347
24348 data(size_type cnt, const basic_json& val)
24349 : m_type(value_t::array)
24350 {
24351 m_value.array = create<array_t>(cnt, val);
24352 }
24353
24354 data() noexcept = default;
24355 data(data&&) noexcept = default;
24356 data(const data&) noexcept = delete;
24357 data& operator=(data&&) noexcept = delete;
24358 data& operator=(const data&) noexcept = delete;
24359
24360 ~data() noexcept
24361 {
24362 m_value.destroy(m_type);
24363 }
24364 };
24365
24366 data m_data = {};
24367
24368#if JSON_DIAGNOSTICS
24369 /// a pointer to a parent value (for debugging purposes)
24370 basic_json* m_parent = nullptr;
24371#endif
24372
24373#if JSON_DIAGNOSTIC_POSITIONS
24374 /// the start position of the value
24375 std::size_t start_position = std::string::npos;
24376 /// the end position of the value
24377 std::size_t end_position = std::string::npos;
24378 public:
24379 constexpr std::size_t start_pos() const noexcept
24380 {
24381 return start_position;
24382 }
24383
24384 constexpr std::size_t end_pos() const noexcept
24385 {
24386 return end_position;
24387 }
24388#endif
24389
24390 //////////////////////////////////////////
24391 // binary serialization/deserialization //
24392 //////////////////////////////////////////
24393
24394 /// @name binary serialization/deserialization support
24395 /// @{
24396
24397 public:
24398 /// @brief create a CBOR serialization of a given JSON value
24399 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
24400 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
24401 {
24402 std::vector<std::uint8_t> result;
24403 to_cbor(j, result);
24404 return result;
24405 }
24406
24407 /// @brief create a CBOR serialization of a given JSON value
24408 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
24410 {
24411 binary_writer<std::uint8_t>(o).write_cbor(j);
24412 }
24413
24414 /// @brief create a CBOR serialization of a given JSON value
24415 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
24417 {
24418 binary_writer<char>(o).write_cbor(j);
24419 }
24420
24421 /// @brief create a MessagePack serialization of a given JSON value
24422 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
24423 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
24424 {
24425 std::vector<std::uint8_t> result;
24426 to_msgpack(j, result);
24427 return result;
24428 }
24429
24430 /// @brief create a MessagePack serialization of a given JSON value
24431 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
24433 {
24434 binary_writer<std::uint8_t>(o).write_msgpack(j);
24435 }
24436
24437 /// @brief create a MessagePack serialization of a given JSON value
24438 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
24440 {
24441 binary_writer<char>(o).write_msgpack(j);
24442 }
24443
24444 /// @brief create a UBJSON serialization of a given JSON value
24445 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
24446 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
24447 const bool use_size = false,
24448 const bool use_type = false)
24449 {
24450 std::vector<std::uint8_t> result;
24451 to_ubjson(j, result, use_size, use_type);
24452 return result;
24453 }
24454
24455 /// @brief create a UBJSON serialization of a given JSON value
24456 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
24458 const bool use_size = false, const bool use_type = false)
24459 {
24460 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
24461 }
24462
24463 /// @brief create a UBJSON serialization of a given JSON value
24464 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
24466 const bool use_size = false, const bool use_type = false)
24467 {
24468 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
24469 }
24470
24471 /// @brief create a BJData serialization of a given JSON value
24472 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
24473 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
24474 const bool use_size = false,
24475 const bool use_type = false,
24476 const bjdata_version_t version = bjdata_version_t::draft2)
24477 {
24478 std::vector<std::uint8_t> result;
24479 to_bjdata(j, result, use_size, use_type, version);
24480 return result;
24481 }
24482
24483 /// @brief create a BJData serialization of a given JSON value
24484 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
24486 const bool use_size = false, const bool use_type = false,
24487 const bjdata_version_t version = bjdata_version_t::draft2)
24488 {
24489 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true, version);
24490 }
24491
24492 /// @brief create a BJData serialization of a given JSON value
24493 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
24495 const bool use_size = false, const bool use_type = false,
24496 const bjdata_version_t version = bjdata_version_t::draft2)
24497 {
24498 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true, version);
24499 }
24500
24501 /// @brief create a BSON serialization of a given JSON value
24502 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
24503 static std::vector<std::uint8_t> to_bson(const basic_json& j)
24504 {
24505 std::vector<std::uint8_t> result;
24506 to_bson(j, result);
24507 return result;
24508 }
24509
24510 /// @brief create a BSON serialization of a given JSON value
24511 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
24513 {
24514 binary_writer<std::uint8_t>(o).write_bson(j);
24515 }
24516
24517 /// @brief create a BSON serialization of a given JSON value
24518 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
24520 {
24521 binary_writer<char>(o).write_bson(j);
24522 }
24523
24524 /// @brief create a JSON value from an input in CBOR format
24525 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
24526 template<typename InputType>
24528 static basic_json from_cbor(InputType&& i,
24529 const bool strict = true,
24530 const bool allow_exceptions = true,
24531 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24532 {
24533 basic_json result;
24534 auto ia = detail::input_adapter(std::forward<InputType>(i));
24535 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24536 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]
24537 return res ? result : basic_json(value_t::discarded);
24538 }
24539
24540 /// @brief create a JSON value from an input in CBOR format
24541 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
24542 template<typename IteratorType>
24544 static basic_json from_cbor(IteratorType first, IteratorType last,
24545 const bool strict = true,
24546 const bool allow_exceptions = true,
24547 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24548 {
24549 basic_json result;
24550 auto ia = detail::input_adapter(std::move(first), std::move(last));
24551 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24552 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]
24553 return res ? result : basic_json(value_t::discarded);
24554 }
24555
24556 template<typename T>
24558 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24559 static basic_json from_cbor(const T* ptr, std::size_t len,
24560 const bool strict = true,
24561 const bool allow_exceptions = true,
24562 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24563 {
24564 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
24565 }
24566
24568 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24569 static basic_json from_cbor(detail::span_input_adapter&& i,
24570 const bool strict = true,
24571 const bool allow_exceptions = true,
24572 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24573 {
24574 basic_json result;
24575 auto ia = i.get();
24576 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24577 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24578 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]
24579 return res ? result : basic_json(value_t::discarded);
24580 }
24581
24582 /// @brief create a JSON value from an input in MessagePack format
24583 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
24584 template<typename InputType>
24586 static basic_json from_msgpack(InputType&& i,
24587 const bool strict = true,
24588 const bool allow_exceptions = true)
24589 {
24590 basic_json result;
24591 auto ia = detail::input_adapter(std::forward<InputType>(i));
24592 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24593 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]
24594 return res ? result : basic_json(value_t::discarded);
24595 }
24596
24597 /// @brief create a JSON value from an input in MessagePack format
24598 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
24599 template<typename IteratorType>
24601 static basic_json from_msgpack(IteratorType first, IteratorType last,
24602 const bool strict = true,
24603 const bool allow_exceptions = true)
24604 {
24605 basic_json result;
24606 auto ia = detail::input_adapter(std::move(first), std::move(last));
24607 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24608 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]
24609 return res ? result : basic_json(value_t::discarded);
24610 }
24611
24612 template<typename T>
24614 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24615 static basic_json from_msgpack(const T* ptr, std::size_t len,
24616 const bool strict = true,
24617 const bool allow_exceptions = true)
24618 {
24619 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
24620 }
24621
24623 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24624 static basic_json from_msgpack(detail::span_input_adapter&& i,
24625 const bool strict = true,
24626 const bool allow_exceptions = true)
24627 {
24628 basic_json result;
24629 auto ia = i.get();
24630 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24631 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24632 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]
24633 return res ? result : basic_json(value_t::discarded);
24634 }
24635
24636 /// @brief create a JSON value from an input in UBJSON format
24637 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
24638 template<typename InputType>
24640 static basic_json from_ubjson(InputType&& i,
24641 const bool strict = true,
24642 const bool allow_exceptions = true)
24643 {
24644 basic_json result;
24645 auto ia = detail::input_adapter(std::forward<InputType>(i));
24646 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24647 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]
24648 return res ? result : basic_json(value_t::discarded);
24649 }
24650
24651 /// @brief create a JSON value from an input in UBJSON format
24652 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
24653 template<typename IteratorType>
24655 static basic_json from_ubjson(IteratorType first, IteratorType last,
24656 const bool strict = true,
24657 const bool allow_exceptions = true)
24658 {
24659 basic_json result;
24660 auto ia = detail::input_adapter(std::move(first), std::move(last));
24661 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24662 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]
24663 return res ? result : basic_json(value_t::discarded);
24664 }
24665
24666 template<typename T>
24668 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24669 static basic_json from_ubjson(const T* ptr, std::size_t len,
24670 const bool strict = true,
24671 const bool allow_exceptions = true)
24672 {
24673 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24674 }
24675
24677 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24678 static basic_json from_ubjson(detail::span_input_adapter&& i,
24679 const bool strict = true,
24680 const bool allow_exceptions = true)
24681 {
24682 basic_json result;
24683 auto ia = i.get();
24684 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24685 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24686 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]
24687 return res ? result : basic_json(value_t::discarded);
24688 }
24689
24690 /// @brief create a JSON value from an input in BJData format
24691 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
24692 template<typename InputType>
24694 static basic_json from_bjdata(InputType&& i,
24695 const bool strict = true,
24696 const bool allow_exceptions = true)
24697 {
24698 basic_json result;
24699 auto ia = detail::input_adapter(std::forward<InputType>(i));
24700 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24701 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]
24702 return res ? result : basic_json(value_t::discarded);
24703 }
24704
24705 /// @brief create a JSON value from an input in BJData format
24706 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
24707 template<typename IteratorType>
24709 static basic_json from_bjdata(IteratorType first, IteratorType last,
24710 const bool strict = true,
24711 const bool allow_exceptions = true)
24712 {
24713 basic_json result;
24714 auto ia = detail::input_adapter(std::move(first), std::move(last));
24715 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24716 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
24717 return res ? result : basic_json(value_t::discarded);
24718 }
24719
24720 /// @brief create a JSON value from an input in BSON format
24721 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
24722 template<typename InputType>
24724 static basic_json from_bson(InputType&& i,
24725 const bool strict = true,
24726 const bool allow_exceptions = true)
24727 {
24728 basic_json result;
24729 auto ia = detail::input_adapter(std::forward<InputType>(i));
24730 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24731 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]
24732 return res ? result : basic_json(value_t::discarded);
24733 }
24734
24735 /// @brief create a JSON value from an input in BSON format
24736 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
24737 template<typename IteratorType>
24739 static basic_json from_bson(IteratorType first, IteratorType last,
24740 const bool strict = true,
24741 const bool allow_exceptions = true)
24742 {
24743 basic_json result;
24744 auto ia = detail::input_adapter(std::move(first), std::move(last));
24745 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24746 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]
24747 return res ? result : basic_json(value_t::discarded);
24748 }
24749
24750 template<typename T>
24752 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24753 static basic_json from_bson(const T* ptr, std::size_t len,
24754 const bool strict = true,
24755 const bool allow_exceptions = true)
24756 {
24757 return from_bson(ptr, ptr + len, strict, allow_exceptions);
24758 }
24759
24761 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24762 static basic_json from_bson(detail::span_input_adapter&& i,
24763 const bool strict = true,
24764 const bool allow_exceptions = true)
24765 {
24766 basic_json result;
24767 auto ia = i.get();
24768 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24769 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24770 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]
24771 return res ? result : basic_json(value_t::discarded);
24772 }
24773 /// @}
24774
24775 //////////////////////////
24776 // JSON Pointer support //
24777 //////////////////////////
24778
24779 /// @name JSON Pointer functions
24780 /// @{
24781
24782 /// @brief access specified element via JSON Pointer
24783 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
24785 {
24786 return ptr.get_unchecked(this);
24787 }
24788
24789 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24790 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24791 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24792 {
24793 return ptr.get_unchecked(this);
24794 }
24795
24796 /// @brief access specified element via JSON Pointer
24797 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
24799 {
24800 return ptr.get_unchecked(this);
24801 }
24802
24803 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24804 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24805 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24806 {
24807 return ptr.get_unchecked(this);
24808 }
24809
24810 /// @brief access specified element via JSON Pointer
24811 /// @sa https://json.nlohmann.me/api/basic_json/at/
24813 {
24814 return ptr.get_checked(this);
24815 }
24816
24817 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24818 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24819 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24820 {
24821 return ptr.get_checked(this);
24822 }
24823
24824 /// @brief access specified element via JSON Pointer
24825 /// @sa https://json.nlohmann.me/api/basic_json/at/
24827 {
24828 return ptr.get_checked(this);
24829 }
24830
24831 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24832 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24833 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24834 {
24835 return ptr.get_checked(this);
24836 }
24837
24838 /// @brief return flattened JSON value
24839 /// @sa https://json.nlohmann.me/api/basic_json/flatten/
24841 {
24842 basic_json result(value_t::object);
24843 json_pointer::flatten("", *this, result);
24844 return result;
24845 }
24846
24847 /// @brief unflatten a previously flattened JSON value
24848 /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
24850 {
24851 return json_pointer::unflatten(*this);
24852 }
24853
24854 /// @}
24855
24856 //////////////////////////
24857 // JSON Patch functions //
24858 //////////////////////////
24859
24860 /// @name JSON Patch functions
24861 /// @{
24862
24863 /// @brief applies a JSON patch in-place without copying the object
24864 /// @sa https://json.nlohmann.me/api/basic_json/patch/
24865 void patch_inplace(const basic_json& json_patch)
24866 {
24867 basic_json& result = *this;
24868 // the valid JSON Patch operations
24869 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24870
24871 const auto get_op = [](const string_t& op)
24872 {
24873 if (op == "add")
24874 {
24875 return patch_operations::add;
24876 }
24877 if (op == "remove")
24878 {
24879 return patch_operations::remove;
24880 }
24881 if (op == "replace")
24882 {
24883 return patch_operations::replace;
24884 }
24885 if (op == "move")
24886 {
24887 return patch_operations::move;
24888 }
24889 if (op == "copy")
24890 {
24891 return patch_operations::copy;
24892 }
24893 if (op == "test")
24894 {
24895 return patch_operations::test;
24896 }
24897
24898 return patch_operations::invalid;
24899 };
24900
24901 // wrapper for "add" operation; add value at ptr
24902 const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
24903 {
24904 // adding to the root of the target document means replacing it
24905 if (ptr.empty())
24906 {
24907 result = val;
24908 return;
24909 }
24910
24911 // make sure the top element of the pointer exists
24912 json_pointer const top_pointer = ptr.top();
24913 if (top_pointer != ptr)
24914 {
24915 result.at(top_pointer);
24916 }
24917
24918 // get reference to the parent of the JSON pointer ptr
24919 const auto last_path = ptr.back();
24920 ptr.pop_back();
24921 // parent must exist when performing patch add per RFC6902 specs
24922 basic_json& parent = result.at(ptr);
24923
24924 switch (parent.m_data.m_type)
24925 {
24926 case value_t::null:
24927 case value_t::object:
24928 {
24929 // use operator[] to add value
24930 parent[last_path] = val;
24931 break;
24932 }
24933
24934 case value_t::array:
24935 {
24936 if (last_path == "-")
24937 {
24938 // special case: append to back
24939 parent.push_back(val);
24940 }
24941 else
24942 {
24943 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24944 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24945 {
24946 // avoid undefined behavior
24947 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24948 }
24949
24950 // default case: insert add offset
24951 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24952 }
24953 break;
24954 }
24955
24956 // if there exists a parent, it cannot be primitive
24957 case value_t::string: // LCOV_EXCL_LINE
24958 case value_t::boolean: // LCOV_EXCL_LINE
24959 case value_t::number_integer: // LCOV_EXCL_LINE
24960 case value_t::number_unsigned: // LCOV_EXCL_LINE
24961 case value_t::number_float: // LCOV_EXCL_LINE
24962 case value_t::binary: // LCOV_EXCL_LINE
24963 case value_t::discarded: // LCOV_EXCL_LINE
24964 default: // LCOV_EXCL_LINE
24965 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24966 }
24967 };
24968
24969 // wrapper for "remove" operation; remove value at ptr
24970 const auto operation_remove = [this, & result](json_pointer & ptr)
24971 {
24972 // get reference to the parent of the JSON pointer ptr
24973 const auto last_path = ptr.back();
24974 ptr.pop_back();
24975 basic_json& parent = result.at(ptr);
24976
24977 // remove child
24978 if (parent.is_object())
24979 {
24980 // perform range check
24981 auto it = parent.find(last_path);
24982 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24983 {
24984 parent.erase(it);
24985 }
24986 else
24987 {
24988 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24989 }
24990 }
24991 else if (parent.is_array())
24992 {
24993 // note erase performs range check
24994 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24995 }
24996 };
24997
24998 // type check: top level value must be an array
24999 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
25000 {
25001 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
25002 }
25003
25004 // iterate and apply the operations
25005 for (const auto& val : json_patch)
25006 {
25007 // wrapper to get a value for an operation
25008 const auto get_value = [&val](const string_t& op,
25009 const string_t& member,
25010 bool string_type) -> basic_json &
25011 {
25012 // find value
25013 auto it = val.m_data.m_value.object->find(member);
25014
25015 // context-sensitive error message
25016 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
25017
25018 // check if the desired value is present
25019 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
25020 {
25021 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
25022 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
25023 }
25024
25025 // check if the result is of type string
25026 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
25027 {
25028 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
25029 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
25030 }
25031
25032 // no error: return value
25033 return it->second;
25034 };
25035
25036 // type check: every element of the array must be an object
25037 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
25038 {
25039 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
25040 }
25041
25042 // collect mandatory members
25043 const auto op = get_value("op", "op", true).template get<string_t>();
25044 const auto path = get_value(op, "path", true).template get<string_t>();
25045 json_pointer ptr(path);
25046
25047 switch (get_op(op))
25048 {
25049 case patch_operations::add:
25050 {
25051 operation_add(ptr, get_value("add", "value", false));
25052 break;
25053 }
25054
25055 case patch_operations::remove:
25056 {
25057 operation_remove(ptr);
25058 break;
25059 }
25060
25061 case patch_operations::replace:
25062 {
25063 // the "path" location must exist - use at()
25064 result.at(ptr) = get_value("replace", "value", false);
25065 break;
25066 }
25067
25068 case patch_operations::move:
25069 {
25070 const auto from_path = get_value("move", "from", true).template get<string_t>();
25071 json_pointer from_ptr(from_path);
25072
25073 // the "from" location must exist - use at()
25074 basic_json const v = result.at(from_ptr);
25075
25076 // The move operation is functionally identical to a
25077 // "remove" operation on the "from" location, followed
25078 // immediately by an "add" operation at the target
25079 // location with the value that was just removed.
25080 operation_remove(from_ptr);
25081 operation_add(ptr, v);
25082 break;
25083 }
25084
25085 case patch_operations::copy:
25086 {
25087 const auto from_path = get_value("copy", "from", true).template get<string_t>();
25088 const json_pointer from_ptr(from_path);
25089
25090 // the "from" location must exist - use at()
25091 basic_json const v = result.at(from_ptr);
25092
25093 // The copy is functionally identical to an "add"
25094 // operation at the target location using the value
25095 // specified in the "from" member.
25096 operation_add(ptr, v);
25097 break;
25098 }
25099
25100 case patch_operations::test:
25101 {
25102 bool success = false;
25103 JSON_TRY
25104 {
25105 // check if "value" matches the one at "path"
25106 // the "path" location must exist - use at()
25107 success = (result.at(ptr) == get_value("test", "value", false));
25108 }
25110 {
25111 // ignore out of range errors: success remains false
25112 }
25113
25114 // throw an exception if the test fails
25115 if (JSON_HEDLEY_UNLIKELY(!success))
25116 {
25117 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
25118 }
25119
25120 break;
25121 }
25122
25123 case patch_operations::invalid:
25124 default:
25125 {
25126 // op must be "add", "remove", "replace", "move", "copy", or
25127 // "test"
25128 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
25129 }
25130 }
25131 }
25132 }
25133
25134 /// @brief applies a JSON patch to a copy of the current object
25135 /// @sa https://json.nlohmann.me/api/basic_json/patch/
25136 basic_json patch(const basic_json& json_patch) const
25137 {
25138 basic_json result = *this;
25139 result.patch_inplace(json_patch);
25140 return result;
25141 }
25142
25143 /// @brief creates a diff as a JSON patch
25144 /// @sa https://json.nlohmann.me/api/basic_json/diff/
25146 static basic_json diff(const basic_json& source, const basic_json& target,
25147 const string_t& path = "")
25148 {
25149 // the patch
25150 basic_json result(value_t::array);
25151
25152 // if the values are the same, return an empty patch
25153 if (source == target)
25154 {
25155 return result;
25156 }
25157
25158 if (source.type() != target.type())
25159 {
25160 // different types: replace value
25161 result.push_back(
25162 {
25163 {"op", "replace"}, {"path", path}, {"value", target}
25164 });
25165 return result;
25166 }
25167
25168 switch (source.type())
25169 {
25170 case value_t::array:
25171 {
25172 // first pass: traverse common elements
25173 std::size_t i = 0;
25174 while (i < source.size() && i < target.size())
25175 {
25176 // recursive call to compare array values at index i
25177 auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
25178 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25179 ++i;
25180 }
25181
25182 // We now reached the end of at least one array
25183 // in a second pass, traverse the remaining elements
25184
25185 // remove my remaining elements
25186 const auto end_index = static_cast<difference_type>(result.size());
25187 while (i < source.size())
25188 {
25189 // add operations in reverse order to avoid invalid
25190 // indices
25191 result.insert(result.begin() + end_index, object(
25192 {
25193 {"op", "remove"},
25194 {"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
25195 }));
25196 ++i;
25197 }
25198
25199 // add other remaining elements
25200 while (i < target.size())
25201 {
25202 result.push_back(
25203 {
25204 {"op", "add"},
25205 {"path", detail::concat<string_t>(path, "/-")},
25206 {"value", target[i]}
25207 });
25208 ++i;
25209 }
25210
25211 break;
25212 }
25213
25214 case value_t::object:
25215 {
25216 // first pass: traverse this object's elements
25217 for (auto it = source.cbegin(); it != source.cend(); ++it)
25218 {
25219 // escape the key name to be used in a JSON patch
25220 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25221
25222 if (target.find(it.key()) != target.end())
25223 {
25224 // recursive call to compare object values at key it
25225 auto temp_diff = diff(it.value(), target[it.key()], path_key);
25226 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25227 }
25228 else
25229 {
25230 // found a key that is not in o -> remove it
25231 result.push_back(object(
25232 {
25233 {"op", "remove"}, {"path", path_key}
25234 }));
25235 }
25236 }
25237
25238 // second pass: traverse other object's elements
25239 for (auto it = target.cbegin(); it != target.cend(); ++it)
25240 {
25241 if (source.find(it.key()) == source.end())
25242 {
25243 // found a key that is not in this -> add it
25244 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25245 result.push_back(
25246 {
25247 {"op", "add"}, {"path", path_key},
25248 {"value", it.value()}
25249 });
25250 }
25251 }
25252
25253 break;
25254 }
25255
25256 case value_t::null:
25257 case value_t::string:
25258 case value_t::boolean:
25259 case value_t::number_integer:
25260 case value_t::number_unsigned:
25261 case value_t::number_float:
25262 case value_t::binary:
25263 case value_t::discarded:
25264 default:
25265 {
25266 // both primitive types: replace value
25267 result.push_back(
25268 {
25269 {"op", "replace"}, {"path", path}, {"value", target}
25270 });
25271 break;
25272 }
25273 }
25274
25275 return result;
25276 }
25277 /// @}
25278
25279 ////////////////////////////////
25280 // JSON Merge Patch functions //
25281 ////////////////////////////////
25282
25283 /// @name JSON Merge Patch functions
25284 /// @{
25285
25286 /// @brief applies a JSON Merge Patch
25287 /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
25288 void merge_patch(const basic_json& apply_patch)
25289 {
25290 if (apply_patch.is_object())
25291 {
25292 if (!is_object())
25293 {
25294 *this = object();
25295 }
25296 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
25297 {
25298 if (it.value().is_null())
25299 {
25300 erase(it.key());
25301 }
25302 else
25303 {
25304 operator[](it.key()).merge_patch(it.value());
25305 }
25306 }
25307 }
25308 else
25309 {
25310 *this = apply_patch;
25311 }
25312 }
25313
25314 /// @}
25315};
25316
25317/// @brief user-defined to_string function for JSON values
25318/// @sa https://json.nlohmann.me/api/basic_json/to_string/
25321{
25322 return j.dump();
25323}
25324
25325inline namespace literals
25326{
25327inline namespace json_literals
25328{
25329
25330/// @brief user-defined string literal for JSON values
25331/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
25333#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25334 inline nlohmann::json operator ""_json(const char* s, std::size_t n)
25335#else
25336 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
25337#endif
25338{
25339 return nlohmann::json::parse(s, s + n);
25340}
25341
25342/// @brief user-defined string literal for JSON pointer
25343/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
25345#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25346 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
25347#else
25348 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
25349#endif
25350{
25351 return nlohmann::json::json_pointer(std::string(s, n));
25352}
25353
25354} // namespace json_literals
25355} // namespace literals
25357
25358///////////////////////
25359// nonmember support //
25360///////////////////////
25361
25362namespace std // NOLINT(cert-dcl58-cpp)
25363{
25364
25365/// @brief hash value for JSON objects
25366/// @sa https://json.nlohmann.me/api/basic_json/std_hash/
25368struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
25369{
25370 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
25371 {
25372 return nlohmann::detail::hash(j);
25373 }
25374};
25375
25376// specialization for std::less<value_t>
25377template<>
25378struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
25379{
25380 /*!
25381 @brief compare two value_t enum values
25382 @since version 3.0.0
25383 */
25384 bool operator()(::nlohmann::detail::value_t lhs,
25385 ::nlohmann::detail::value_t rhs) const noexcept
25386 {
25387#if JSON_HAS_THREE_WAY_COMPARISON
25388 return std::is_lt(lhs <=> rhs); // *NOPAD*
25389#else
25390 return ::nlohmann::detail::operator<(lhs, rhs);
25391#endif
25392 }
25393};
25394
25395// C++20 prohibit function specialization in the std namespace.
25396#ifndef JSON_HAS_CPP_20
25397
25398/// @brief exchanges the values of two JSON objects
25399/// @sa https://json.nlohmann.me/api/basic_json/std_swap/
25401inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
25402 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
25403 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
25404{
25405 j1.swap(j2);
25406}
25407
25408#endif
25409
25410} // namespace std
25411
25412#if JSON_USE_GLOBAL_UDLS
25413 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25414 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25415 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25416 #else
25417 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25418 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25419 #endif
25420#endif
25421
25422// #include <nlohmann/detail/macro_unscope.hpp>
25423// __ _____ _____ _____
25424// __| | __| | | | JSON for Modern C++
25425// | | |__ | | | | | | version 3.12.0
25426// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25427//
25428// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25429// SPDX-License-Identifier: MIT
25430
25431
25432
25433// restore clang diagnostic settings
25434#if defined(__clang__)
25435 #pragma clang diagnostic pop
25436#endif
25437
25438// clean up
25439#undef JSON_ASSERT
25440#undef JSON_INTERNAL_CATCH
25441#undef JSON_THROW
25442#undef JSON_PRIVATE_UNLESS_TESTED
25443#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
25444#undef NLOHMANN_BASIC_JSON_TPL
25445#undef JSON_EXPLICIT
25446#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
25447#undef JSON_INLINE_VARIABLE
25448#undef JSON_NO_UNIQUE_ADDRESS
25449#undef JSON_DISABLE_ENUM_SERIALIZATION
25450#undef JSON_USE_GLOBAL_UDLS
25451
25452#ifndef JSON_TEST_KEEP_MACROS
25453 #undef JSON_CATCH
25454 #undef JSON_TRY
25455 #undef JSON_HAS_CPP_11
25456 #undef JSON_HAS_CPP_14
25457 #undef JSON_HAS_CPP_17
25458 #undef JSON_HAS_CPP_20
25459 #undef JSON_HAS_CPP_23
25460 #undef JSON_HAS_CPP_26
25461 #undef JSON_HAS_FILESYSTEM
25462 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
25463 #undef JSON_HAS_THREE_WAY_COMPARISON
25464 #undef JSON_HAS_RANGES
25465 #undef JSON_HAS_STATIC_RTTI
25466 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
25467#endif
25468
25469// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
25470// __ _____ _____ _____
25471// __| | __| | | | JSON for Modern C++
25472// | | |__ | | | | | | version 3.12.0
25473// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25474//
25475// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25476// SPDX-License-Identifier: MIT
25477
25478
25479
25480#undef JSON_HEDLEY_ALWAYS_INLINE
25481#undef JSON_HEDLEY_ARM_VERSION
25482#undef JSON_HEDLEY_ARM_VERSION_CHECK
25483#undef JSON_HEDLEY_ARRAY_PARAM
25484#undef JSON_HEDLEY_ASSUME
25485#undef JSON_HEDLEY_BEGIN_C_DECLS
25486#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
25487#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
25488#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
25489#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
25490#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
25491#undef JSON_HEDLEY_CLANG_HAS_FEATURE
25492#undef JSON_HEDLEY_CLANG_HAS_WARNING
25493#undef JSON_HEDLEY_COMPCERT_VERSION
25494#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
25495#undef JSON_HEDLEY_CONCAT
25496#undef JSON_HEDLEY_CONCAT3
25497#undef JSON_HEDLEY_CONCAT3_EX
25498#undef JSON_HEDLEY_CONCAT_EX
25499#undef JSON_HEDLEY_CONST
25500#undef JSON_HEDLEY_CONSTEXPR
25501#undef JSON_HEDLEY_CONST_CAST
25502#undef JSON_HEDLEY_CPP_CAST
25503#undef JSON_HEDLEY_CRAY_VERSION
25504#undef JSON_HEDLEY_CRAY_VERSION_CHECK
25505#undef JSON_HEDLEY_C_DECL
25506#undef JSON_HEDLEY_DEPRECATED
25507#undef JSON_HEDLEY_DEPRECATED_FOR
25508#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
25509#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
25510#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
25511#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
25512#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
25513#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
25514#undef JSON_HEDLEY_DIAGNOSTIC_POP
25515#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
25516#undef JSON_HEDLEY_DMC_VERSION
25517#undef JSON_HEDLEY_DMC_VERSION_CHECK
25518#undef JSON_HEDLEY_EMPTY_BASES
25519#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
25520#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
25521#undef JSON_HEDLEY_END_C_DECLS
25522#undef JSON_HEDLEY_FLAGS
25523#undef JSON_HEDLEY_FLAGS_CAST
25524#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
25525#undef JSON_HEDLEY_GCC_HAS_BUILTIN
25526#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
25527#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
25528#undef JSON_HEDLEY_GCC_HAS_EXTENSION
25529#undef JSON_HEDLEY_GCC_HAS_FEATURE
25530#undef JSON_HEDLEY_GCC_HAS_WARNING
25531#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
25532#undef JSON_HEDLEY_GCC_VERSION
25533#undef JSON_HEDLEY_GCC_VERSION_CHECK
25534#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
25535#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
25536#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
25537#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
25538#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
25539#undef JSON_HEDLEY_GNUC_HAS_FEATURE
25540#undef JSON_HEDLEY_GNUC_HAS_WARNING
25541#undef JSON_HEDLEY_GNUC_VERSION
25542#undef JSON_HEDLEY_GNUC_VERSION_CHECK
25543#undef JSON_HEDLEY_HAS_ATTRIBUTE
25544#undef JSON_HEDLEY_HAS_BUILTIN
25545#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
25546#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
25547#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
25548#undef JSON_HEDLEY_HAS_EXTENSION
25549#undef JSON_HEDLEY_HAS_FEATURE
25550#undef JSON_HEDLEY_HAS_WARNING
25551#undef JSON_HEDLEY_IAR_VERSION
25552#undef JSON_HEDLEY_IAR_VERSION_CHECK
25553#undef JSON_HEDLEY_IBM_VERSION
25554#undef JSON_HEDLEY_IBM_VERSION_CHECK
25555#undef JSON_HEDLEY_IMPORT
25556#undef JSON_HEDLEY_INLINE
25557#undef JSON_HEDLEY_INTEL_CL_VERSION
25558#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
25559#undef JSON_HEDLEY_INTEL_VERSION
25560#undef JSON_HEDLEY_INTEL_VERSION_CHECK
25561#undef JSON_HEDLEY_IS_CONSTANT
25562#undef JSON_HEDLEY_IS_CONSTEXPR_
25563#undef JSON_HEDLEY_LIKELY
25564#undef JSON_HEDLEY_MALLOC
25565#undef JSON_HEDLEY_MCST_LCC_VERSION
25566#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
25567#undef JSON_HEDLEY_MESSAGE
25568#undef JSON_HEDLEY_MSVC_VERSION
25569#undef JSON_HEDLEY_MSVC_VERSION_CHECK
25570#undef JSON_HEDLEY_NEVER_INLINE
25571#undef JSON_HEDLEY_NON_NULL
25572#undef JSON_HEDLEY_NO_ESCAPE
25573#undef JSON_HEDLEY_NO_RETURN
25574#undef JSON_HEDLEY_NO_THROW
25575#undef JSON_HEDLEY_NULL
25576#undef JSON_HEDLEY_PELLES_VERSION
25577#undef JSON_HEDLEY_PELLES_VERSION_CHECK
25578#undef JSON_HEDLEY_PGI_VERSION
25579#undef JSON_HEDLEY_PGI_VERSION_CHECK
25580#undef JSON_HEDLEY_PREDICT
25581#undef JSON_HEDLEY_PRINTF_FORMAT
25582#undef JSON_HEDLEY_PRIVATE
25583#undef JSON_HEDLEY_PUBLIC
25584#undef JSON_HEDLEY_PURE
25585#undef JSON_HEDLEY_REINTERPRET_CAST
25586#undef JSON_HEDLEY_REQUIRE
25587#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
25588#undef JSON_HEDLEY_REQUIRE_MSG
25589#undef JSON_HEDLEY_RESTRICT
25590#undef JSON_HEDLEY_RETURNS_NON_NULL
25591#undef JSON_HEDLEY_SENTINEL
25592#undef JSON_HEDLEY_STATIC_ASSERT
25593#undef JSON_HEDLEY_STATIC_CAST
25594#undef JSON_HEDLEY_STRINGIFY
25595#undef JSON_HEDLEY_STRINGIFY_EX
25596#undef JSON_HEDLEY_SUNPRO_VERSION
25597#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
25598#undef JSON_HEDLEY_TINYC_VERSION
25599#undef JSON_HEDLEY_TINYC_VERSION_CHECK
25600#undef JSON_HEDLEY_TI_ARMCL_VERSION
25601#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
25602#undef JSON_HEDLEY_TI_CL2000_VERSION
25603#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
25604#undef JSON_HEDLEY_TI_CL430_VERSION
25605#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
25606#undef JSON_HEDLEY_TI_CL6X_VERSION
25607#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
25608#undef JSON_HEDLEY_TI_CL7X_VERSION
25609#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
25610#undef JSON_HEDLEY_TI_CLPRU_VERSION
25611#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
25612#undef JSON_HEDLEY_TI_VERSION
25613#undef JSON_HEDLEY_TI_VERSION_CHECK
25614#undef JSON_HEDLEY_UNAVAILABLE
25615#undef JSON_HEDLEY_UNLIKELY
25616#undef JSON_HEDLEY_UNPREDICTABLE
25617#undef JSON_HEDLEY_UNREACHABLE
25618#undef JSON_HEDLEY_UNREACHABLE_RETURN
25619#undef JSON_HEDLEY_VERSION
25620#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
25621#undef JSON_HEDLEY_VERSION_DECODE_MINOR
25622#undef JSON_HEDLEY_VERSION_DECODE_REVISION
25623#undef JSON_HEDLEY_VERSION_ENCODE
25624#undef JSON_HEDLEY_WARNING
25625#undef JSON_HEDLEY_WARN_UNUSED_RESULT
25626#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
25627#undef JSON_HEDLEY_FALL_THROUGH
25628
25629
25630
25631#endif // INCLUDE_NLOHMANN_JSON_HPP_
25632
25633// NOLINTEND(modernize-type-traits)
a class to store JSON values
Definition json.h:20205
constexpr bool is_string() const noexcept
return whether value is a string
Definition json.h:21504
number_integer_t * get_impl_ptr(number_integer_t *) noexcept
get a pointer to the value (integer number)
Definition json.h:21597
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.h:22739
reference operator[](KeyType &&key)
access specified object element
Definition json.h:22305
json_value(object_t &&value)
constructor for rvalue objects
Definition json.h:20643
size_type size() const noexcept
returns the number of elements
Definition json.h:23080
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.h:24544
json_value(typename binary_t::container_type &&value)
constructor for rvalue binary arrays
Definition json.h:20655
number_unsigned_t number_unsigned
number (unsigned integer)
Definition json.h:20547
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
get a (pointer) value (explicit)
Definition json.h:21877
::nlohmann::detail::iteration_proxy< Iterator > iteration_proxy
Definition json.h:20257
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition json.h:22937
reference back()
access the last element
Definition json.h:22543
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value from compatible types
Definition json.h:20944
number_float_t number_float
number (floating-point)
Definition json.h:20549
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.h:22953
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition json.h:25136
json_value(const array_t &value)
constructor for arrays
Definition json.h:20646
array_t * get_impl_ptr(array_t *) noexcept
get a pointer to the value (array)
Definition json.h:21561
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
Definition json.h:24303
const_reference front() const
access the first element
Definition json.h:22536
constexpr bool is_array() const noexcept
return whether value is an array
Definition json.h:21497
number_float_t * get_impl_ptr(number_float_t *) noexcept
get a pointer to the value (floating-point number)
Definition json.h:21621
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.h:23598
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.h:22486
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.h:22856
constexpr const number_integer_t * get_impl_ptr(const number_integer_t *) const noexcept
get a pointer to the value (integer number)
Definition json.h:21603
iter_impl< const basic_json > const_iterator
a const iterator for a basic_json container
Definition json.h:20339
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition json.h:20283
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition json.h:21469
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition json.h:20343
data(size_type cnt, const basic_json &val)
Definition json.h:24348
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.h:24739
::nlohmann::detail::json_base_class< CustomBaseClass > json_base_class_t
Definition json.h:20231
basic_json get_impl(detail::priority_tag< 3 >) const
get special-case overload
Definition json.h:21829
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.h:24784
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition json.h:20334
static JSON_HEDLEY_RETURNS_NON_NULL T * create(Args &&... args)
helper for exception-safe object creation
Definition json.h:20487
std::size_t size_type
a type to represent container sizes
Definition json.h:20326
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.h:21441
json_value(boolean_t v) noexcept
constructor for booleans
Definition json.h:20554
const_reference operator[](KeyType &&key) const
access specified object element
Definition json.h:22329
boolean_t get_impl(boolean_t *) const
get a boolean (explicit)
Definition json.h:21538
void swap(binary_t &other)
exchanges the values
Definition json.h:23675
ReferenceType get_ref()
get a reference value (implicit)
Definition json.h:21967
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.h:23119
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.h:23544
::nlohmann::detail::iter_impl< BasicJsonType > iter_impl
Definition json.h:20255
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.h:21978
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.h:21518
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.h:23335
::nlohmann::detail::output_adapter_t< CharType > output_adapter_t
Definition json.h:20261
void push_back(basic_json &&val)
add an object to an array
Definition json.h:23223
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition json.h:22274
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.h:23025
json_value(number_integer_t v) noexcept
constructor for numbers (integer)
Definition json.h:20556
static ReferenceType get_ref_impl(ThisType &obj)
helper function to implement get_ref()
Definition json.h:21656
::nlohmann::detail::json_reverse_iterator< Base > json_reverse_iterator
Definition json.h:20258
const_reference back() const
access the last element
Definition json.h:22552
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.h:22634
reference operator+=(const basic_json &val)
add an object to an array
Definition json.h:23280
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.h:23615
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.h:24640
constexpr const string_t * get_impl_ptr(const string_t *) const noexcept
get a pointer to the value (string)
Definition json.h:21579
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.h:21086
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition json.h:23447
object_t * get_impl_ptr(object_t *) noexcept
get a pointer to the value (object)
Definition json.h:21549
static ::nlohmann::detail::parser< basic_json, InputAdapterType > parser(InputAdapterType adapter, detail::parser_callback_t< basic_json >cb=nullptr, const bool allow_exceptions=true, const bool ignore_comments=false, const bool ignore_trailing_commas=false)
Definition json.h:20238
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.h:24724
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.h:20349
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
Definition json.h:20474
reference at(KeyType &&key)
access specified object element with bounds checking
Definition json.h:22137
iterator end() noexcept
returns an iterator to one past the last element
Definition json.h:22928
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.h:21476
json_value(array_t &&value)
constructor for rvalue arrays
Definition json.h:20649
void update(const_iterator first, const_iterator last, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.h:23551
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition json.h:24503
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition json.h:22960
data m_data
Definition json.h:24366
void push_back(initializer_list_t init)
add an object to an object
Definition json.h:23319
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
Definition json.h:20911
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.h:21127
ValueType & get_to(ValueType &v) const
get a value (explicit)
Definition json.h:21944
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
create a MessagePack serialization of a given JSON value
Definition json.h:24439
iterator begin() noexcept
returns an iterator to the first element
Definition json.h:22903
array_t * array
array (stored with pointer to save storage)
Definition json.h:20537
void assert_invariant(bool check_parents=true) const noexcept
checks the class invariants
Definition json.h:20791
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition json.h:22384
void destroy(value_t t)
Definition json.h:20663
ValueType get_impl(detail::priority_tag< 0 >) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), std::declval< ValueType & >())))
get a value (explicit)
Definition json.h:21739
json_value(string_t &&value)
constructor for rvalue strings
Definition json.h:20637
const_iterator cend() const noexcept
returns an iterator to one past the last element
Definition json.h:22944
constexpr const binary_t * get_impl_ptr(const binary_t *) const noexcept
get a pointer to the value (binary)
Definition json.h:21639
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.h:24694
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.h:24826
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition json.h:21097
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.h:20932
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.h:24528
constexpr const number_unsigned_t * get_impl_ptr(const number_unsigned_t *) const noexcept
get a pointer to the value (unsigned number)
Definition json.h:21615
constexpr const boolean_t * get_impl_ptr(const boolean_t *) const noexcept
get a pointer to the value (boolean)
Definition json.h:21591
basic_json flatten() const
return flattened JSON value
Definition json.h:24840
constexpr const array_t * get_impl_ptr(const array_t *) const noexcept
get a pointer to the value (array)
Definition json.h:21567
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.h:24655
json_value(number_unsigned_t v) noexcept
constructor for numbers (unsigned)
Definition json.h:20558
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition json.h:22750
::nlohmann::detail::primitive_iterator_t primitive_iterator_t
Definition json.h:20251
json_value(const string_t &value)
constructor for strings
Definition json.h:20634
const binary_t & get_binary() const
get a binary value
Definition json.h:22049
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition json.h:23467
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition json.h:24865
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.h:22437
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.h:24798
json_value(number_float_t v) noexcept
constructor for numbers (floating-point)
Definition json.h:20560
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition json.h:20450
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition json.h:22873
static void to_cbor(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a CBOR serialization of a given JSON value
Definition json.h:24409
::nlohmann::detail::binary_reader< basic_json, InputType > binary_reader
Definition json.h:20264
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
create a BSON serialization of a given JSON value
Definition json.h:24519
iterator find(const typename object_t::key_type &key)
find an element in a JSON object
Definition json.h:22786
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
Definition json.h:21075
BasicJsonType get_impl(detail::priority_tag< 2 >) const
get special-case overload
Definition json.h:21806
static std::vector< std::uint8_t > to_bjdata(const basic_json &j, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
Definition json.h:24473
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition json.h:22175
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.h:20357
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.h:21134
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition json.h:22800
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.h:24400
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.h:22564
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition json.h:23420
NumberFloatType number_float_t
a type for a number (floating-point)
Definition json.h:20470
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.h:22359
string_t * string
string (stored with pointer to save storage)
Definition json.h:20539
AllocatorType< basic_json > allocator_type
the allocator type
Definition json.h:20329
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition json.h:20332
reference set_parent(reference j, std::size_t old_capacity=detail::unknown_size())
Definition json.h:20862
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition json.h:21405
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.h:25288
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition json.h:21931
static void to_bjdata(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
Definition json.h:24485
reference operator[](T *key)
access specified array element with bounds checking
Definition json.h:22290
reference at(size_type idx)
access specified array element with bounds checking
Definition json.h:22071
iterator find(KeyType &&key)
find an element in a JSON object
Definition json.h:22816
binary_t * binary
binary (stored with pointer to save storage)
Definition json.h:20541
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition json.h:21483
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.h:22967
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.h:24446
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.h:24812
BooleanType boolean_t
a type for a boolean
Definition json.h:20458
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const string_t &path="")
creates a diff as a JSON patch
Definition json.h:25146
::nlohmann::detail::internal_iterator< BasicJsonType > internal_iterator
Definition json.h:20253
void set_parents()
Definition json.h:20812
std::conditional< detail::is_c_string_uncvref< ValueType >::value, string_t, typename std::decay< ValueType >::type > value_return_type
access specified array element with bounds checking
Definition json.h:22350
size_type erase_internal(KeyType &&key)
access specified array element with bounds checking
Definition json.h:22705
std::less< StringType > default_object_comparator_t
default object key comparator type The actual object key comparator type (object_comparator_t) may be...
Definition json.h:20437
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.h:23311
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition json.h:22919
constexpr const number_float_t * get_impl_ptr(const number_float_t *) const noexcept
get a pointer to the value (floating-point number)
Definition json.h:21627
reference operator[](typename object_t::key_type key)
access specified object element
Definition json.h:22252
string_t * get_impl_ptr(string_t *) noexcept
get a pointer to the value (string)
Definition json.h:21573
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.h:21689
~basic_json() noexcept
destructor
Definition json.h:21387
json_value(binary_t &&value)
constructor for rvalue binary arrays (internal type)
Definition json.h:20661
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition json.h:22988
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition json.h:21016
json_value(const object_t &value)
constructor for objects
Definition json.h:20640
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.h:23691
binary_t & get_binary()
get a binary value
Definition json.h:22037
const_iterator begin() const noexcept
returns an iterator to the first element
Definition json.h:22912
constexpr bool is_number() const noexcept
return whether value is a number
Definition json.h:21462
number_unsigned_t * get_impl_ptr(number_unsigned_t *) noexcept
get a pointer to the value (unsigned number)
Definition json.h:21609
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition json.h:23518
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.h:24586
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.h:21918
const_reference operator[](T *key) const
access specified array element with bounds checking
Definition json.h:22296
data(const value_t v)
Definition json.h:24343
reference operator[](size_type idx)
access specified array element
Definition json.h:22193
basic_json(const JsonRef &ref)
explicitly create a binary array (without subtype)
Definition json.h:21255
JSONSerializer< T, SFINAE > json_serializer
Definition json.h:20275
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value &&std::is_nothrow_move_assignable< json_base_class_t >::value)
copy assignment
Definition json.h:21358
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.h:24465
Array get_to(T(&v)[N]) const noexcept(noexcept(JSONSerializer< Array >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition json.h:21955
NumberIntegerType number_integer_t
a type for a number (integer)
Definition json.h:20462
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.h:21678
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.h:22155
binary_t * get_impl_ptr(binary_t *) noexcept
get a pointer to the value (binary)
Definition json.h:21633
constexpr bool is_binary() const noexcept
return whether value is a binary array
Definition json.h:21511
void swap(object_t &other)
exchanges the values
Definition json.h:23643
iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
Definition json.h:20849
constexpr auto get_impl(detail::priority_tag< 4 >) const noexcept -> decltype(std::declval< const basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.h:21842
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.h:24849
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition json.h:23498
static void to_bjdata(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
Definition json.h:24494
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.h:21108
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.h:23018
bool empty() const noexcept
checks whether the container is empty.
Definition json.h:23041
void swap(array_t &other)
exchanges the values
Definition json.h:23627
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.h:22757
reference operator+=(basic_json &&val)
add an object to an array
Definition json.h:23248
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.h:22880
ValueType get_impl(detail::priority_tag< 1 >) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >())))
get a value (explicit); special case
Definition json.h:21781
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.h:21427
reference emplace_back(Args &&... args)
add an object to an array
Definition json.h:23344
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.h:22460
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.h:21119
data() noexcept=default
StringType string_t
a type for a string
Definition json.h:20454
ObjectType< StringType, basic_json, default_object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
Definition json.h:20446
void push_back(const basic_json &val)
add an object to an array
Definition json.h:23256
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition json.h:22410
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.h:22117
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.h:24709
json_value m_value
the value of the current element
Definition json.h:24341
number_integer_t number_integer
number (integer)
Definition json.h:20545
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.h:22981
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition json.h:21455
size_type count(const typename object_t::key_type &key) const
returns the number of occurrences of a key in a JSON object
Definition json.h:22846
reference front()
access the first element
Definition json.h:22529
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.h:21434
constexpr bool is_null() const noexcept
return whether value is null
Definition json.h:21448
void clear() noexcept
clears the contents
Definition json.h:23162
constexpr const object_t * get_impl_ptr(const object_t *) const noexcept
get a pointer to the value (object)
Definition json.h:21555
json_value(value_t t)
constructor for empty values of a given type
Definition json.h:20562
static void to_ubjson(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.h:24457
json_value()=default
default constructor (for null values)
basic_json(basic_json &&other) noexcept
move constructor
Definition json.h:21332
iter_impl< basic_json > iterator
an iterator for a basic_json container
Definition json.h:20337
basic_json(const value_t v)
create an empty value with a given type
Definition json.h:20924
const_reference operator[](size_type idx) const
access specified array element
Definition json.h:22239
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition json.h:20324
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition json.h:23440
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition json.h:22974
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition json.h:20466
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition json.h:24288
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.h:24423
void swap(string_t &other)
exchanges the values
Definition json.h:23659
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.h:20958
NLOHMANN_BASIC_JSON_TPL basic_json_t
workaround type for MSVC
Definition json.h:20230
boolean_t * get_impl_ptr(boolean_t *) noexcept
get a pointer to the value (boolean)
Definition json.h:21585
::nlohmann::detail::binary_writer< basic_json, CharType > binary_writer
Definition json.h:20265
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition json.h:20341
json_value(const binary_t &value)
constructor for binary arrays (internal type)
Definition json.h:20658
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.h:22094
detail::actual_object_comparator_t< basic_json > object_comparator_t
object key comparator type
Definition json.h:20478
basic_json(const basic_json &other)
copy constructor
Definition json.h:21259
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.h:23288
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.h:23369
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
create a CBOR serialization of a given JSON value
Definition json.h:24416
constexpr bool is_object() const noexcept
return whether value is an object
Definition json.h:21490
static void to_msgpack(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a MessagePack serialization of a given JSON value
Definition json.h:24432
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.h:24601
iterator insert_iterator(const_iterator pos, Args &&... args)
Helper for insertion of an iterator.
Definition json.h:23401
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.h:21146
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition json.h:22864
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a BSON serialization of a given JSON value
Definition json.h:24512
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition json.h:22832
boolean_t boolean
boolean
Definition json.h:20543
json_value(const typename binary_t::container_type &value)
constructor for binary arrays
Definition json.h:20652
::nlohmann::json_pointer< StringType > json_pointer
JSON Pointer, see nlohmann::json_pointer.
Definition json.h:20273
an internal type for a backed binary type
Definition json.h:6241
bool operator!=(const byte_container_with_subtype &rhs) const
Definition json.h:6281
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.h:6247
std::uint64_t subtype_type
Definition json.h:6244
bool operator==(const byte_container_with_subtype &rhs) const
Definition json.h:6275
BinaryType container_type
Definition json.h:6243
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.h:6269
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.h:6257
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.h:6296
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.h:6262
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.h:6303
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.h:6252
subtype_type m_subtype
Definition json.h:6317
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.h:6288
void clear_subtype() noexcept
clears the binary subtype
Definition json.h:6310
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.h:9894
bool get_string(const input_format_t format, const NumberType len, string_t &result)
create a string by reading characters from the input
Definition json.h:12725
bool get_ubjson_size_type(std::pair< std::size_t, char_int_type > &result, bool inside_ndarray=false)
determine the type and size for a container
Definition json.h:12072
binary_reader(const binary_reader &)=delete
bool parse_bson_array()
Reads an array from the BSON input and passes it to the SAX-parser.
Definition json.h:10222
typename BasicJsonType::string_t string_t
Definition json.h:9898
std::pair< char_int_type, string_t > bjd_type
Definition json.h:12890
bool parse_bson_element_list(const bool is_array)
Read a BSON element list (as specified in the BSON-spec)
Definition json.h:10184
typename InputAdapterType::char_type char_type
Definition json.h:9901
bool parse_msgpack_internal()
Definition json.h:11028
std::string get_token_string() const
Definition json.h:12795
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.h:9896
bool get_msgpack_string(string_t &result)
reads a MessagePack string
Definition json.h:11409
std::string exception_message(const input_format_t format, const std::string &detail, const std::string &context) const
Definition json.h:12808
InputAdapterType ia
input adapter
Definition json.h:12848
bool get_ubjson_high_precision_number()
Definition json.h:12530
bool get_binary(const input_format_t format, const NumberType len, binary_t &result)
create a byte array by reading bytes from the input
Definition json.h:12758
binary_reader(binary_reader &&)=default
static void byte_swap(NumberType &number)
Definition json.h:12653
char_int_type get_ignore_noop()
Definition json.h:12641
bool get_ubjson_value(const char_int_type prefix)
Definition json.h:12139
bool get_ubjson_ndarray_size(std::vector< size_t > &dim)
Definition json.h:11776
bool parse_bson_element_internal(const char_int_type element_type, const std::size_t element_type_parse_position)
Read a BSON document element of the given element_type.
Definition json.h:10098
bool get_msgpack_object(const std::size_t len)
Definition json.h:11625
typename char_traits< char_type >::int_type char_int_type
Definition json.h:9902
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.h:9910
typename BasicJsonType::binary_t binary_t
Definition json.h:9899
bool parse_bson_internal()
Reads in a BSON-object and passes it to the SAX-parser.
Definition json.h:9994
binary_reader & operator=(const binary_reader &)=delete
bool get_cbor_object(const std::size_t len, const cbor_tag_handler_t tag_handler)
Definition json.h:10972
bool get_cbor_binary(binary_t &result)
reads a CBOR byte array
Definition json.h:10839
bool get_number(const input_format_t format, NumberType &result)
Definition json.h:12695
typename BasicJsonType::number_integer_t number_integer_t
Definition json.h:9895
bool get_ubjson_array()
Definition json.h:12332
bool get_bson_cstr(string_t &result)
Parses a C-style string from the BSON input.
Definition json.h:10019
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.h:9931
bool get_cbor_array(const std::size_t len, const cbor_tag_handler_t tag_handler)
Definition json.h:10934
bool get_msgpack_array(const std::size_t len)
Definition json.h:11603
char_int_type get()
get next character from the input
Definition json.h:12609
typename BasicJsonType::number_float_t number_float_t
Definition json.h:9897
bool get_msgpack_binary(binary_t &result)
reads a MessagePack byte array
Definition json.h:11492
bool parse_ubjson_internal(const bool get_char=true)
Definition json.h:11662
bool get_ubjson_size_value(std::size_t &result, bool &is_ndarray, char_int_type prefix=0)
Definition json.h:11841
bool parse_cbor_internal(const bool get_char, const cbor_tag_handler_t tag_handler)
Definition json.h:10252
bool get_ubjson_object()
Definition json.h:12447
bool get_bson_string(const NumberType len, string_t &result)
Parses a zero-terminated string of length len from the BSON input.
Definition json.h:10049
bool get_ubjson_string(string_t &result, const bool get_char=true)
reads a UBJSON string
Definition json.h:11681
bool get_to(T &dest, const input_format_t format, const char *context)
get_to read into a primitive type
Definition json.h:12624
bool get_cbor_string(string_t &result)
reads a CBOR string
Definition json.h:10743
bool get_bson_binary(const NumberType len, binary_t &result)
Parses a byte array input of length len from the BSON input.
Definition json.h:10071
binary_reader & operator=(binary_reader &&)=default
serialization to CBOR and MessagePack values
Definition json.h:15865
void write_bson_binary(const string_t &name, const binary_t &value)
Writes a BSON element with key name and binary value value.
Definition json.h:16978
void write_bson_boolean(const string_t &name, const bool value)
Writes a BSON element with key name and boolean value value.
Definition json.h:16815
void write_bson(const BasicJsonType &j)
Definition json.h:15885
typename BasicJsonType::binary_t binary_t
Definition json.h:15867
void write_bson_integer(const string_t &name, const std::int64_t value)
Writes a BSON element with key name and integer value.
Definition json.h:16875
typename BasicJsonType::string_t string_t
Definition json.h:15866
static constexpr CharType to_char_type(std::uint8_t x) noexcept
Definition json.h:17625
static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
Definition json.h:16893
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.h:16565
void write_bson_array(const string_t &name, const typename BasicJsonType::array_t &value)
Writes a BSON element with key name and array value.
Definition json.h:16959
static CharType to_char_type(std::uint8_t x) noexcept
Definition json.h:17632
static constexpr CharType get_cbor_float_prefix(double)
Definition json.h:17124
void write_bson_string(const string_t &name, const string_t &value)
Writes a BSON element with key name and string value value.
Definition json.h:16843
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition json.h:15876
static constexpr CharType get_ubjson_float_prefix(double)
Definition json.h:17439
void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix, const bool use_bjdata)
Definition json.h:17150
static constexpr CharType get_msgpack_float_prefix(double)
Definition json.h:17138
void write_bson_element(const string_t &name, const BasicJsonType &j)
Serializes the JSON value j to BSON and associates it with the key name.
Definition json.h:17041
static constexpr CharType to_char_type(InputCharType x) noexcept
Definition json.h:17667
void write_bson_object(const typename BasicJsonType::object_t &value)
Definition json.h:17103
void write_bson_double(const string_t &name, const double value)
Writes a BSON element with key name and double value value.
Definition json.h:16825
static std::size_t calc_bson_string_size(const string_t &value)
Definition json.h:16835
void write_number(const NumberType n, const bool OutputIsLittleEndian=false)
Definition json.h:17575
static std::size_t calc_bson_entry_header_size(const string_t &name, const BasicJsonType &j)
Definition json.h:16788
void write_bson_null(const string_t &name)
Writes a BSON element with key name and null value.
Definition json.h:16857
typename BasicJsonType::number_float_t number_float_t
Definition json.h:15868
CharType ubjson_prefix(const BasicJsonType &j, const bool use_bjdata) const noexcept
determine the type prefix of container values
Definition json.h:17333
void write_bson_unsigned(const string_t &name, const BasicJsonType &j)
Writes a BSON element with key name and unsigned value.
Definition json.h:16903
static constexpr CharType get_ubjson_float_prefix(float)
Definition json.h:17434
static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t &value)
Definition json.h:16951
bool write_bjdata_ndarray(const typename BasicJsonType::object_t &value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
Definition json.h:17447
static std::size_t calc_bson_element_size(const string_t &name, const BasicJsonType &j)
Calculates the size necessary to serialize the JSON value j with its name.
Definition json.h:16993
void write_msgpack(const BasicJsonType &j)
Definition json.h:16238
static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t &value)
Calculates the size of the BSON serialization of the given JSON-object j.
Definition json.h:17088
void write_compact_float(const number_float_t n, detail::input_format_t format)
Definition json.h:17591
void write_cbor(const BasicJsonType &j)
Definition json.h:15914
static constexpr CharType get_cbor_float_prefix(float)
Definition json.h:17119
void write_bson_entry_header(const string_t &name, const std::uint8_t element_type)
Writes the given element_type and name to the output adapter.
Definition json.h:16803
void write_bson_object_entry(const string_t &name, const typename BasicJsonType::object_t &value)
Writes a BSON element with key name and object value.
Definition json.h:16926
static constexpr CharType get_msgpack_float_prefix(float)
Definition json.h:17133
static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t &value)
Definition json.h:16936
static std::size_t calc_bson_integer_size(const std::int64_t value)
Definition json.h:16865
general exception of the basic_json class
Definition json.h:4542
static std::string get_byte_positions(const BasicJsonType *leaf_element)
Definition json.h:4647
const int id
the id of the exception
Definition json.h:4551
static std::string diagnostics(std::nullptr_t)
Definition json.h:4562
std::runtime_error m
an exception object as storage for error messages
Definition json.h:4634
static std::string name(const std::string &ename, int id_)
Definition json.h:4557
const char * what() const noexcept override
returns the explanatory string
Definition json.h:4545
static std::string diagnostics(const BasicJsonType *leaf_element)
Definition json.h:4568
Input adapter for stdio file access.
Definition json.h:6544
file_input_adapter(const file_input_adapter &)=delete
std::FILE * m_file
the file pointer to read from
Definition json.h:6576
std::char_traits< char >::int_type get_character() noexcept
Definition json.h:6562
file_input_adapter(file_input_adapter &&) noexcept=default
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.h:6569
Input adapter for a (caching) istream.
Definition json.h:6589
input_stream_adapter & operator=(input_stream_adapter &&)=delete
std::istream * is
the associated input stream
Definition json.h:6646
input_stream_adapter(input_stream_adapter &&rhs) noexcept
Definition json.h:6612
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.h:6634
std::char_traits< char >::int_type get_character()
Definition json.h:6622
input_stream_adapter(const input_stream_adapter &)=delete
std::streambuf * sb
Definition json.h:6647
input_stream_adapter & operator=(input_stream_adapter &)=delete
input_stream_adapter(std::istream &i)
Definition json.h:6603
exception indicating errors with iterators
Definition json.h:4711
static invalid_iterator create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.h:4714
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition json.h:13684
~iter_impl()=default
iter_impl operator+(difference_type i) const
add to iterator
Definition json.h:14267
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.h:13821
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.h:14212
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.h:13811
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.h:14154
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.h:14194
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.h:14258
iter_impl & operator--()
pre-decrement (–it)
Definition json.h:14064
const object_t::key_type & key() const
return the key of an object iterator
Definition json.h:14367
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.h:14105
iter_impl operator++(int) &
post-increment (it++)
Definition json.h:14002
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.h:14221
reference operator[](difference_type n) const
access to successor
Definition json.h:14329
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition json.h:13714
pointer operator->() const
dereference the iterator
Definition json.h:13960
friend other_iter_impl
allow basic_json to access private members
Definition json.h:13688
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
Definition json.h:14392
difference_type operator-(const iter_impl &other) const
return difference
Definition json.h:14300
iter_impl(iter_impl &&) noexcept=default
std::bidirectional_iterator_tag iterator_category
The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
Definition json.h:13709
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.h:14278
reference value() const
return the value of an iterator
Definition json.h:14383
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.h:14203
typename BasicJsonType::array_t array_t
Definition json.h:13694
typename BasicJsonType::object_t object_t
Definition json.h:13693
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition json.h:13718
iter_impl & operator++()
pre-increment (++it)
Definition json.h:14013
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition json.h:13712
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.h:13916
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.h:14289
iter_impl()=default
friend BasicJsonType
Definition json.h:13689
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.h:13796
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition json.h:14145
iter_impl operator--(int) &
post-decrement (it–)
Definition json.h:14053
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition json.h:13723
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.h:13786
void set_end() noexcept
set the iterator past the last value
Definition json.h:13877
iteration_proxy_value operator++(int) &
Definition json.h:5559
iteration_proxy_value(iteration_proxy_value const &)=default
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.h:5568
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.h:5574
std::ptrdiff_t difference_type
Definition json.h:5505
string_type empty_str
an empty string (to return a reference for primitive values)
Definition json.h:5522
iteration_proxy_value(IteratorType it, std::size_t array_index_=0) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_default_constructible< string_type >::value)
Definition json.h:5526
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.h:5551
std::forward_iterator_tag iterator_category
Definition json.h:5509
std::size_t array_index_last
last stringified array index
Definition json.h:5518
std::size_t array_index
an index for arrays (used to create key names)
Definition json.h:5516
iteration_proxy_value(iteration_proxy_value &&) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_move_constructible< string_type >::value)=default
IteratorType::reference value() const
return value of the iterator
Definition json.h:5616
const string_type & key() const
return key of the iterator
Definition json.h:5580
iteration_proxy_value & operator=(iteration_proxy_value const &)=default
string_type array_index_str
a string representation of the array index
Definition json.h:5520
typename std::remove_cv< typename std::remove_reference< decltype(std::declval< IteratorType >().key()) >::type >::type string_type
Definition json.h:5510
IteratorType anchor
the iterator
Definition json.h:5514
proxy class for the items() function
Definition json.h:5624
IteratorType::pointer container
the container to iterate
Definition json.h:5627
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.h:5649
iteration_proxy(iteration_proxy const &)=default
iteration_proxy(iteration_proxy &&) noexcept=default
iteration_proxy_value< IteratorType > begin() const noexcept
return iterator begin (needed for range-based for)
Definition json.h:5643
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.h:5633
iteration_proxy & operator=(iteration_proxy const &)=default
char_traits< char_type >::int_type get_character()
Definition json.h:6663
iterator_input_adapter(IteratorType first, IteratorType last)
Definition json.h:6659
typename std::iterator_traits< IteratorType >::value_type char_type
Definition json.h:6657
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.h:6677
json_ref(json_ref &&) noexcept=default
json_ref(const value_type &value)
Definition json.h:15605
json_ref(value_type &&value)
Definition json.h:15601
value_type const & operator*() const
Definition json.h:15636
value_type const * operator->() const
Definition json.h:15641
json_ref(std::initializer_list< json_ref > init)
Definition json.h:15609
json_ref(Args &&... args)
Definition json.h:15616
value_type moved_or_copied() const
Definition json.h:15627
BasicJsonType value_type
Definition json.h:15599
a template for a reverse iterator class
Definition json.h:14446
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition json.h:14462
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition json.h:14474
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.h:14468
std::ptrdiff_t difference_type
Definition json.h:14448
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.h:14486
reference operator[](difference_type n) const
access to successor
Definition json.h:14510
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.h:14516
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.h:14504
typename Base::reference reference
the reference type for the pointed-to element
Definition json.h:14452
reference value() const
return the value of an iterator
Definition json.h:14523
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.h:14459
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.h:14480
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.h:14450
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.h:14498
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.h:14455
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.h:14492
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.h:9612
bool binary(binary_t &)
Definition json.h:9647
bool number_integer(number_integer_t)
Definition json.h:9627
bool start_array(std::size_t=detail::unknown_size())
Definition json.h:9667
bool number_unsigned(number_unsigned_t)
Definition json.h:9632
bool start_object(std::size_t=detail::unknown_size())
Definition json.h:9652
bool string(string_t &)
Definition json.h:9642
typename BasicJsonType::binary_t binary_t
Definition json.h:9615
bool number_float(number_float_t, const string_t &)
Definition json.h:9637
bool parse_error(std::size_t, const std::string &, const detail::exception &)
Definition json.h:9677
bool key(string_t &)
Definition json.h:9657
typename BasicJsonType::number_integer_t number_integer_t
Definition json.h:9611
typename BasicJsonType::number_float_t number_float_t
Definition json.h:9613
typename BasicJsonType::string_t string_t
Definition json.h:9614
bool start_array(std::size_t len)
Definition json.h:9340
typename BasicJsonType::parser_callback_t parser_callback_t
Definition json.h:9179
typename BasicJsonType::parse_event_t parse_event_t
Definition json.h:9180
json_sax_dom_callback_parser & operator=(json_sax_dom_callback_parser &&)=default
bool number_integer(number_integer_t val)
Definition json.h:9211
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.h:9419
typename BasicJsonType::number_float_t number_float_t
Definition json.h:9176
json_sax_dom_callback_parser & operator=(const json_sax_dom_callback_parser &)=delete
lexer< BasicJsonType, InputAdapterType > lexer_t
Definition json.h:9181
bool number_unsigned(number_unsigned_t val)
Definition json.h:9217
bool number_float(number_float_t val, const string_t &)
Definition json.h:9223
constexpr bool is_errored() const
Definition json.h:9431
json_sax_dom_callback_parser(BasicJsonType &r, parser_callback_t cb, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.h:9183
bool binary(binary_t &val)
Definition json.h:9235
typename BasicJsonType::string_t string_t
Definition json.h:9177
bool string(string_t &val)
Definition json.h:9229
json_sax_dom_callback_parser(json_sax_dom_callback_parser &&)=default
BasicJsonType & root
the parsed JSON value
Definition json.h:9586
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.h:9175
typename BasicJsonType::number_integer_t number_integer_t
Definition json.h:9174
typename BasicJsonType::binary_t binary_t
Definition json.h:9178
bool start_object(std::size_t len)
Definition json.h:9241
std::pair< bool, BasicJsonType * > handle_value(Value &&v, const bool skip_callback=false)
Definition json.h:9518
json_sax_dom_callback_parser(const json_sax_dom_callback_parser &)=delete
SAX implementation to create a JSON value from SAX events.
Definition json.h:8866
bool number_float(number_float_t val, const string_t &)
Definition json.h:8915
bool number_unsigned(number_unsigned_t val)
Definition json.h:8909
json_sax_dom_parser(const json_sax_dom_parser &)=delete
json_sax_dom_parser & operator=(const json_sax_dom_parser &)=delete
bool binary(binary_t &val)
Definition json.h:8927
typename BasicJsonType::binary_t binary_t
Definition json.h:8872
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.h:8880
bool start_object(std::size_t len)
Definition json.h:8933
typename BasicJsonType::number_integer_t number_integer_t
Definition json.h:8868
bool key(string_t &val)
Definition json.h:8956
typename BasicJsonType::string_t string_t
Definition json.h:8871
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.h:8869
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.h:9024
lexer< BasicJsonType, InputAdapterType > lexer_t
Definition json.h:8873
bool boolean(bool val)
Definition json.h:8897
bool start_array(std::size_t len)
Definition json.h:8984
typename BasicJsonType::number_float_t number_float_t
Definition json.h:8870
JSON_HEDLEY_RETURNS_NON_NULL BasicJsonType * handle_value(Value &&v)
Definition json.h:9119
BasicJsonType & root
the parsed JSON value
Definition json.h:9157
json_sax_dom_parser(json_sax_dom_parser &&)=default
constexpr bool is_errored() const
Definition json.h:9036
bool string(string_t &val)
Definition json.h:8921
json_sax_dom_parser & operator=(json_sax_dom_parser &&)=default
bool number_integer(number_integer_t val)
Definition json.h:8903
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.h:7133
token_type
token types for the parser
Definition json.h:7110
@ value_float
an floating point number – use get_number_float() for actual value
@ begin_array
the character for array begin [
@ value_string
a string – use get_string() for actual value
@ end_array
the character for array end ]
@ uninitialized
indicating the scanner is uninitialized
@ parse_error
indicating a parse error
@ value_integer
a signed integer – use get_number_integer() for actual value
@ value_separator
the value separator ,
@ end_object
the character for object end }
@ literal_true
the true literal
@ begin_object
the character for object begin {
@ value_unsigned
an unsigned integer – use get_number_unsigned() for actual value
@ literal_null
the null literal
@ end_of_input
indicating the end of the input buffer
@ name_separator
the name separator :
@ literal_or_value
a literal or the begin of a value (only for diagnostics)
@ literal_false
the false literal
lexical analysis
Definition json.h:7183
void reset() noexcept
reset token_buffer; current character is beginning of token
Definition json.h:8393
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.h:8565
string_t token_buffer
buffer for variable-length tokens (numbers, strings)
Definition json.h:8696
int get_codepoint()
get codepoint from 4 hex characters following \u
Definition json.h:7240
token_type scan_string()
scan a string literal
Definition json.h:7325
number_integer_t value_integer
Definition json.h:8702
void skip_whitespace()
Definition json.h:8579
const bool ignore_comments
whether comments should be ignored (true) or signaled as errors (false)
Definition json.h:8681
lexer(InputAdapterType &&adapter, bool ignore_comments_=false) noexcept
Definition json.h:7194
char_int_type current
the current character
Definition json.h:8684
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.h:8552
std::string get_token_string() const
return the last read token (for errors only).
Definition json.h:8527
typename BasicJsonType::number_float_t number_float_t
Definition json.h:7186
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.h:8486
typename BasicJsonType::string_t string_t
Definition json.h:7187
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.h:7185
bool next_byte_in_range(std::initializer_list< char_int_type > ranges)
check if the next byte(s) are inside a given range
Definition json.h:7288
char_int_type get()
Definition json.h:8411
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.h:8519
static void strtof(float &f, const char *str, char **endptr) noexcept
Definition json.h:7983
const char_int_type decimal_point_char
the decimal point
Definition json.h:8707
number_unsigned_t value_unsigned
Definition json.h:8703
typename BasicJsonType::number_integer_t number_integer_t
Definition json.h:7184
token_type scan()
Definition json.h:8588
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.h:8492
typename char_traits< char_type >::int_type char_int_type
Definition json.h:7189
bool scan_comment()
scan a comment
Definition json.h:7915
typename lexer_base< BasicJsonType >::token_type token_type
Definition json.h:7192
lexer(lexer &&)=default
~lexer()=default
const char * error_message
a description of occurred lexer errors
Definition json.h:8699
lexer & operator=(lexer &&)=default
bool next_unget
whether the next get() call should just return current
Definition json.h:8687
lexer(const lexer &)=delete
std::size_t decimal_point_position
the position of the decimal point in the input
Definition json.h:8709
typename InputAdapterType::char_type char_type
Definition json.h:7188
InputAdapterType ia
input adapter
Definition json.h:8678
lexer & operator=(lexer &)=delete
token_type scan_number()
scan a number literal
Definition json.h:8040
number_float_t value_float
Definition json.h:8704
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.h:8504
token_type scan_literal(const char_type *literal_text, const std::size_t length, token_type return_type)
Definition json.h:8373
std::vector< char_type > token_string
raw input token string (for error messages)
Definition json.h:8693
void add(char_int_type c)
add a character to token_buffer
Definition json.h:8475
position_t position
the start position of the current token
Definition json.h:8690
void unget()
unget current character (read it again on next get)
Definition json.h:8448
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.h:8498
static JSON_HEDLEY_PURE char get_decimal_point() noexcept
return the locale-dependent decimal point
Definition json.h:7214
exception indicating other library errors
Definition json.h:4763
static other_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.h:4766
exception indicating access out of the defined range
Definition json.h:4746
static out_of_range create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.h:4749
output_adapter(StringType &s)
Definition json.h:15827
output_adapter(std::basic_ostream< CharType > &s)
Definition json.h:15823
output_adapter(std::vector< CharType, AllocatorType > &vec)
Definition json.h:15819
output adapter for output streams
Definition json.h:15768
output_stream_adapter(std::basic_ostream< CharType > &s) noexcept
Definition json.h:15770
void write_character(CharType c) override
Definition json.h:15774
std::basic_ostream< CharType > & stream
Definition json.h:15786
output adapter for basic_string
Definition json.h:15793
void write_character(CharType c) override
Definition json.h:15799
output_string_adapter(StringType &s) noexcept
Definition json.h:15795
output adapter for byte vectors
Definition json.h:15743
std::vector< CharType, AllocatorType > & v
Definition json.h:15761
output_vector_adapter(std::vector< CharType, AllocatorType > &vec) noexcept
Definition json.h:15745
void write_character(CharType c) override
Definition json.h:15749
exception indicating a parse error
Definition json.h:4658
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
Definition json.h:4670
static std::string position_string(const position_t &pos)
Definition json.h:4701
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg, BasicJsonContext context)
Definition json.h:4678
const std::size_t byte
byte index of the parse error
Definition json.h:4695
parse_error(int id_, std::size_t byte_, const char *what_arg)
Definition json.h:4698
syntax analysis
Definition json.h:12980
std::string exception_message(const token_type expected, const std::string &context)
Definition json.h:13412
typename lexer_t::token_type token_type
Definition json.h:12986
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.h:13014
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.h:12982
typename BasicJsonType::number_integer_t number_integer_t
Definition json.h:12981
typename BasicJsonType::string_t string_t
Definition json.h:12984
lexer_t m_lexer
the lexer
Definition json.h:13447
lexer< BasicJsonType, InputAdapterType > lexer_t
Definition json.h:12985
bool accept(const bool strict=true)
public accept interface
Definition json.h:13074
typename BasicJsonType::number_float_t number_float_t
Definition json.h:12983
token_type get_token()
get next token from lexer
Definition json.h:13407
parser(InputAdapterType &&adapter, parser_callback_t< BasicJsonType > cb=nullptr, const bool allow_exceptions_=true, const bool ignore_comments=false, const bool ignore_trailing_commas_=false)
a parser reading from an input adapter
Definition json.h:12990
primitive_iterator_t & operator++() noexcept
Definition json.h:13563
primitive_iterator_t & operator-=(difference_type n) noexcept
Definition json.h:13595
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition json.h:13530
primitive_iterator_t & operator--() noexcept
Definition json.h:13576
void set_end() noexcept
set iterator to a defined past the end
Definition json.h:13524
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.h:13546
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition json.h:13536
primitive_iterator_t operator++(int) &noexcept
Definition json.h:13569
primitive_iterator_t & operator+=(difference_type n) noexcept
Definition json.h:13589
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.h:13541
constexpr difference_type get_value() const noexcept
Definition json.h:13512
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.h:13558
primitive_iterator_t operator+(difference_type n) noexcept
Definition json.h:13551
void set_begin() noexcept
set iterator to a defined beginning
Definition json.h:13518
primitive_iterator_t operator--(int) &noexcept
Definition json.h:13582
std::ptrdiff_t difference_type
Definition json.h:13503
typename BasicJsonType::binary_t::value_type binary_char_t
Definition json.h:18869
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.h:18868
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.h:18879
serializer & operator=(const serializer &)=delete
~serializer()=default
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition json.h:19796
string_t indent_string
the indentation string
Definition json.h:19793
typename BasicJsonType::number_integer_t number_integer_t
Definition json.h:18867
typename BasicJsonType::number_float_t number_float_t
Definition json.h:18866
serializer & operator=(serializer &&)=delete
typename BasicJsonType::string_t string_t
Definition json.h:18865
const char indent_char
the indentation character
Definition json.h:19791
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.h:18919
serializer(const serializer &)=delete
serializer(serializer &&)=delete
span_input_adapter(CharT b, std::size_t l)
Definition json.h:7025
contiguous_bytes_input_adapter ia
Definition json.h:7041
span_input_adapter(IteratorType first, IteratorType last)
Definition json.h:7032
contiguous_bytes_input_adapter && get()
Definition json.h:7035
exception indicating executing a member function with a wrong type
Definition json.h:4729
static type_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.h:4732
std::size_t get_elements(T *, std::size_t=1)
Definition json.h:6860
std::char_traits< char >::int_type get_character() noexcept
Definition json.h:6841
std::array< std::char_traits< char >::int_type, 4 > utf8_bytes
a buffer for UTF-8 bytes
Definition json.h:6875
std::size_t utf8_bytes_filled
number of valid bytes in the utf8_codes array
Definition json.h:6880
BaseInputAdapter base_adapter
Definition json.h:6866
wide_string_input_adapter(BaseInputAdapter base)
Definition json.h:6838
std::size_t utf8_bytes_index
index to the utf8_codes array for the next valid byte
Definition json.h:6878
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition json.h:14618
BasicJsonType & get_checked(BasicJsonType *ptr) const
Definition json.h:15004
json_pointer< string_t > convert() const &
Definition json.h:15417
friend json_pointer operator/(const json_pointer &lhs, string_t token)
create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
Definition json.h:14713
static BasicJsonType::size_type array_index(const string_t &s)
Definition json.h:14796
typename string_t_helper< RefStringType >::type string_t
Definition json.h:14640
friend json_pointer operator/(const json_pointer &lhs, std::size_t array_idx)
create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
Definition json.h:14720
result reference_tokens
Definition json.h:14842
json_pointer(const string_t &s="")
create JSON pointer
Definition json.h:14644
static std::vector< string_t > split(const string_t &reference_string)
split the string input to reference tokens
Definition json.h:15248
bool empty() const noexcept
return whether pointer points to the root document
Definition json.h:14779
BasicJsonType & get_and_create(BasicJsonType &j) const
create and return a reference to the pointed to value
Definition json.h:14856
void pop_back()
remove last reference token
Definition json.h:14741
string_t to_string() const
return a string representation of the JSON pointer
Definition json.h:14650
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition json.h:14698
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition json.h:14772
json_pointer< string_t > convert() &&
Definition json.h:15424
std::vector< string_t > reference_tokens
the reference tokens
Definition json.h:15507
return result
Definition json.h:14843
static void flatten(const string_t &reference_string, const BasicJsonType &value, BasicJsonType &result)
Definition json.h:15317
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition json.h:14680
friend json_pointer operator/(const json_pointer &lhs, const json_pointer &rhs)
create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
Definition json.h:14705
BasicJsonType & get_unchecked(BasicJsonType *ptr) const
return a reference to the pointed to value
Definition json.h:14936
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition json.h:14727
static BasicJsonType unflatten(const BasicJsonType &value)
Definition json.h:15389
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition json.h:14690
const string_t & back() const
return last reference token
Definition json.h:14753
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition json.h:14671
const BasicJsonType & get_unchecked(const BasicJsonType *ptr) const
return a const reference to the pointed to value
Definition json.h:15062
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition json.h:14765
const BasicJsonType & get_checked(const BasicJsonType *ptr) const
Definition json.h:15111
bool contains(const BasicJsonType *ptr) const
Definition json.h:15160
decltype(get< N >(std::declval< ::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
Definition json.h:5697
bool operator>=(const int64x64_t &lhs, const int64x64_t &rhs)
Greater or equal operator.
Definition int64x64.h:162
bool operator<=(const int64x64_t &lhs, const int64x64_t &rhs)
Less or equal operator.
Definition int64x64.h:149
bool operator>(const Length &left, const Length &right)
Check if left has a value greater than right.
Definition length.cc:410
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
Definition json.h:2624
#define JSON_HEDLEY_CONST
Definition json.h:1831
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
Definition json.h:1115
#define JSON_INLINE_VARIABLE
Definition json.h:2523
#define JSON_HEDLEY_WARN_UNUSED_RESULT
Definition json.h:1461
#define JSON_PRIVATE_UNLESS_TESTED
Definition json.h:2583
#define NLOHMANN_JSON_VERSION_PATCH
Definition json.h:72
#define JSON_HEDLEY_LIKELY(expr)
Definition json.h:1726
#define JSON_HEDLEY_NON_NULL(...)
Definition json.h:1619
#define JSON_INTERNAL_CATCH(exception)
Definition json.h:2550
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition json.h:25320
#define JSON_HEDLEY_RETURNS_NON_NULL
Definition json.h:2060
bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.h:15513
#define JSON_CATCH(exception)
Definition json.h:2549
#define JSON_ASSERT(x)
Definition json.h:2576
#define JSON_THROW(exception)
Definition json.h:2547
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
Definition json.h:83
#define NLOHMANN_JSON_VERSION_MAJOR
Definition json.h:70
#define NLOHMANN_BASIC_JSON_TPL
Definition json.h:2634
#define JSON_HEDLEY_UNLIKELY(expr)
Definition json.h:1727
#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
Definition json.h:12869
#define JSON_TRY
Definition json.h:2548
#define NLOHMANN_JSON_NAMESPACE_END
Definition json.h:157
#define JSON_NO_UNIQUE_ADDRESS
Definition json.h:2529
bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.h:15538
#define NLOHMANN_JSON_VERSION_MINOR
Definition json.h:71
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)
Definition json.h:2918
#define NLOHMANN_JSON_NAMESPACE_BEGIN
Definition json.h:147
#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
Definition json.h:12866
#define JSON_HEDLEY_DIAGNOSTIC_POP
Definition json.h:1116
#define JSON_EXPLICIT
Definition json.h:2957
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
Definition json.h:1409
#define JSON_HEDLEY_PURE
Definition json.h:1800
bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.h:15563
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)
Definition json.h:23716
#define JSON_DIAGNOSTIC_POSITIONS
Definition json.h:79
JSON_INLINE_VARIABLE constexpr const auto & from_json
Definition json.h:5396
JSON_INLINE_VARIABLE constexpr const auto & to_json
Definition json.h:6167
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
Definition json.h:18203
cached_power get_cached_power_for_binary_exponent(int e)
For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached power-of-ten c = f_c ...
Definition json.h:18039
Target reinterpret_bits(const Source source)
Definition json.h:17759
boundaries compute_boundaries(FloatType value)
Compute the (normalized) diyfp representing the input number 'value' and its boundaries.
Definition json.h:17900
void grisu2_round(char *buf, int len, std::uint64_t dist, std::uint64_t delta, std::uint64_t rest, std::uint64_t ten_k)
Definition json.h:18257
constexpr int kAlpha
Definition json.h:18022
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
v = buf * 10^decimal_exponent len is the length of the buffer (number of decimal digits) The buffer m...
Definition json.h:18539
constexpr int kGamma
Definition json.h:18023
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
Definition json.h:18298
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition json.h:18639
constexpr bool is_transparent()
Definition json.h:4352
constexpr bool is_c_string()
Definition json.h:4324
detail namespace with internal helper functions
Definition json.h:262
input_format_t
the supported input formats
Definition json.h:6532
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
Definition json.h:6112
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
Definition json.h:322
typename make_void< Ts... >::type void_t
Definition json.h:268
decltype(std::declval< T & >().start_array(std::declval< std::size_t >())) start_array_function_t
Definition json.h:9756
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition json.h:15738
decltype(std::declval< StringType & >()+=std::declval< Arg && >()) string_can_append_op
Definition json.h:4433
decltype(std::declval< T & >().parse_error(std::declval< std::size_t >(), std::declval< const std::string & >(), std::declval< const Exception & >())) parse_error_function_t
Definition json.h:9764
std::function< bool(int, parse_event_t, BasicJsonType &)> parser_callback_t
Definition json.h:12971
OutStringType concat(Args &&... args)
Definition json.h:4507
is_detected< string_can_append_iter, StringType, Arg > detect_string_can_append_iter
Definition json.h:4442
decltype(T::to_json(std::declval< Args >()...)) to_json_function
Definition json.h:3651
constexpr std::array< T, sizeof...(Args)> make_array(Args &&... args)
Definition json.h:3354
decltype(std::declval< T >().template get< U >()) get_template_function
Definition json.h:3657
typename std::conditional< is_usable_as_key_type< typename BasicJsonType::object_comparator_t, typename BasicJsonType::object_t::key_type, KeyTypeCVRef, RequireTransparentComparator, ExcludeObjectKeyType >::value &&!is_json_iterator_of< BasicJsonType, KeyType >::value, std::true_type, std::false_type >::type is_usable_as_basic_json_key_type
Definition json.h:4174
typename T::pointer pointer_t
Definition json.h:3642
parse_event_t
Definition json.h:12954
@ value
the parser finished reading a JSON value
@ key
the parser read a key of a value in an object
@ array_end
the parser read ] and finished processing a JSON array
@ array_start
the parser read [ and started to process a JSON array
@ object_start
the parser read { and started to process a JSON object
@ object_end
the parser read } and finished processing a JSON object
is_detected< string_can_append_op, StringType, Arg > detect_string_can_append_op
Definition json.h:4436
std::pair< A1, A2 > from_json_tuple_impl(BasicJsonType &&j, identity_tag< std::pair< A1, A2 > >, priority_tag< 0 >)
Definition json.h:5280
void from_json_array_impl(const BasicJsonType &j, typename BasicJsonType::array_t &arr, priority_tag< 3 >)
Definition json.h:5085
typename utility_internal::Gen< T, N >::type make_integer_sequence
Definition json.h:3315
typename T::value_type value_type_t
Definition json.h:3636
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
Definition json.h:326
void int_to_string(StringType &target, std::size_t value)
Definition json.h:5477
T conditional_static_cast(U value)
Definition json.h:4208
is_detected< string_can_append_data, StringType, Arg > detect_string_can_append_data
Definition json.h:4448
typename std::enable_if< B, T >::type enable_if_t
Definition json.h:3227
decltype(std::declval< T & >().number_integer(std::declval< Integer >())) number_integer_function_t
Definition json.h:9725
typename T::mapped_type mapped_type_t
Definition json.h:3630
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.h:3103
decltype(std::declval< T & >().number_float(std::declval< Float >(), std::declval< const String & >())) number_float_function_t
Definition json.h:9733
enable_if_t< is_range< R >::value, result_of_begin< decltype(std::declval< R & >())> > iterator_t
Definition json.h:3902
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition json.h:5659
bool little_endianness(int num=1) noexcept
determine system byte order
Definition json.h:9880
cbor_tag_handler_t
how to treat CBOR tags
Definition json.h:9867
@ store
store tags as binary type
@ error
throw a parse_error exception in case of a tag
typename detected_or< Default, Op, Args... >::type detected_or_t
Definition json.h:319
decltype(T::from_json(std::declval< Args >()...)) from_json_function
Definition json.h:3654
decltype(input_adapter(std::declval< const char * >(), std::declval< const char * >())) contiguous_bytes_input_adapter
Definition json.h:6986
make_integer_sequence< size_t, N > make_index_sequence
Definition json.h:3323
std::integral_constant< bool, Value > bool_constant
Definition json.h:4314
void concat_into(OutStringType &)
Definition json.h:4423
typename T::key_type key_type_t
Definition json.h:3633
constexpr bool value_in_range_of(T val)
Definition json.h:4308
value_t
the JSON type enumeration
Definition json.h:3005
@ null
null value
@ number_integer
number value (signed integer)
@ boolean
boolean value
@ discarded
discarded by the parser callback function
@ binary
binary array (ordered collection of bytes)
@ object
object (unordered set of name/value pairs)
@ string
string value
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
std::integral_constant< bool, all_signed< Types... >::value||all_unsigned< Types... >::value > same_sign
Definition json.h:4231
constexpr std::size_t unknown_size()
Definition json.h:8846
decltype(std::declval< T & >().binary(std::declval< Binary & >())) binary_function_t
Definition json.h:9741
std::array< T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType &&j, identity_tag< std::array< T, sizeof...(Idx)> >, index_sequence< Idx... >)
Definition json.h:5168
StringType to_string(std::size_t value)
Definition json.h:5485
typename detector< nonesuch, void, Op, Args... >::type detected_t
Definition json.h:313
typename std::conditional< is_comparable< Comparator, ObjectKeyType, KeyTypeCVRef >::value &&!(ExcludeObjectKeyType &&std::is_same< KeyType, ObjectKeyType >::value) &&(!RequireTransparentComparator||is_detected< detect_is_transparent, Comparator >::value) &&!is_json_pointer< KeyType >::value, std::true_type, std::false_type >::type is_usable_as_key_type
Definition json.h:4158
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition json.h:6372
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().begin(), std::declval< const Arg & >().end())) string_can_append_iter
Definition json.h:4439
typename T::iterator_category iterator_category_t
Definition json.h:3648
void unescape(StringType &s)
string unescaping as described in RFC 6901 (Sect.
Definition json.h:3137
decltype(input_adapter(std::declval< std::string >())) string_input_adapter_type
Definition json.h:6962
std::size_t combine(std::size_t seed, std::size_t h) noexcept
Definition json.h:6354
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.h:3034
iterator_input_adapter_factory< IteratorType >::adapter_type input_adapter(IteratorType first, IteratorType last)
Definition json.h:6922
decltype(std::declval< T & >().end_array()) end_array_function_t
Definition json.h:9759
typename std::conditional< is_detected< detect_erase_with_key_type, typename BasicJsonType::object_t, KeyType >::value, std::true_type, std::false_type >::type has_erase_with_key_type
Definition json.h:4186
error_handler_t
how to treat decoding errors
Definition json.h:18856
@ strict
throw a type_error exception in case of invalid UTF-8
@ replace
replace invalid UTF-8 sequences with U+FFFD
std::size_t concat_length()
Definition json.h:4392
value_type_t< iterator_traits< iterator_t< T > > > range_value_t
Definition json.h:3905
void from_json(const BasicJsonType &j, typename std::nullptr_t &n)
Definition json.h:4865
typename actual_object_comparator< BasicJsonType >::type actual_object_comparator_t
Definition json.h:3730
decltype(std::declval< StringType & >().append(std::declval< Arg && >())) string_can_append
Definition json.h:4427
void to_json(BasicJsonType &j, T b) noexcept
Definition json.h:5973
void get_arithmetic_value(const BasicJsonType &j, ArithmeticType &val)
Definition json.h:4894
decltype(std::declval< T & >().null()) null_function_t
Definition json.h:9717
make_index_sequence< sizeof...(Ts)> index_sequence_for
Definition json.h:3331
typename T::difference_type difference_type_t
Definition json.h:3639
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition json.h:3213
std::tuple< Args... > from_json_tuple_impl_base(BasicJsonType &&j, index_sequence< Idx... >)
Definition json.h:5268
typename T::is_transparent detect_is_transparent
Definition json.h:4144
decltype(std::declval< T & >().string(std::declval< String & >())) string_function_t
Definition json.h:9737
typename std::conditional< std::is_same< T, void >::value, json_default_base, T >::type json_base_class
Definition json.h:14572
typename T::reference reference_t
Definition json.h:3645
decltype(std::declval< T & >().boolean(std::declval< bool >())) boolean_function_t
Definition json.h:9721
decltype(std::declval< T & >().end_object()) end_object_function_t
Definition json.h:9752
bjdata_version_t
how to encode BJData
Definition json.h:15851
decltype(std::declval< ObjectType & >().erase(std::declval< KeyType >())) detect_erase_with_key_type
Definition json.h:4177
typename T::key_compare detect_key_compare
Definition json.h:3714
decltype(std::declval< T & >().start_object(std::declval< std::size_t >())) start_object_function_t
Definition json.h:9745
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().data(), std::declval< const Arg & >().size())) string_can_append_data
Definition json.h:4445
decltype(std::declval< T & >().number_unsigned(std::declval< Unsigned >())) number_unsigned_function_t
Definition json.h:9729
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect.
Definition json.h:3122
std::integral_constant< bool,(std::is_signed< OfType >::value &&(sizeof(T)< sizeof(OfType)))||(same_sign< OfType, T >::value &&sizeof(OfType)==sizeof(T)) > never_out_of_range
Definition json.h:4236
is_detected< string_can_append, StringType, Arg > detect_string_can_append
Definition json.h:4430
decltype(std::declval< T & >().key(std::declval< String & >())) key_function_t
Definition json.h:9749
Definition first.py:1
std::istream & operator>>(std::istream &is, Angles &a)
Definition angles.cc:172
STL namespace.
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition json.h:25401
-ns3 Test suite for the ns3 wrapper script
-ray-to-three-gpp-ch-calibration
#define delete
#define E(name, start, end)
std::ostream & operator<<(std::ostream &os, const PairObject &obj)
Stream insertion operator.
uint8_t data[writeSize]
namespace for Niels Lohmann
Definition json.h:6183
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.h:6207
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.h:6197
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.h:6187
typename BasicJsonType::object_t object_t
Definition json.h:3723
typename BasicJsonType::default_object_comparator_t object_comparator_t
Definition json.h:3724
typename std::conditional< has_key_compare< object_t >::value, typename object_t::key_compare, object_comparator_t >::type type
Definition json.h:3726
static constexpr int_type eof() noexcept
Definition json.h:3783
static char_type to_char_type(int_type i) noexcept
Definition json.h:3778
static int_type to_int_type(char_type c) noexcept
Definition json.h:3773
static char_type to_char_type(int_type i) noexcept
Definition json.h:3754
static constexpr int_type eof() noexcept
Definition json.h:3759
static int_type to_int_type(char_type c) noexcept
Definition json.h:3749
std::false_type value_t
Definition json.h:295
Default type
Definition json.h:296
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition json.h:17793
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
Definition json.h:17875
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition json.h:17858
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition json.h:17781
constexpr diyfp(std::uint64_t f_, int e_) noexcept
Definition json.h:17775
std::uint64_t f
Definition json.h:17772
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
Definition json.h:5882
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
Definition json.h:5857
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
Definition json.h:5847
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
Definition json.h:5869
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
Definition json.h:5898
static void construct(BasicJsonType &j, const typename BasicJsonType::binary_t &b)
Definition json.h:5786
static void construct(BasicJsonType &j, typename BasicJsonType::binary_t &&b)
Definition json.h:5795
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
Definition json.h:5740
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
Definition json.h:5808
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
Definition json.h:5834
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
Definition json.h:5821
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
Definition json.h:5917
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
Definition json.h:5938
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
Definition json.h:5927
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
Definition json.h:5762
static void construct(BasicJsonType &j, const CompatibleStringType &str)
Definition json.h:5773
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
Definition json.h:5753
auto operator()(const BasicJsonType &j, T &&val) const noexcept(noexcept(from_json(j, std::forward< T >(val)))) -> decltype(from_json(j, std::forward< T >(val)))
Definition json.h:5379
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.h:3676
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.h:3691
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.h:3706
static constexpr std::size_t size() noexcept
Definition json.h:3257
an iterator value
Definition json.h:13617
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition json.h:13621
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition json.h:13623
static constexpr auto value
Definition json.h:3977
ConstructibleStringType laundered_type
Definition json.h:3988
static constexpr auto value
Definition json.h:3991
static constexpr bool value
Definition json.h:3670
typename std::iterator_traits< T >::value_type value_type
Definition json.h:6899
static one test(decltype(&C::capacity))
static two test(...)
detected_t< result_of_end, t_ref > sentinel
Definition json.h:3889
detected_t< result_of_begin, t_ref > iterator
Definition json.h:3888
typename std::add_lvalue_reference< T >::type t_ref
Definition json.h:3886
static constexpr bool value
Definition json.h:3898
static constexpr auto is_iterator_begin
Definition json.h:3894
typename BasicJsonType::number_integer_t number_integer_t
Definition json.h:9804
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.h:9805
typename BasicJsonType::binary_t binary_t
Definition json.h:9808
typename BasicJsonType::exception exception_t
Definition json.h:9809
typename BasicJsonType::string_t string_t
Definition json.h:9807
typename BasicJsonType::number_float_t number_float_t
Definition json.h:9806
typename BasicJsonType::binary_t binary_t
Definition json.h:9777
typename BasicJsonType::exception exception_t
Definition json.h:9778
typename BasicJsonType::number_float_t number_float_t
Definition json.h:9775
typename BasicJsonType::string_t string_t
Definition json.h:9776
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.h:9774
typename BasicJsonType::number_integer_t number_integer_t
Definition json.h:9773
iterator_input_adapter< iterator_type > adapter_type
Definition json.h:6888
typename std::iterator_traits< iterator_type >::value_type char_type
Definition json.h:6887
static adapter_type create(IteratorType first, IteratorType last)
Definition json.h:6890
Default base class of the basic_json class.
Definition json.h:14565
nonesuch(nonesuch const &&)=delete
~nonesuch()=delete
void operator=(nonesuch &&)=delete
void operator=(nonesuch const &)=delete
nonesuch(nonesuch const &)=delete
abstract output adapter interface
Definition json.h:15724
output_adapter_protocol(const output_adapter_protocol &)=default
virtual ~output_adapter_protocol()=default
virtual void write_character(CharType c)=0
output_adapter_protocol(output_adapter_protocol &&) noexcept=default
virtual void write_characters(const CharType *s, std::size_t length)=0
struct to capture the start position of the current token
Definition json.h:3168
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.h:3172
std::size_t lines_read
the number of lines read
Definition json.h:3174
std::size_t chars_read_total
the total number of characters read
Definition json.h:3170
static JSON_INLINE_VARIABLE constexpr T value
Definition json.h:3345
auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward< T >(val)))) -> decltype(to_json(j, std::forward< T >(val)), void())
Definition json.h:6152
typename Extend< typename Gen< T, N/2 >::type, N/2, N % 2 >::type type
Definition json.h:3296
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.h:6773
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.h:6715
SAX interface.
Definition json.h:8731
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
json_sax()=default
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
typename BasicJsonType::number_integer_t number_integer_t
Definition json.h:8732
typename BasicJsonType::string_t string_t
Definition json.h:8735
virtual bool end_array()=0
the end of an array was read
json_sax(const json_sax &)=default
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
typename BasicJsonType::number_float_t number_float_t
Definition json.h:8734
virtual bool null()=0
a null value was read
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.h:8733
json_sax(json_sax &&) noexcept=default
typename BasicJsonType::binary_t binary_t
Definition json.h:8736
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.h:19838
std::vector< std::pair< const Key, T >, Allocator > Container
Definition json.h:19841
std::pair< iterator, bool > insert(value_type &&value)
Definition json.h:20132
typename Container::value_type value_type
Definition json.h:19845
std::equal_to< Key > key_compare
Definition json.h:19849
iterator erase(iterator pos)
Definition json.h:20010
T mapped_type
Definition json.h:19840
ordered_map(const Allocator &alloc) noexcept(noexcept(Container(alloc)))
Definition json.h:19855
T & operator[](KeyType &&key)
Definition json.h:19897
typename Container::iterator iterator
Definition json.h:19842
const T & at(KeyType &&key) const
Definition json.h:19957
T & at(KeyType &&key)
Definition json.h:19929
const T & operator[](KeyType &&key) const
Definition json.h:19909
iterator find(const key_type &key)
Definition json.h:20094
iterator erase(iterator first, iterator last)
Definition json.h:20015
const T & at(const key_type &key) const
Definition json.h:19942
const_iterator find(const key_type &key) const
Definition json.h:20120
T & operator[](const key_type &key)
Definition json.h:19890
size_type erase(KeyType &&key)
Definition json.h:19991
typename Container::size_type size_type
Definition json.h:19844
ordered_map() noexcept(noexcept(Container()))
Definition json.h:19854
void insert(InputIt first, InputIt last)
Definition json.h:20155
size_type count(const key_type &key) const
Definition json.h:20068
std::pair< iterator, bool > emplace(KeyType &&key, T &&t)
Definition json.h:19877
size_type erase(const key_type &key)
Definition json.h:19970
ordered_map(std::initializer_list< value_type > init, const Allocator &alloc=Allocator())
Definition json.h:19859
std::pair< iterator, bool > insert(const value_type &value)
Definition json.h:20137
size_type count(KeyType &&key) const
Definition json.h:20082
Key key_type
Definition json.h:19839
ordered_map(It first, It last, const Allocator &alloc=Allocator())
Definition json.h:19857
typename std::enable_if< std::is_convertible< typename std::iterator_traits< InputIt >::iterator_category, std::input_iterator_tag >::value >::type require_input_iter
Definition json.h:20152
const T & operator[](const key_type &key) const
Definition json.h:19902
iterator find(KeyType &&key)
Definition json.h:20108
T & at(const key_type &key)
Definition json.h:19914
typename Container::const_iterator const_iterator
Definition json.h:19843
std::pair< iterator, bool > emplace(const key_type &key, T &&t)
Definition json.h:19862
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL &j) const
Definition json.h:25370
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.h:25384