Project Alice
Loading...
Searching...
No Matches
json.hpp
Go to the documentation of this file.
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.11.3
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9/****************************************************************************\
10 * Note on documentation: The source files contain links to the online *
11 * documentation of the public API at https://json.nlohmann.me. This URL *
12 * contains the most recent documentation and should also be applicable to *
13 * previous versions; documentation for deprecated functions is not *
14 * removed, but marked deprecated. See "Generate documentation" section in *
15 * file docs/README.md. *
16\****************************************************************************/
17
18#ifndef INCLUDE_NLOHMANN_JSON_HPP_
19#define INCLUDE_NLOHMANN_JSON_HPP_
20
21#include <algorithm> // all_of, find, for_each
22#include <cstddef> // nullptr_t, ptrdiff_t, size_t
23#include <functional> // hash, less
24#include <initializer_list> // initializer_list
25#ifndef JSON_NO_IO
26 #include <iosfwd> // istream, ostream
27#endif // JSON_NO_IO
28#include <iterator> // random_access_iterator_tag
29#include <memory> // unique_ptr
30#include <string> // string, stoi, to_string
31#include <utility> // declval, forward, move, pair, swap
32#include <vector> // vector
33
34// #include <nlohmann/adl_serializer.hpp>
35// __ _____ _____ _____
36// __| | __| | | | JSON for Modern C++
37// | | |__ | | | | | | version 3.11.3
38// |_____|_____|_____|_|___| https://github.com/nlohmann/json
39//
40// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
41// SPDX-License-Identifier: MIT
42
43
44
45#include <utility>
46
47// #include <nlohmann/detail/abi_macros.hpp>
48// __ _____ _____ _____
49// __| | __| | | | JSON for Modern C++
50// | | |__ | | | | | | version 3.11.3
51// |_____|_____|_____|_|___| https://github.com/nlohmann/json
52//
53// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
54// SPDX-License-Identifier: MIT
55
56
57
58// This file contains all macro definitions affecting or depending on the ABI
59
60#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
61 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
62 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3
63 #warning "Already included a different version of the library!"
64 #endif
65 #endif
66#endif
67
68#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
69#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
70#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum)
71
72#ifndef JSON_DIAGNOSTICS
73 #define JSON_DIAGNOSTICS 0
74#endif
75
76#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
77 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
78#endif
79
80#if JSON_DIAGNOSTICS
81 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
82#else
83 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
84#endif
85
86#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
87 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
88#else
89 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
90#endif
91
92#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
93 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
94#endif
95
96// Construct the namespace ABI tags component
97#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
98#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
99 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
100
101#define NLOHMANN_JSON_ABI_TAGS \
102 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
103 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
104 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
105
106// Construct the namespace version component
107#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
108 _v ## major ## _ ## minor ## _ ## patch
109#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
110 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
111
112#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
113#define NLOHMANN_JSON_NAMESPACE_VERSION
114#else
115#define NLOHMANN_JSON_NAMESPACE_VERSION \
116 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
117 NLOHMANN_JSON_VERSION_MINOR, \
118 NLOHMANN_JSON_VERSION_PATCH)
119#endif
120
121// Combine namespace components
122#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
123#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
124 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
125
126#ifndef NLOHMANN_JSON_NAMESPACE
127#define NLOHMANN_JSON_NAMESPACE \
128 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
129 NLOHMANN_JSON_ABI_TAGS, \
130 NLOHMANN_JSON_NAMESPACE_VERSION)
131#endif
132
133#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
134#define NLOHMANN_JSON_NAMESPACE_BEGIN \
135 namespace nlohmann \
136 { \
137 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
138 NLOHMANN_JSON_ABI_TAGS, \
139 NLOHMANN_JSON_NAMESPACE_VERSION) \
140 {
141#endif
142
143#ifndef NLOHMANN_JSON_NAMESPACE_END
144#define NLOHMANN_JSON_NAMESPACE_END \
145 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
146 } // namespace nlohmann
147#endif
148
149// #include <nlohmann/detail/conversions/from_json.hpp>
150// __ _____ _____ _____
151// __| | __| | | | JSON for Modern C++
152// | | |__ | | | | | | version 3.11.3
153// |_____|_____|_____|_|___| https://github.com/nlohmann/json
154//
155// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
156// SPDX-License-Identifier: MIT
157
158
159
160#include <algorithm> // transform
161#include <array> // array
162#include <forward_list> // forward_list
163#include <iterator> // inserter, front_inserter, end
164#include <map> // map
165#ifdef JSON_HAS_CPP_17
166 #include <optional> // optional
167#endif
168#include <string> // string
169#include <tuple> // tuple, make_tuple
170#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
171#include <unordered_map> // unordered_map
172#include <utility> // pair, declval
173#include <valarray> // valarray
174
175
176// #include <nlohmann/detail/exceptions.hpp>
177// __ _____ _____ _____
178// __| | __| | | | JSON for Modern C++
179// | | |__ | | | | | | version 3.11.3
180// |_____|_____|_____|_|___| https://github.com/nlohmann/json
181//
182// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
183// SPDX-License-Identifier: MIT
184
185
186
187#include <cstddef> // nullptr_t
188#include <exception> // exception
189#if JSON_DIAGNOSTICS
190 #include <numeric> // accumulate
191#endif
192#include <stdexcept> // runtime_error
193#include <string> // to_string
194#include <vector> // vector
195
196// #include <nlohmann/detail/value_t.hpp>
197// __ _____ _____ _____
198// __| | __| | | | JSON for Modern C++
199// | | |__ | | | | | | version 3.11.3
200// |_____|_____|_____|_|___| https://github.com/nlohmann/json
201//
202// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
203// SPDX-License-Identifier: MIT
204
205
206
207#include <array> // array
208#include <cstddef> // size_t
209#include <cstdint> // uint8_t
210#include <string> // string
211
212// #include <nlohmann/detail/macro_scope.hpp>
213// __ _____ _____ _____
214// __| | __| | | | JSON for Modern C++
215// | | |__ | | | | | | version 3.11.3
216// |_____|_____|_____|_|___| https://github.com/nlohmann/json
217//
218// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
219// SPDX-License-Identifier: MIT
220
221
222
223#include <utility> // declval, pair
224// #include <nlohmann/detail/meta/detected.hpp>
225// __ _____ _____ _____
226// __| | __| | | | JSON for Modern C++
227// | | |__ | | | | | | version 3.11.3
228// |_____|_____|_____|_|___| https://github.com/nlohmann/json
229//
230// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
231// SPDX-License-Identifier: MIT
232
233
234
235#include <type_traits>
236
237// #include <nlohmann/detail/meta/void_t.hpp>
238// __ _____ _____ _____
239// __| | __| | | | JSON for Modern C++
240// | | |__ | | | | | | version 3.11.3
241// |_____|_____|_____|_|___| https://github.com/nlohmann/json
242//
243// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
244// SPDX-License-Identifier: MIT
245
246
247
248// #include <nlohmann/detail/abi_macros.hpp>
249
250
252namespace detail
253{
254
255template<typename ...Ts> struct make_void
256{
257 using type = void;
258};
259template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
260
261} // namespace detail
263
264
266namespace detail
267{
268
269// https://en.cppreference.com/w/cpp/experimental/is_detected
271{
272 nonesuch() = delete;
273 ~nonesuch() = delete;
274 nonesuch(nonesuch const&) = delete;
275 nonesuch(nonesuch const&&) = delete;
276 void operator=(nonesuch const&) = delete;
277 void operator=(nonesuch&&) = delete;
278};
279
280template<class Default,
281 class AlwaysVoid,
282 template<class...> class Op,
283 class... Args>
285{
286 using value_t = std::false_type;
287 using type = Default;
288};
289
290template<class Default, template<class...> class Op, class... Args>
291struct detector<Default, void_t<Op<Args...>>, Op, Args...>
292{
293 using value_t = std::true_type;
294 using type = Op<Args...>;
295};
296
297template<template<class...> class Op, class... Args>
298using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
299
300template<template<class...> class Op, class... Args>
301struct is_detected_lazy : is_detected<Op, Args...> { };
302
303template<template<class...> class Op, class... Args>
304using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
305
306template<class Default, template<class...> class Op, class... Args>
307using detected_or = detector<Default, void, Op, Args...>;
308
309template<class Default, template<class...> class Op, class... Args>
310using detected_or_t = typename detected_or<Default, Op, Args...>::type;
311
312template<class Expected, template<class...> class Op, class... Args>
313using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
314
315template<class To, template<class...> class Op, class... Args>
317 std::is_convertible<detected_t<Op, Args...>, To>;
318
319} // namespace detail
321
322// #include <nlohmann/thirdparty/hedley/hedley.hpp>
323
324
325// __ _____ _____ _____
326// __| | __| | | | JSON for Modern C++
327// | | |__ | | | | | | version 3.11.3
328// |_____|_____|_____|_|___| https://github.com/nlohmann/json
329//
330// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
331// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com>
332// SPDX-License-Identifier: MIT
333
334/* Hedley - https://nemequ.github.io/hedley
335 * Created by Evan Nemerson <evan@nemerson.com>
336 */
337
338#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
339#if defined(JSON_HEDLEY_VERSION)
340 #undef JSON_HEDLEY_VERSION
341#endif
342#define JSON_HEDLEY_VERSION 15
343
344#if defined(JSON_HEDLEY_STRINGIFY_EX)
345 #undef JSON_HEDLEY_STRINGIFY_EX
346#endif
347#define JSON_HEDLEY_STRINGIFY_EX(x) #x
348
349#if defined(JSON_HEDLEY_STRINGIFY)
350 #undef JSON_HEDLEY_STRINGIFY
351#endif
352#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
353
354#if defined(JSON_HEDLEY_CONCAT_EX)
355 #undef JSON_HEDLEY_CONCAT_EX
356#endif
357#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
358
359#if defined(JSON_HEDLEY_CONCAT)
360 #undef JSON_HEDLEY_CONCAT
361#endif
362#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
363
364#if defined(JSON_HEDLEY_CONCAT3_EX)
365 #undef JSON_HEDLEY_CONCAT3_EX
366#endif
367#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
368
369#if defined(JSON_HEDLEY_CONCAT3)
370 #undef JSON_HEDLEY_CONCAT3
371#endif
372#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
373
374#if defined(JSON_HEDLEY_VERSION_ENCODE)
375 #undef JSON_HEDLEY_VERSION_ENCODE
376#endif
377#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
378
379#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
380 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
381#endif
382#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
383
384#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
385 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
386#endif
387#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
388
389#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
390 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
391#endif
392#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
393
394#if defined(JSON_HEDLEY_GNUC_VERSION)
395 #undef JSON_HEDLEY_GNUC_VERSION
396#endif
397#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
398 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
399#elif defined(__GNUC__)
400 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
401#endif
402
403#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
404 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
405#endif
406#if defined(JSON_HEDLEY_GNUC_VERSION)
407 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
408#else
409 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
410#endif
411
412#if defined(JSON_HEDLEY_MSVC_VERSION)
413 #undef JSON_HEDLEY_MSVC_VERSION
414#endif
415#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
416 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
417#elif defined(_MSC_FULL_VER) && !defined(__ICL)
418 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
419#elif defined(_MSC_VER) && !defined(__ICL)
420 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
421#endif
422
423#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
424 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
425#endif
426#if !defined(JSON_HEDLEY_MSVC_VERSION)
427 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
428#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
429 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
430#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
431 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
432#else
433 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
434#endif
435
436#if defined(JSON_HEDLEY_INTEL_VERSION)
437 #undef JSON_HEDLEY_INTEL_VERSION
438#endif
439#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
440 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
441#elif defined(__INTEL_COMPILER) && !defined(__ICL)
442 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
443#endif
444
445#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
446 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
447#endif
448#if defined(JSON_HEDLEY_INTEL_VERSION)
449 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
450#else
451 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
452#endif
453
454#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
455 #undef JSON_HEDLEY_INTEL_CL_VERSION
456#endif
457#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
458 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
459#endif
460
461#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
462 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
463#endif
464#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
465 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
466#else
467 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
468#endif
469
470#if defined(JSON_HEDLEY_PGI_VERSION)
471 #undef JSON_HEDLEY_PGI_VERSION
472#endif
473#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
474 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
475#endif
476
477#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
478 #undef JSON_HEDLEY_PGI_VERSION_CHECK
479#endif
480#if defined(JSON_HEDLEY_PGI_VERSION)
481 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
482#else
483 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
484#endif
485
486#if defined(JSON_HEDLEY_SUNPRO_VERSION)
487 #undef JSON_HEDLEY_SUNPRO_VERSION
488#endif
489#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
490 #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)
491#elif defined(__SUNPRO_C)
492 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
493#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
494 #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)
495#elif defined(__SUNPRO_CC)
496 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
497#endif
498
499#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
500 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
501#endif
502#if defined(JSON_HEDLEY_SUNPRO_VERSION)
503 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
504#else
505 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
506#endif
507
508#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
509 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
510#endif
511#if defined(__EMSCRIPTEN__)
512 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
513#endif
514
515#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
516 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
517#endif
518#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
519 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
520#else
521 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
522#endif
523
524#if defined(JSON_HEDLEY_ARM_VERSION)
525 #undef JSON_HEDLEY_ARM_VERSION
526#endif
527#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
528 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
529#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
530 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
531#endif
532
533#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
534 #undef JSON_HEDLEY_ARM_VERSION_CHECK
535#endif
536#if defined(JSON_HEDLEY_ARM_VERSION)
537 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
538#else
539 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
540#endif
541
542#if defined(JSON_HEDLEY_IBM_VERSION)
543 #undef JSON_HEDLEY_IBM_VERSION
544#endif
545#if defined(__ibmxl__)
546 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
547#elif defined(__xlC__) && defined(__xlC_ver__)
548 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
549#elif defined(__xlC__)
550 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
551#endif
552
553#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
554 #undef JSON_HEDLEY_IBM_VERSION_CHECK
555#endif
556#if defined(JSON_HEDLEY_IBM_VERSION)
557 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
558#else
559 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
560#endif
561
562#if defined(JSON_HEDLEY_TI_VERSION)
563 #undef JSON_HEDLEY_TI_VERSION
564#endif
565#if \
566 defined(__TI_COMPILER_VERSION__) && \
567 ( \
568 defined(__TMS470__) || defined(__TI_ARM__) || \
569 defined(__MSP430__) || \
570 defined(__TMS320C2000__) \
571 )
572#if (__TI_COMPILER_VERSION__ >= 16000000)
573 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
574#endif
575#endif
576
577#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
578 #undef JSON_HEDLEY_TI_VERSION_CHECK
579#endif
580#if defined(JSON_HEDLEY_TI_VERSION)
581 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
582#else
583 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
584#endif
585
586#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
587 #undef JSON_HEDLEY_TI_CL2000_VERSION
588#endif
589#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
590 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
591#endif
592
593#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
594 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
595#endif
596#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
597 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
598#else
599 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
600#endif
601
602#if defined(JSON_HEDLEY_TI_CL430_VERSION)
603 #undef JSON_HEDLEY_TI_CL430_VERSION
604#endif
605#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
606 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
607#endif
608
609#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
610 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
611#endif
612#if defined(JSON_HEDLEY_TI_CL430_VERSION)
613 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
614#else
615 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
616#endif
617
618#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
619 #undef JSON_HEDLEY_TI_ARMCL_VERSION
620#endif
621#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
622 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
623#endif
624
625#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
626 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
627#endif
628#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
629 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
630#else
631 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
632#endif
633
634#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
635 #undef JSON_HEDLEY_TI_CL6X_VERSION
636#endif
637#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
638 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
639#endif
640
641#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
642 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
643#endif
644#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
645 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
646#else
647 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
648#endif
649
650#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
651 #undef JSON_HEDLEY_TI_CL7X_VERSION
652#endif
653#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
654 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
655#endif
656
657#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
658 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
659#endif
660#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
661 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
662#else
663 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
664#endif
665
666#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
667 #undef JSON_HEDLEY_TI_CLPRU_VERSION
668#endif
669#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
670 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
671#endif
672
673#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
674 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
675#endif
676#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
677 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
678#else
679 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
680#endif
681
682#if defined(JSON_HEDLEY_CRAY_VERSION)
683 #undef JSON_HEDLEY_CRAY_VERSION
684#endif
685#if defined(_CRAYC)
686 #if defined(_RELEASE_PATCHLEVEL)
687 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
688 #else
689 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
690 #endif
691#endif
692
693#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
694 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
695#endif
696#if defined(JSON_HEDLEY_CRAY_VERSION)
697 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
698#else
699 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
700#endif
701
702#if defined(JSON_HEDLEY_IAR_VERSION)
703 #undef JSON_HEDLEY_IAR_VERSION
704#endif
705#if defined(__IAR_SYSTEMS_ICC__)
706 #if __VER__ > 1000
707 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
708 #else
709 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
710 #endif
711#endif
712
713#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
714 #undef JSON_HEDLEY_IAR_VERSION_CHECK
715#endif
716#if defined(JSON_HEDLEY_IAR_VERSION)
717 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
718#else
719 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
720#endif
721
722#if defined(JSON_HEDLEY_TINYC_VERSION)
723 #undef JSON_HEDLEY_TINYC_VERSION
724#endif
725#if defined(__TINYC__)
726 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
727#endif
728
729#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
730 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
731#endif
732#if defined(JSON_HEDLEY_TINYC_VERSION)
733 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
734#else
735 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
736#endif
737
738#if defined(JSON_HEDLEY_DMC_VERSION)
739 #undef JSON_HEDLEY_DMC_VERSION
740#endif
741#if defined(__DMC__)
742 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
743#endif
744
745#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
746 #undef JSON_HEDLEY_DMC_VERSION_CHECK
747#endif
748#if defined(JSON_HEDLEY_DMC_VERSION)
749 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
750#else
751 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
752#endif
753
754#if defined(JSON_HEDLEY_COMPCERT_VERSION)
755 #undef JSON_HEDLEY_COMPCERT_VERSION
756#endif
757#if defined(__COMPCERT_VERSION__)
758 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
759#endif
760
761#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
762 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
763#endif
764#if defined(JSON_HEDLEY_COMPCERT_VERSION)
765 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
766#else
767 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
768#endif
769
770#if defined(JSON_HEDLEY_PELLES_VERSION)
771 #undef JSON_HEDLEY_PELLES_VERSION
772#endif
773#if defined(__POCC__)
774 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
775#endif
776
777#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
778 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
779#endif
780#if defined(JSON_HEDLEY_PELLES_VERSION)
781 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
782#else
783 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
784#endif
785
786#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
787 #undef JSON_HEDLEY_MCST_LCC_VERSION
788#endif
789#if defined(__LCC__) && defined(__LCC_MINOR__)
790 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
791#endif
792
793#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
794 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
795#endif
796#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
797 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
798#else
799 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
800#endif
801
802#if defined(JSON_HEDLEY_GCC_VERSION)
803 #undef JSON_HEDLEY_GCC_VERSION
804#endif
805#if \
806 defined(JSON_HEDLEY_GNUC_VERSION) && \
807 !defined(__clang__) && \
808 !defined(JSON_HEDLEY_INTEL_VERSION) && \
809 !defined(JSON_HEDLEY_PGI_VERSION) && \
810 !defined(JSON_HEDLEY_ARM_VERSION) && \
811 !defined(JSON_HEDLEY_CRAY_VERSION) && \
812 !defined(JSON_HEDLEY_TI_VERSION) && \
813 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
814 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
815 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
816 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
817 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
818 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
819 !defined(__COMPCERT__) && \
820 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
821 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
822#endif
823
824#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
825 #undef JSON_HEDLEY_GCC_VERSION_CHECK
826#endif
827#if defined(JSON_HEDLEY_GCC_VERSION)
828 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
829#else
830 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
831#endif
832
833#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
834 #undef JSON_HEDLEY_HAS_ATTRIBUTE
835#endif
836#if \
837 defined(__has_attribute) && \
838 ( \
839 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
840 )
841# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
842#else
843# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
844#endif
845
846#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
847 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
848#endif
849#if defined(__has_attribute)
850 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
851#else
852 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
853#endif
854
855#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
856 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
857#endif
858#if defined(__has_attribute)
859 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
860#else
861 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
862#endif
863
864#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
865 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
866#endif
867#if \
868 defined(__has_cpp_attribute) && \
869 defined(__cplusplus) && \
870 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
871 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
872#else
873 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
874#endif
875
876#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
877 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
878#endif
879#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
880 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
881#elif \
882 !defined(JSON_HEDLEY_PGI_VERSION) && \
883 !defined(JSON_HEDLEY_IAR_VERSION) && \
884 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
885 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
886 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
887#else
888 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
889#endif
890
891#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
892 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
893#endif
894#if defined(__has_cpp_attribute) && defined(__cplusplus)
895 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
896#else
897 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
898#endif
899
900#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
901 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
902#endif
903#if defined(__has_cpp_attribute) && defined(__cplusplus)
904 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
905#else
906 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
907#endif
908
909#if defined(JSON_HEDLEY_HAS_BUILTIN)
910 #undef JSON_HEDLEY_HAS_BUILTIN
911#endif
912#if defined(__has_builtin)
913 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
914#else
915 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
916#endif
917
918#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
919 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
920#endif
921#if defined(__has_builtin)
922 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
923#else
924 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
925#endif
926
927#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
928 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
929#endif
930#if defined(__has_builtin)
931 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
932#else
933 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
934#endif
935
936#if defined(JSON_HEDLEY_HAS_FEATURE)
937 #undef JSON_HEDLEY_HAS_FEATURE
938#endif
939#if defined(__has_feature)
940 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
941#else
942 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
943#endif
944
945#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
946 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
947#endif
948#if defined(__has_feature)
949 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
950#else
951 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
952#endif
953
954#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
955 #undef JSON_HEDLEY_GCC_HAS_FEATURE
956#endif
957#if defined(__has_feature)
958 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
959#else
960 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
961#endif
962
963#if defined(JSON_HEDLEY_HAS_EXTENSION)
964 #undef JSON_HEDLEY_HAS_EXTENSION
965#endif
966#if defined(__has_extension)
967 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
968#else
969 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
970#endif
971
972#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
973 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
974#endif
975#if defined(__has_extension)
976 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
977#else
978 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
979#endif
980
981#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
982 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
983#endif
984#if defined(__has_extension)
985 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
986#else
987 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
988#endif
989
990#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
991 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
992#endif
993#if defined(__has_declspec_attribute)
994 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
995#else
996 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
997#endif
998
999#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1000 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1001#endif
1002#if defined(__has_declspec_attribute)
1003 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1004#else
1005 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1006#endif
1007
1008#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1009 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1010#endif
1011#if defined(__has_declspec_attribute)
1012 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1013#else
1014 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1015#endif
1016
1017#if defined(JSON_HEDLEY_HAS_WARNING)
1018 #undef JSON_HEDLEY_HAS_WARNING
1019#endif
1020#if defined(__has_warning)
1021 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1022#else
1023 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1024#endif
1025
1026#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1027 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1028#endif
1029#if defined(__has_warning)
1030 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1031#else
1032 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1033#endif
1034
1035#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1036 #undef JSON_HEDLEY_GCC_HAS_WARNING
1037#endif
1038#if defined(__has_warning)
1039 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1040#else
1041 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1042#endif
1043
1044#if \
1045 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1046 defined(__clang__) || \
1047 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1048 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1049 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1050 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1051 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1052 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1053 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1054 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1055 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1056 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1057 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1058 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1059 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1060 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1061 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1062 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1063 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1064#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1065 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1066#else
1067 #define JSON_HEDLEY_PRAGMA(value)
1068#endif
1069
1070#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1071 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1072#endif
1073#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1074 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1075#endif
1076#if defined(__clang__)
1077 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1078 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1079#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1080 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1081 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1082#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1083 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1084 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1085#elif \
1086 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1087 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1088 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1089 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1090#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1091 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1092 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1093#elif \
1094 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1095 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1096 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1097 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1098 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1099 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1100 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1101 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1102#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1103 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1104 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1105#else
1106 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1107 #define JSON_HEDLEY_DIAGNOSTIC_POP
1108#endif
1109
1110/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1111 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1112#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1113 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1114#endif
1115#if defined(__cplusplus)
1116# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1117# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1118# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1119# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1120 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1121 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1122 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1123 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1124 xpr \
1125 JSON_HEDLEY_DIAGNOSTIC_POP
1126# else
1127# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1128 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1129 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1130 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1131 xpr \
1132 JSON_HEDLEY_DIAGNOSTIC_POP
1133# endif
1134# else
1135# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1136 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1137 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1138 xpr \
1139 JSON_HEDLEY_DIAGNOSTIC_POP
1140# endif
1141# endif
1142#endif
1143#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1144 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1145#endif
1146
1147#if defined(JSON_HEDLEY_CONST_CAST)
1148 #undef JSON_HEDLEY_CONST_CAST
1149#endif
1150#if defined(__cplusplus)
1151# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1152#elif \
1153 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1154 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1155 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1156# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1157 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1158 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1159 ((T) (expr)); \
1160 JSON_HEDLEY_DIAGNOSTIC_POP \
1161 }))
1162#else
1163# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1164#endif
1165
1166#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1167 #undef JSON_HEDLEY_REINTERPRET_CAST
1168#endif
1169#if defined(__cplusplus)
1170 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1171#else
1172 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1173#endif
1174
1175#if defined(JSON_HEDLEY_STATIC_CAST)
1176 #undef JSON_HEDLEY_STATIC_CAST
1177#endif
1178#if defined(__cplusplus)
1179 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1180#else
1181 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1182#endif
1183
1184#if defined(JSON_HEDLEY_CPP_CAST)
1185 #undef JSON_HEDLEY_CPP_CAST
1186#endif
1187#if defined(__cplusplus)
1188# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1189# define JSON_HEDLEY_CPP_CAST(T, expr) \
1190 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1191 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1192 ((T) (expr)) \
1193 JSON_HEDLEY_DIAGNOSTIC_POP
1194# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1195# define JSON_HEDLEY_CPP_CAST(T, expr) \
1196 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1197 _Pragma("diag_suppress=Pe137") \
1198 JSON_HEDLEY_DIAGNOSTIC_POP
1199# else
1200# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1201# endif
1202#else
1203# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1204#endif
1205
1206#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1207 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1208#endif
1209#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1210 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1211#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1212 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1213#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1214 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1215#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1216 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1217#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1218 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1219#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1220 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1221#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1222 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1223#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1224 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1225#elif \
1226 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1227 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1228 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1229 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1230 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1231 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1232 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1233 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1234 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1235 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1236 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1237 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1238#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1239 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1240#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1241 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1242#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1243 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1244#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1245 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1246#else
1247 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1248#endif
1249
1250#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1251 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1252#endif
1253#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1254 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1255#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1256 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1257#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1258 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1259#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1260 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1261#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1262 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1263#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1264 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1265#elif \
1266 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1267 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1268 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1269 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1270 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1271#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1272 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1273#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1274 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1275#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1276 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1277#else
1278 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1279#endif
1280
1281#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1282 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1283#endif
1284#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1285 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1286#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1287 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1288#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1289 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1290#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1291 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1292#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1293 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1294#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1295 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1296#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1297 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1298#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1299 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1300#elif \
1301 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1302 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1303 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1304 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1305#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1306 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1307#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1308 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1309#else
1310 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1311#endif
1312
1313#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1314 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1315#endif
1316#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1317 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1318#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1319 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1320#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1321 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1322#else
1323 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1324#endif
1325
1326#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1327 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1328#endif
1329#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1330 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1331#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1332 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1333#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1334 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1335#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1336 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1337#else
1338 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1339#endif
1340
1341#if defined(JSON_HEDLEY_DEPRECATED)
1342 #undef JSON_HEDLEY_DEPRECATED
1343#endif
1344#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1345 #undef JSON_HEDLEY_DEPRECATED_FOR
1346#endif
1347#if \
1348 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1349 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1350 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1351 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1352#elif \
1353 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1354 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1355 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1356 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1357 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1358 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1359 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1360 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1361 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1362 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1363 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1364 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1365 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1366 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1367#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1368 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1369 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1370#elif \
1371 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1372 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1373 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1374 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1375 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1376 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1377 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1378 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1379 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1380 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1381 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1382 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1383 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1384 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1385 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1386 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1387 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1388 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1389#elif \
1390 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1391 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1392 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1393 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1394 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1395#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1396 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1397 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1398#else
1399 #define JSON_HEDLEY_DEPRECATED(since)
1400 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1401#endif
1402
1403#if defined(JSON_HEDLEY_UNAVAILABLE)
1404 #undef JSON_HEDLEY_UNAVAILABLE
1405#endif
1406#if \
1407 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1408 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1409 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1410 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1411 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1412#else
1413 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1414#endif
1415
1416#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1417 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1418#endif
1419#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1420 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1421#endif
1422#if \
1423 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1424 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1425 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1426 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1427 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1428 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1429 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1430 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1431 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1432 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1433 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1434 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1435 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1436 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1437 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1438 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1439 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1440 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1441 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1442#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1443 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1444 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1445#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1446 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1447 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1448#elif defined(_Check_return_) /* SAL */
1449 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1450 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1451#else
1452 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1453 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1454#endif
1455
1456#if defined(JSON_HEDLEY_SENTINEL)
1457 #undef JSON_HEDLEY_SENTINEL
1458#endif
1459#if \
1460 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1461 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1462 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1463 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1464 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1465 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1466#else
1467 #define JSON_HEDLEY_SENTINEL(position)
1468#endif
1469
1470#if defined(JSON_HEDLEY_NO_RETURN)
1471 #undef JSON_HEDLEY_NO_RETURN
1472#endif
1473#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1474 #define JSON_HEDLEY_NO_RETURN __noreturn
1475#elif \
1476 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1477 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1478 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1479#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1480 #define JSON_HEDLEY_NO_RETURN _Noreturn
1481#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1482 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1483#elif \
1484 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1485 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1486 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1487 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1488 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1489 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1490 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1491 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1492 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1493 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1494 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1495 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1496 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1497 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1498 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1499 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1500 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1501 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1502#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1503 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1504#elif \
1505 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1506 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1507 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1508#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1509 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1510#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1511 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1512#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1513 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1514#else
1515 #define JSON_HEDLEY_NO_RETURN
1516#endif
1517
1518#if defined(JSON_HEDLEY_NO_ESCAPE)
1519 #undef JSON_HEDLEY_NO_ESCAPE
1520#endif
1521#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1522 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1523#else
1524 #define JSON_HEDLEY_NO_ESCAPE
1525#endif
1526
1527#if defined(JSON_HEDLEY_UNREACHABLE)
1528 #undef JSON_HEDLEY_UNREACHABLE
1529#endif
1530#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1531 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1532#endif
1533#if defined(JSON_HEDLEY_ASSUME)
1534 #undef JSON_HEDLEY_ASSUME
1535#endif
1536#if \
1537 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1538 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1539 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1540 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1541#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1542 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1543#elif \
1544 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1545 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1546 #if defined(__cplusplus)
1547 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1548 #else
1549 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1550 #endif
1551#endif
1552#if \
1553 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1554 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1555 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1556 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1557 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1558 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1559 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1560 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1561#elif defined(JSON_HEDLEY_ASSUME)
1562 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1563#endif
1564#if !defined(JSON_HEDLEY_ASSUME)
1565 #if defined(JSON_HEDLEY_UNREACHABLE)
1566 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1567 #else
1568 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1569 #endif
1570#endif
1571#if defined(JSON_HEDLEY_UNREACHABLE)
1572 #if \
1573 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1574 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1575 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1576 #else
1577 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1578 #endif
1579#else
1580 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1581#endif
1582#if !defined(JSON_HEDLEY_UNREACHABLE)
1583 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1584#endif
1585
1587#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1588 #pragma clang diagnostic ignored "-Wpedantic"
1589#endif
1590#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1591 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1592#endif
1593#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1594 #if defined(__clang__)
1595 #pragma clang diagnostic ignored "-Wvariadic-macros"
1596 #elif defined(JSON_HEDLEY_GCC_VERSION)
1597 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1598 #endif
1599#endif
1600#if defined(JSON_HEDLEY_NON_NULL)
1601 #undef JSON_HEDLEY_NON_NULL
1602#endif
1603#if \
1604 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1605 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1606 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1607 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1608 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1609#else
1610 #define JSON_HEDLEY_NON_NULL(...)
1611#endif
1613
1614#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1615 #undef JSON_HEDLEY_PRINTF_FORMAT
1616#endif
1617#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1618 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1619#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1620 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1621#elif \
1622 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1623 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1624 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1625 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1626 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1627 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1628 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1629 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1630 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1631 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1632 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1633 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1634 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1635 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1636 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1637 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1638 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1639 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1640#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1641 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1642#else
1643 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1644#endif
1645
1646#if defined(JSON_HEDLEY_CONSTEXPR)
1647 #undef JSON_HEDLEY_CONSTEXPR
1648#endif
1649#if defined(__cplusplus)
1650 #if __cplusplus >= 201103L
1651 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1652 #endif
1653#endif
1654#if !defined(JSON_HEDLEY_CONSTEXPR)
1655 #define JSON_HEDLEY_CONSTEXPR
1656#endif
1657
1658#if defined(JSON_HEDLEY_PREDICT)
1659 #undef JSON_HEDLEY_PREDICT
1660#endif
1661#if defined(JSON_HEDLEY_LIKELY)
1662 #undef JSON_HEDLEY_LIKELY
1663#endif
1664#if defined(JSON_HEDLEY_UNLIKELY)
1665 #undef JSON_HEDLEY_UNLIKELY
1666#endif
1667#if defined(JSON_HEDLEY_UNPREDICTABLE)
1668 #undef JSON_HEDLEY_UNPREDICTABLE
1669#endif
1670#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1671 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1672#endif
1673#if \
1674 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1675 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1676 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1677# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1678# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1679# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1680# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1681# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1682#elif \
1683 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1684 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1685 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1686 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1687 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1688 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1689 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1690 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1691 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1692 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1693 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1694 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1695 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1696 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1697 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1698 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1699# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1700 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1701# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1702 (__extension__ ({ \
1703 double hedley_probability_ = (probability); \
1704 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1705 }))
1706# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1707 (__extension__ ({ \
1708 double hedley_probability_ = (probability); \
1709 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1710 }))
1711# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1712# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1713#else
1714# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1715# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1716# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1717# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1718# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1719#endif
1720#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1721 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1722#endif
1723
1724#if defined(JSON_HEDLEY_MALLOC)
1725 #undef JSON_HEDLEY_MALLOC
1726#endif
1727#if \
1728 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1729 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1730 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1731 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1732 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1733 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1734 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1735 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1736 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1737 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1738 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1739 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1740 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1741 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1742 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1743 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1744 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1745 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1746 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1747#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1748 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1749#elif \
1750 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1751 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1752 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1753#else
1754 #define JSON_HEDLEY_MALLOC
1755#endif
1756
1757#if defined(JSON_HEDLEY_PURE)
1758 #undef JSON_HEDLEY_PURE
1759#endif
1760#if \
1761 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1762 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1763 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1764 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1765 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1766 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1767 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1768 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1769 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1770 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1771 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1772 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1773 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1774 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1775 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1776 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1777 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1778 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1779 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1780# define JSON_HEDLEY_PURE __attribute__((__pure__))
1781#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1782# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1783#elif defined(__cplusplus) && \
1784 ( \
1785 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1786 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1787 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1788 )
1789# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1790#else
1791# define JSON_HEDLEY_PURE
1792#endif
1793
1794#if defined(JSON_HEDLEY_CONST)
1795 #undef JSON_HEDLEY_CONST
1796#endif
1797#if \
1798 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1799 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1800 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1801 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1802 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1803 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1804 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1805 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1806 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1807 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1808 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1809 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1810 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1811 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1812 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1813 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1814 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1815 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1816 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1817 #define JSON_HEDLEY_CONST __attribute__((__const__))
1818#elif \
1819 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1820 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1821#else
1822 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1823#endif
1824
1825#if defined(JSON_HEDLEY_RESTRICT)
1826 #undef JSON_HEDLEY_RESTRICT
1827#endif
1828#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1829 #define JSON_HEDLEY_RESTRICT restrict
1830#elif \
1831 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1832 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1833 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1834 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1835 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1836 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1837 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1838 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1839 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1840 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1841 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1842 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1843 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1844 defined(__clang__) || \
1845 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1846 #define JSON_HEDLEY_RESTRICT __restrict
1847#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1848 #define JSON_HEDLEY_RESTRICT _Restrict
1849#else
1850 #define JSON_HEDLEY_RESTRICT
1851#endif
1852
1853#if defined(JSON_HEDLEY_INLINE)
1854 #undef JSON_HEDLEY_INLINE
1855#endif
1856#if \
1857 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1858 (defined(__cplusplus) && (__cplusplus >= 199711L))
1859 #define JSON_HEDLEY_INLINE inline
1860#elif \
1861 defined(JSON_HEDLEY_GCC_VERSION) || \
1862 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1863 #define JSON_HEDLEY_INLINE __inline__
1864#elif \
1865 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1866 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1867 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1868 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1869 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1870 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1871 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1872 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1873 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1874 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1875 #define JSON_HEDLEY_INLINE __inline
1876#else
1877 #define JSON_HEDLEY_INLINE
1878#endif
1879
1880#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1881 #undef JSON_HEDLEY_ALWAYS_INLINE
1882#endif
1883#if \
1884 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1885 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1886 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1887 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1888 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1889 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1890 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1891 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1892 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1893 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1894 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1895 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1896 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1897 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1898 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1899 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1900 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1901 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1902 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1903# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1904#elif \
1905 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1906 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1907# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1908#elif defined(__cplusplus) && \
1909 ( \
1910 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1911 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1912 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1913 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1914 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1915 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1916 )
1917# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1918#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1919# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1920#else
1921# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1922#endif
1923
1924#if defined(JSON_HEDLEY_NEVER_INLINE)
1925 #undef JSON_HEDLEY_NEVER_INLINE
1926#endif
1927#if \
1928 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1929 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1930 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1931 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1932 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1933 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1934 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1935 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1936 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1937 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1938 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1939 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1940 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1941 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1942 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1943 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1944 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1945 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1946 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1947 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1948#elif \
1949 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1950 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1951 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1952#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1953 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1954#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1955 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1956#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1957 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1958#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1959 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1960#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1961 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1962#else
1963 #define JSON_HEDLEY_NEVER_INLINE
1964#endif
1965
1966#if defined(JSON_HEDLEY_PRIVATE)
1967 #undef JSON_HEDLEY_PRIVATE
1968#endif
1969#if defined(JSON_HEDLEY_PUBLIC)
1970 #undef JSON_HEDLEY_PUBLIC
1971#endif
1972#if defined(JSON_HEDLEY_IMPORT)
1973 #undef JSON_HEDLEY_IMPORT
1974#endif
1975#if defined(_WIN32) || defined(__CYGWIN__)
1976# define JSON_HEDLEY_PRIVATE
1977# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1978# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1979#else
1980# if \
1981 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1982 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1983 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1984 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1985 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1986 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1987 ( \
1988 defined(__TI_EABI__) && \
1989 ( \
1990 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1991 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1992 ) \
1993 ) || \
1994 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1995# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1996# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1997# else
1998# define JSON_HEDLEY_PRIVATE
1999# define JSON_HEDLEY_PUBLIC
2000# endif
2001# define JSON_HEDLEY_IMPORT extern
2002#endif
2003
2004#if defined(JSON_HEDLEY_NO_THROW)
2005 #undef JSON_HEDLEY_NO_THROW
2006#endif
2007#if \
2008 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2009 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2010 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2011 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2012 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2013#elif \
2014 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2015 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2016 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2017 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2018#else
2019 #define JSON_HEDLEY_NO_THROW
2020#endif
2021
2022#if defined(JSON_HEDLEY_FALL_THROUGH)
2023 #undef JSON_HEDLEY_FALL_THROUGH
2024#endif
2025#if \
2026 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2027 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2028 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2029 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2030#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2031 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2032#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2033 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2034#elif defined(__fallthrough) /* SAL */
2035 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2036#else
2037 #define JSON_HEDLEY_FALL_THROUGH
2038#endif
2039
2040#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2041 #undef JSON_HEDLEY_RETURNS_NON_NULL
2042#endif
2043#if \
2044 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2045 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2046 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2047 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2048#elif defined(_Ret_notnull_) /* SAL */
2049 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2050#else
2051 #define JSON_HEDLEY_RETURNS_NON_NULL
2052#endif
2053
2054#if defined(JSON_HEDLEY_ARRAY_PARAM)
2055 #undef JSON_HEDLEY_ARRAY_PARAM
2056#endif
2057#if \
2058 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2059 !defined(__STDC_NO_VLA__) && \
2060 !defined(__cplusplus) && \
2061 !defined(JSON_HEDLEY_PGI_VERSION) && \
2062 !defined(JSON_HEDLEY_TINYC_VERSION)
2063 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2064#else
2065 #define JSON_HEDLEY_ARRAY_PARAM(name)
2066#endif
2067
2068#if defined(JSON_HEDLEY_IS_CONSTANT)
2069 #undef JSON_HEDLEY_IS_CONSTANT
2070#endif
2071#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2072 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2073#endif
2074/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2075 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2076#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2077 #undef JSON_HEDLEY_IS_CONSTEXPR_
2078#endif
2079#if \
2080 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2081 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2082 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2083 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2084 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2085 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2086 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2087 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2088 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2089 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2090 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2091#endif
2092#if !defined(__cplusplus)
2093# if \
2094 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2095 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2096 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2097 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2098 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2099 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2100 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2101#if defined(__INTPTR_TYPE__)
2102 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2103#else
2104 #include <stdint.h>
2105 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2106#endif
2107# elif \
2108 ( \
2109 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2110 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2111 !defined(JSON_HEDLEY_PGI_VERSION) && \
2112 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2113 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2114 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2115 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2116 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2117 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2118#if defined(__INTPTR_TYPE__)
2119 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2120#else
2121 #include <stdint.h>
2122 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2123#endif
2124# elif \
2125 defined(JSON_HEDLEY_GCC_VERSION) || \
2126 defined(JSON_HEDLEY_INTEL_VERSION) || \
2127 defined(JSON_HEDLEY_TINYC_VERSION) || \
2128 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2129 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2130 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2131 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2132 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2133 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2134 defined(__clang__)
2135# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2136 sizeof(void) != \
2137 sizeof(*( \
2138 1 ? \
2139 ((void*) ((expr) * 0L) ) : \
2140((struct { char v[sizeof(void) * 2]; } *) 1) \
2141 ) \
2142 ) \
2143 )
2144# endif
2145#endif
2146#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2147 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2148 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2149 #endif
2150 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2151#else
2152 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2153 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2154 #endif
2155 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2156#endif
2157
2158#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2159 #undef JSON_HEDLEY_BEGIN_C_DECLS
2160#endif
2161#if defined(JSON_HEDLEY_END_C_DECLS)
2162 #undef JSON_HEDLEY_END_C_DECLS
2163#endif
2164#if defined(JSON_HEDLEY_C_DECL)
2165 #undef JSON_HEDLEY_C_DECL
2166#endif
2167#if defined(__cplusplus)
2168 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2169 #define JSON_HEDLEY_END_C_DECLS }
2170 #define JSON_HEDLEY_C_DECL extern "C"
2171#else
2172 #define JSON_HEDLEY_BEGIN_C_DECLS
2173 #define JSON_HEDLEY_END_C_DECLS
2174 #define JSON_HEDLEY_C_DECL
2175#endif
2176
2177#if defined(JSON_HEDLEY_STATIC_ASSERT)
2178 #undef JSON_HEDLEY_STATIC_ASSERT
2179#endif
2180#if \
2181 !defined(__cplusplus) && ( \
2182 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2183 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2184 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2185 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2186 defined(_Static_assert) \
2187 )
2188# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2189#elif \
2190 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2191 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2192 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2193# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2194#else
2195# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2196#endif
2197
2198#if defined(JSON_HEDLEY_NULL)
2199 #undef JSON_HEDLEY_NULL
2200#endif
2201#if defined(__cplusplus)
2202 #if __cplusplus >= 201103L
2203 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2204 #elif defined(NULL)
2205 #define JSON_HEDLEY_NULL NULL
2206 #else
2207 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2208 #endif
2209#elif defined(NULL)
2210 #define JSON_HEDLEY_NULL NULL
2211#else
2212 #define JSON_HEDLEY_NULL ((void*) 0)
2213#endif
2214
2215#if defined(JSON_HEDLEY_MESSAGE)
2216 #undef JSON_HEDLEY_MESSAGE
2217#endif
2218#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2219# define JSON_HEDLEY_MESSAGE(msg) \
2220 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2221 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2222 JSON_HEDLEY_PRAGMA(message msg) \
2223 JSON_HEDLEY_DIAGNOSTIC_POP
2224#elif \
2225 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2226 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2227# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2228#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2229# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2230#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2231# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2232#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2233# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2234#else
2235# define JSON_HEDLEY_MESSAGE(msg)
2236#endif
2237
2238#if defined(JSON_HEDLEY_WARNING)
2239 #undef JSON_HEDLEY_WARNING
2240#endif
2241#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2242# define JSON_HEDLEY_WARNING(msg) \
2243 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2244 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2245 JSON_HEDLEY_PRAGMA(clang warning msg) \
2246 JSON_HEDLEY_DIAGNOSTIC_POP
2247#elif \
2248 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2249 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2250 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2251# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2252#elif \
2253 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2254 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2255# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2256#else
2257# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2258#endif
2259
2260#if defined(JSON_HEDLEY_REQUIRE)
2261 #undef JSON_HEDLEY_REQUIRE
2262#endif
2263#if defined(JSON_HEDLEY_REQUIRE_MSG)
2264 #undef JSON_HEDLEY_REQUIRE_MSG
2265#endif
2266#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2267# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2268# define JSON_HEDLEY_REQUIRE(expr) \
2269 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2270 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2271 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2272 JSON_HEDLEY_DIAGNOSTIC_POP
2273# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2274 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2275 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2276 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2277 JSON_HEDLEY_DIAGNOSTIC_POP
2278# else
2279# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2280# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2281# endif
2282#else
2283# define JSON_HEDLEY_REQUIRE(expr)
2284# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2285#endif
2286
2287#if defined(JSON_HEDLEY_FLAGS)
2288 #undef JSON_HEDLEY_FLAGS
2289#endif
2290#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2291 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2292#else
2293 #define JSON_HEDLEY_FLAGS
2294#endif
2295
2296#if defined(JSON_HEDLEY_FLAGS_CAST)
2297 #undef JSON_HEDLEY_FLAGS_CAST
2298#endif
2299#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2300# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2301 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2302 _Pragma("warning(disable:188)") \
2303 ((T) (expr)); \
2304 JSON_HEDLEY_DIAGNOSTIC_POP \
2305 }))
2306#else
2307# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2308#endif
2309
2310#if defined(JSON_HEDLEY_EMPTY_BASES)
2311 #undef JSON_HEDLEY_EMPTY_BASES
2312#endif
2313#if \
2314 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2315 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2316 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2317#else
2318 #define JSON_HEDLEY_EMPTY_BASES
2319#endif
2320
2321/* Remaining macros are deprecated. */
2322
2323#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2324 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2325#endif
2326#if defined(__clang__)
2327 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2328#else
2329 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2330#endif
2331
2332#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2333 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2334#endif
2335#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2336
2337#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2338 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2339#endif
2340#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2341
2342#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2343 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2344#endif
2345#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2346
2347#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2348 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2349#endif
2350#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2351
2352#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2353 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2354#endif
2355#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2356
2357#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2358 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2359#endif
2360#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2361
2362#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2363 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2364#endif
2365#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2366
2367#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2368
2369
2370// This file contains all internal macro definitions (except those affecting ABI)
2371// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2372
2373// #include <nlohmann/detail/abi_macros.hpp>
2374
2375
2376// exclude unsupported compilers
2377#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2378 #if defined(__clang__)
2379 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2380 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2381 #endif
2382 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2383 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2384 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2385 #endif
2386 #endif
2387#endif
2388
2389// C++ language standard detection
2390// if the user manually specified the used c++ version this is skipped
2391#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2392 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2393 #define JSON_HAS_CPP_20
2394 #define JSON_HAS_CPP_17
2395 #define JSON_HAS_CPP_14
2396 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2397 #define JSON_HAS_CPP_17
2398 #define JSON_HAS_CPP_14
2399 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2400 #define JSON_HAS_CPP_14
2401 #endif
2402 // the cpp 11 flag is always specified because it is the minimal required version
2403 #define JSON_HAS_CPP_11
2404#endif
2405
2406#ifdef __has_include
2407 #if __has_include(<version>)
2408 #include <version>
2409 #endif
2410#endif
2411
2412#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2413 #ifdef JSON_HAS_CPP_17
2414 #if defined(__cpp_lib_filesystem)
2415 #define JSON_HAS_FILESYSTEM 1
2416 #elif defined(__cpp_lib_experimental_filesystem)
2417 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2418 #elif !defined(__has_include)
2419 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2420 #elif __has_include(<filesystem>)
2421 #define JSON_HAS_FILESYSTEM 1
2422 #elif __has_include(<experimental/filesystem>)
2423 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2424 #endif
2425
2426 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2427 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2428 #undef JSON_HAS_FILESYSTEM
2429 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2430 #endif
2431
2432 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2433 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2434 #undef JSON_HAS_FILESYSTEM
2435 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2436 #endif
2437
2438 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2439 #if defined(__clang_major__) && __clang_major__ < 7
2440 #undef JSON_HAS_FILESYSTEM
2441 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2442 #endif
2443
2444 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2445 #if defined(_MSC_VER) && _MSC_VER < 1914
2446 #undef JSON_HAS_FILESYSTEM
2447 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2448 #endif
2449
2450 // no filesystem support before iOS 13
2451 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2452 #undef JSON_HAS_FILESYSTEM
2453 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2454 #endif
2455
2456 // no filesystem support before macOS Catalina
2457 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2458 #undef JSON_HAS_FILESYSTEM
2459 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2460 #endif
2461 #endif
2462#endif
2463
2464#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2465 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2466#endif
2467
2468#ifndef JSON_HAS_FILESYSTEM
2469 #define JSON_HAS_FILESYSTEM 0
2470#endif
2471
2472#ifndef JSON_HAS_THREE_WAY_COMPARISON
2473 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2474 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2475 #define JSON_HAS_THREE_WAY_COMPARISON 1
2476 #else
2477 #define JSON_HAS_THREE_WAY_COMPARISON 0
2478 #endif
2479#endif
2480
2481#ifndef JSON_HAS_RANGES
2482 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2483 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2484 #define JSON_HAS_RANGES 0
2485 #elif defined(__cpp_lib_ranges)
2486 #define JSON_HAS_RANGES 1
2487 #else
2488 #define JSON_HAS_RANGES 0
2489 #endif
2490#endif
2491
2492#ifndef JSON_HAS_STATIC_RTTI
2493 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2494 #define JSON_HAS_STATIC_RTTI 1
2495 #else
2496 #define JSON_HAS_STATIC_RTTI 0
2497 #endif
2498#endif
2499
2500#ifdef JSON_HAS_CPP_17
2501 #define JSON_INLINE_VARIABLE inline
2502#else
2503 #define JSON_INLINE_VARIABLE
2504#endif
2505
2506#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2507 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2508#else
2509 #define JSON_NO_UNIQUE_ADDRESS
2510#endif
2511
2512// disable documentation warnings on clang
2513#if defined(__clang__)
2514 #pragma clang diagnostic push
2515 #pragma clang diagnostic ignored "-Wdocumentation"
2516 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2517#endif
2518
2519// allow disabling exceptions
2520#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2521 #define JSON_THROW(exception) throw exception
2522 #define JSON_TRY try
2523 #define JSON_CATCH(exception) catch(exception)
2524 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2525#else
2526 #include <cstdlib>
2527 #define JSON_THROW(exception) std::abort()
2528 #define JSON_TRY if(true)
2529 #define JSON_CATCH(exception) if(false)
2530 #define JSON_INTERNAL_CATCH(exception) if(false)
2531#endif
2532
2533// override exception macros
2534#if defined(JSON_THROW_USER)
2535 #undef JSON_THROW
2536 #define JSON_THROW JSON_THROW_USER
2537#endif
2538#if defined(JSON_TRY_USER)
2539 #undef JSON_TRY
2540 #define JSON_TRY JSON_TRY_USER
2541#endif
2542#if defined(JSON_CATCH_USER)
2543 #undef JSON_CATCH
2544 #define JSON_CATCH JSON_CATCH_USER
2545 #undef JSON_INTERNAL_CATCH
2546 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2547#endif
2548#if defined(JSON_INTERNAL_CATCH_USER)
2549 #undef JSON_INTERNAL_CATCH
2550 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2551#endif
2552
2553// allow overriding assert
2554#if !defined(JSON_ASSERT)
2555 #include <cassert> // assert
2556 #define JSON_ASSERT(x) assert(x)
2557#endif
2558
2559// allow to access some private functions (needed by the test suite)
2560#if defined(JSON_TESTS_PRIVATE)
2561 #define JSON_PRIVATE_UNLESS_TESTED public
2562#else
2563 #define JSON_PRIVATE_UNLESS_TESTED private
2564#endif
2565
2571#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2572 template<typename BasicJsonType> \
2573 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2574 { \
2575 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2576 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2577 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2578 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2579 auto it = std::find_if(std::begin(m), std::end(m), \
2580 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2581 { \
2582 return ej_pair.first == e; \
2583 }); \
2584 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2585 } \
2586 template<typename BasicJsonType> \
2587 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2588 { \
2589 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2590 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2591 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2592 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2593 auto it = std::find_if(std::begin(m), std::end(m), \
2594 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2595 { \
2596 return ej_pair.second == j; \
2597 }); \
2598 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2599 }
2600
2601// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2602// may be removed in the future once the class is split.
2603
2604#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2605 template<template<typename, typename, typename...> class ObjectType, \
2606 template<typename, typename...> class ArrayType, \
2607 class StringType, class BooleanType, class NumberIntegerType, \
2608 class NumberUnsignedType, class NumberFloatType, \
2609 template<typename> class AllocatorType, \
2610 template<typename, typename = void> class JSONSerializer, \
2611 class BinaryType, \
2612 class CustomBaseClass>
2613
2614#define NLOHMANN_BASIC_JSON_TPL \
2615 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2616 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2617 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2618
2619// Macros to simplify conversion from/to types
2620
2621#define NLOHMANN_JSON_EXPAND( x ) x
2622#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
2623#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2624 NLOHMANN_JSON_PASTE64, \
2625 NLOHMANN_JSON_PASTE63, \
2626 NLOHMANN_JSON_PASTE62, \
2627 NLOHMANN_JSON_PASTE61, \
2628 NLOHMANN_JSON_PASTE60, \
2629 NLOHMANN_JSON_PASTE59, \
2630 NLOHMANN_JSON_PASTE58, \
2631 NLOHMANN_JSON_PASTE57, \
2632 NLOHMANN_JSON_PASTE56, \
2633 NLOHMANN_JSON_PASTE55, \
2634 NLOHMANN_JSON_PASTE54, \
2635 NLOHMANN_JSON_PASTE53, \
2636 NLOHMANN_JSON_PASTE52, \
2637 NLOHMANN_JSON_PASTE51, \
2638 NLOHMANN_JSON_PASTE50, \
2639 NLOHMANN_JSON_PASTE49, \
2640 NLOHMANN_JSON_PASTE48, \
2641 NLOHMANN_JSON_PASTE47, \
2642 NLOHMANN_JSON_PASTE46, \
2643 NLOHMANN_JSON_PASTE45, \
2644 NLOHMANN_JSON_PASTE44, \
2645 NLOHMANN_JSON_PASTE43, \
2646 NLOHMANN_JSON_PASTE42, \
2647 NLOHMANN_JSON_PASTE41, \
2648 NLOHMANN_JSON_PASTE40, \
2649 NLOHMANN_JSON_PASTE39, \
2650 NLOHMANN_JSON_PASTE38, \
2651 NLOHMANN_JSON_PASTE37, \
2652 NLOHMANN_JSON_PASTE36, \
2653 NLOHMANN_JSON_PASTE35, \
2654 NLOHMANN_JSON_PASTE34, \
2655 NLOHMANN_JSON_PASTE33, \
2656 NLOHMANN_JSON_PASTE32, \
2657 NLOHMANN_JSON_PASTE31, \
2658 NLOHMANN_JSON_PASTE30, \
2659 NLOHMANN_JSON_PASTE29, \
2660 NLOHMANN_JSON_PASTE28, \
2661 NLOHMANN_JSON_PASTE27, \
2662 NLOHMANN_JSON_PASTE26, \
2663 NLOHMANN_JSON_PASTE25, \
2664 NLOHMANN_JSON_PASTE24, \
2665 NLOHMANN_JSON_PASTE23, \
2666 NLOHMANN_JSON_PASTE22, \
2667 NLOHMANN_JSON_PASTE21, \
2668 NLOHMANN_JSON_PASTE20, \
2669 NLOHMANN_JSON_PASTE19, \
2670 NLOHMANN_JSON_PASTE18, \
2671 NLOHMANN_JSON_PASTE17, \
2672 NLOHMANN_JSON_PASTE16, \
2673 NLOHMANN_JSON_PASTE15, \
2674 NLOHMANN_JSON_PASTE14, \
2675 NLOHMANN_JSON_PASTE13, \
2676 NLOHMANN_JSON_PASTE12, \
2677 NLOHMANN_JSON_PASTE11, \
2678 NLOHMANN_JSON_PASTE10, \
2679 NLOHMANN_JSON_PASTE9, \
2680 NLOHMANN_JSON_PASTE8, \
2681 NLOHMANN_JSON_PASTE7, \
2682 NLOHMANN_JSON_PASTE6, \
2683 NLOHMANN_JSON_PASTE5, \
2684 NLOHMANN_JSON_PASTE4, \
2685 NLOHMANN_JSON_PASTE3, \
2686 NLOHMANN_JSON_PASTE2, \
2687 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2688#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2689#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2690#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2691#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2692#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2693#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)
2694#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)
2695#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)
2696#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)
2697#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)
2698#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)
2699#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)
2700#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)
2701#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)
2702#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)
2703#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)
2704#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)
2705#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)
2706#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)
2707#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)
2708#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)
2709#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)
2710#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)
2711#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)
2712#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)
2713#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)
2714#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)
2715#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)
2716#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)
2717#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)
2718#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)
2719#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)
2720#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)
2721#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)
2722#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)
2723#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)
2724#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)
2725#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)
2726#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)
2727#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)
2728#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)
2729#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)
2730#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)
2731#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)
2732#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)
2733#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)
2734#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)
2735#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)
2736#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)
2737#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)
2738#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)
2739#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)
2740#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)
2741#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)
2742#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)
2743#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)
2744#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)
2745#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)
2746#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)
2747#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)
2748#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)
2749#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)
2750#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)
2751
2752#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2753#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2754#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2755
2761#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2762 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2763 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2764
2765#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2766 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2767 friend void from_json(const nlohmann::json& 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__)) }
2768
2769#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2770 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2771
2777#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2778 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2779 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2780
2781#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2782 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2783
2784#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2785 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2786 inline void from_json(const nlohmann::json& 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__)) }
2787
2793#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \
2794 friend void to_json(nlohmann::json& 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__)) } \
2795 friend void from_json(const nlohmann::json& 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__)) }
2796
2797#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2798 friend void to_json(nlohmann::json& 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__)) } \
2799 friend void from_json(const nlohmann::json& 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__)) }
2800
2806#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \
2807 inline void to_json(nlohmann::json& 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__)) } \
2808 inline void from_json(const nlohmann::json& 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__)) }
2809
2810#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2811 inline void to_json(nlohmann::json& 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__)) } \
2812 inline void from_json(const nlohmann::json& 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__)) }
2813
2814// inspired from https://stackoverflow.com/a/26745591
2815// allows to call any std function as if (e.g. with begin):
2816// using std::begin; begin(x);
2817//
2818// it allows using the detected idiom to retrieve the return type
2819// of such an expression
2820#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2821 namespace detail { \
2822 using std::std_name; \
2823 \
2824 template<typename... T> \
2825 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2826 } \
2827 \
2828 namespace detail2 { \
2829 struct std_name##_tag \
2830 { \
2831 }; \
2832 \
2833 template<typename... T> \
2834 std_name##_tag std_name(T&&...); \
2835 \
2836 template<typename... T> \
2837 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2838 \
2839 template<typename... T> \
2840 struct would_call_std_##std_name \
2841 { \
2842 static constexpr auto const value = ::nlohmann::detail:: \
2843 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2844 }; \
2845 } /* namespace detail2 */ \
2846 \
2847 template<typename... T> \
2848 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2849 { \
2850 }
2851
2852#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2853 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2854#endif
2855
2856#if JSON_USE_IMPLICIT_CONVERSIONS
2857 #define JSON_EXPLICIT
2858#else
2859 #define JSON_EXPLICIT explicit
2860#endif
2861
2862#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2863 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2864#endif
2865
2866#ifndef JSON_USE_GLOBAL_UDLS
2867 #define JSON_USE_GLOBAL_UDLS 1
2868#endif
2869
2870#if JSON_HAS_THREE_WAY_COMPARISON
2871 #include <compare> // partial_ordering
2872#endif
2873
2875namespace detail
2876{
2877
2879// JSON type enumeration //
2881
2906enum class value_t : std::uint8_t
2907{
2908 null,
2909 object,
2910 array,
2911 string,
2912 boolean,
2915 number_float,
2916 binary,
2917 discarded
2918};
2919
2933#if JSON_HAS_THREE_WAY_COMPARISON
2934 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
2935#else
2936 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2937#endif
2938{
2939 static constexpr std::array<std::uint8_t, 9> order = {{
2940 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
2941 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
2942 6 /* binary */
2943 }
2944 };
2945
2946 const auto l_index = static_cast<std::size_t>(lhs);
2947 const auto r_index = static_cast<std::size_t>(rhs);
2948#if JSON_HAS_THREE_WAY_COMPARISON
2949 if (l_index < order.size() && r_index < order.size())
2950 {
2951 return order[l_index] <=> order[r_index]; // *NOPAD*
2952 }
2953 return std::partial_ordering::unordered;
2954#else
2955 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
2956#endif
2957}
2958
2959// GCC selects the built-in operator< over an operator rewritten from
2960// a user-defined spaceship operator
2961// Clang, MSVC, and ICC select the rewritten candidate
2962// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
2963#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
2964inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2965{
2966 return std::is_lt(lhs <=> rhs); // *NOPAD*
2967}
2968#endif
2969
2970} // namespace detail
2972
2973// #include <nlohmann/detail/string_escape.hpp>
2974// __ _____ _____ _____
2975// __| | __| | | | JSON for Modern C++
2976// | | |__ | | | | | | version 3.11.3
2977// |_____|_____|_____|_|___| https://github.com/nlohmann/json
2978//
2979// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
2980// SPDX-License-Identifier: MIT
2981
2982
2983
2984// #include <nlohmann/detail/abi_macros.hpp>
2985
2986
2988namespace detail
2989{
2990
3004template<typename StringType>
3005inline void replace_substring(StringType& s, const StringType& f,
3006 const StringType& t)
3007{
3008 JSON_ASSERT(!f.empty());
3009 for (auto pos = s.find(f); // find first occurrence of f
3010 pos != StringType::npos; // make sure f was found
3011 s.replace(pos, f.size(), t), // replace with t, and
3012 pos = s.find(f, pos + t.size())) // find next occurrence of f
3013 {}
3014}
3015
3023template<typename StringType>
3024inline StringType escape(StringType s)
3025{
3026 replace_substring(s, StringType{"~"}, StringType{"~0"});
3027 replace_substring(s, StringType{"/"}, StringType{"~1"});
3028 return s;
3029}
3030
3038template<typename StringType>
3039static void unescape(StringType& s)
3040{
3041 replace_substring(s, StringType{"~1"}, StringType{"/"});
3042 replace_substring(s, StringType{"~0"}, StringType{"~"});
3043}
3044
3045} // namespace detail
3047
3048// #include <nlohmann/detail/input/position_t.hpp>
3049// __ _____ _____ _____
3050// __| | __| | | | JSON for Modern C++
3051// | | |__ | | | | | | version 3.11.3
3052// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3053//
3054// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3055// SPDX-License-Identifier: MIT
3056
3057
3058
3059#include <cstddef> // size_t
3060
3061// #include <nlohmann/detail/abi_macros.hpp>
3062
3063
3065namespace detail
3066{
3067
3070{
3072 std::size_t chars_read_total = 0;
3076 std::size_t lines_read = 0;
3077
3079 constexpr operator size_t() const
3080 {
3081 return chars_read_total;
3082 }
3083};
3084
3085} // namespace detail
3087
3088// #include <nlohmann/detail/macro_scope.hpp>
3089
3090// #include <nlohmann/detail/meta/cpp_future.hpp>
3091// __ _____ _____ _____
3092// __| | __| | | | JSON for Modern C++
3093// | | |__ | | | | | | version 3.11.3
3094// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3095//
3096// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3097// SPDX-FileCopyrightText: 2018 The Abseil Authors
3098// SPDX-License-Identifier: MIT
3099
3100
3101
3102#include <array> // array
3103#include <cstddef> // size_t
3104#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3105#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3106
3107// #include <nlohmann/detail/macro_scope.hpp>
3108
3109
3111namespace detail
3112{
3113
3114template<typename T>
3115using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3116
3117#ifdef JSON_HAS_CPP_14
3118
3119// the following utilities are natively available in C++14
3120using std::enable_if_t;
3121using std::index_sequence;
3122using std::make_index_sequence;
3123using std::index_sequence_for;
3124
3125#else
3126
3127// alias templates to reduce boilerplate
3128template<bool B, typename T = void>
3129using enable_if_t = typename std::enable_if<B, T>::type;
3130
3131// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3132// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3133
3135
3136// integer_sequence
3137//
3138// Class template representing a compile-time integer sequence. An instantiation
3139// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3140// type through its template arguments (which is a common need when
3141// working with C++11 variadic templates). `absl::integer_sequence` is designed
3142// to be a drop-in replacement for C++14's `std::integer_sequence`.
3143//
3144// Example:
3145//
3146// template< class T, T... Ints >
3147// void user_function(integer_sequence<T, Ints...>);
3148//
3149// int main()
3150// {
3151// // user_function's `T` will be deduced to `int` and `Ints...`
3152// // will be deduced to `0, 1, 2, 3, 4`.
3153// user_function(make_integer_sequence<int, 5>());
3154// }
3155template <typename T, T... Ints>
3157{
3158 using value_type = T;
3159 static constexpr std::size_t size() noexcept
3160 {
3161 return sizeof...(Ints);
3162 }
3163};
3164
3165// index_sequence
3166//
3167// A helper template for an `integer_sequence` of `size_t`,
3168// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3169// `std::index_sequence`.
3170template <size_t... Ints>
3171using index_sequence = integer_sequence<size_t, Ints...>;
3172
3173namespace utility_internal
3174{
3175
3176template <typename Seq, size_t SeqSize, size_t Rem>
3177struct Extend;
3178
3179// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3180template <typename T, T... Ints, size_t SeqSize>
3181struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3182{
3183 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3184};
3185
3186template <typename T, T... Ints, size_t SeqSize>
3187struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3188{
3189 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3190};
3191
3192// Recursion helper for 'make_integer_sequence<T, N>'.
3193// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3194template <typename T, size_t N>
3195struct Gen
3196{
3197 using type =
3198 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3199};
3200
3201template <typename T>
3202struct Gen<T, 0>
3203{
3205};
3206
3207} // namespace utility_internal
3208
3209// Compile-time sequences of integers
3210
3211// make_integer_sequence
3212//
3213// This template alias is equivalent to
3214// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3215// replacement for C++14's `std::make_integer_sequence`.
3216template <typename T, T N>
3218
3219// make_index_sequence
3220//
3221// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3222// and is designed to be a drop-in replacement for C++14's
3223// `std::make_index_sequence`.
3224template <size_t N>
3226
3227// index_sequence_for
3228//
3229// Converts a typename pack into an index sequence of the same length, and
3230// is designed to be a drop-in replacement for C++14's
3231// `std::index_sequence_for()`
3232template <typename... Ts>
3234
3236
3237#endif
3238
3239// dispatch utility (taken from ranges-v3)
3240template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3241template<> struct priority_tag<0> {};
3242
3243// taken from ranges-v3
3244template<typename T>
3246{
3247 static JSON_INLINE_VARIABLE constexpr T value{};
3248};
3249
3250#ifndef JSON_HAS_CPP_17
3251 template<typename T>
3252 constexpr T static_const<T>::value;
3253#endif
3254
3255template<typename T, typename... Args>
3256constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3257{
3258 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3259}
3260
3261} // namespace detail
3263
3264// #include <nlohmann/detail/meta/type_traits.hpp>
3265// __ _____ _____ _____
3266// __| | __| | | | JSON for Modern C++
3267// | | |__ | | | | | | version 3.11.3
3268// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3269//
3270// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3271// SPDX-License-Identifier: MIT
3272
3273
3274
3275#include <limits> // numeric_limits
3276#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3277#include <utility> // declval
3278#include <tuple> // tuple
3279#include <string> // char_traits
3280
3281// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3282// __ _____ _____ _____
3283// __| | __| | | | JSON for Modern C++
3284// | | |__ | | | | | | version 3.11.3
3285// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3286//
3287// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3288// SPDX-License-Identifier: MIT
3289
3290
3291
3292#include <iterator> // random_access_iterator_tag
3293
3294// #include <nlohmann/detail/abi_macros.hpp>
3295
3296// #include <nlohmann/detail/meta/void_t.hpp>
3297
3298// #include <nlohmann/detail/meta/cpp_future.hpp>
3299
3300
3302namespace detail
3303{
3304
3305template<typename It, typename = void>
3307
3308template<typename It>
3310 It,
3311 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3312 typename It::reference, typename It::iterator_category >>
3313{
3314 using difference_type = typename It::difference_type;
3315 using value_type = typename It::value_type;
3316 using pointer = typename It::pointer;
3317 using reference = typename It::reference;
3318 using iterator_category = typename It::iterator_category;
3319};
3320
3321// This is required as some compilers implement std::iterator_traits in a way that
3322// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3323template<typename T, typename = void>
3325{
3326};
3327
3328template<typename T>
3329struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3330 : iterator_types<T>
3331{
3332};
3333
3334template<typename T>
3336{
3337 using iterator_category = std::random_access_iterator_tag;
3338 using value_type = T;
3339 using difference_type = ptrdiff_t;
3340 using pointer = T*;
3341 using reference = T&;
3342};
3343
3344} // namespace detail
3346
3347// #include <nlohmann/detail/macro_scope.hpp>
3348
3349// #include <nlohmann/detail/meta/call_std/begin.hpp>
3350// __ _____ _____ _____
3351// __| | __| | | | JSON for Modern C++
3352// | | |__ | | | | | | version 3.11.3
3353// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3354//
3355// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3356// SPDX-License-Identifier: MIT
3357
3358
3359
3360// #include <nlohmann/detail/macro_scope.hpp>
3361
3362
3364
3366
3368
3369// #include <nlohmann/detail/meta/call_std/end.hpp>
3370// __ _____ _____ _____
3371// __| | __| | | | JSON for Modern C++
3372// | | |__ | | | | | | version 3.11.3
3373// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3374//
3375// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3376// SPDX-License-Identifier: MIT
3377
3378
3379
3380// #include <nlohmann/detail/macro_scope.hpp>
3381
3382
3384
3386
3388
3389// #include <nlohmann/detail/meta/cpp_future.hpp>
3390
3391// #include <nlohmann/detail/meta/detected.hpp>
3392
3393// #include <nlohmann/json_fwd.hpp>
3394// __ _____ _____ _____
3395// __| | __| | | | JSON for Modern C++
3396// | | |__ | | | | | | version 3.11.3
3397// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3398//
3399// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3400// SPDX-License-Identifier: MIT
3401
3402#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3403 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3404
3405 #include <cstdint> // int64_t, uint64_t
3406 #include <map> // map
3407 #include <memory> // allocator
3408 #include <string> // string
3409 #include <vector> // vector
3410
3411 // #include <nlohmann/detail/abi_macros.hpp>
3412
3413
3420
3428 template<typename T = void, typename SFINAE = void>
3429 struct adl_serializer;
3430
3433 template<template<typename U, typename V, typename... Args> class ObjectType =
3434 std::map,
3435 template<typename U, typename... Args> class ArrayType = std::vector,
3436 class StringType = std::string, class BooleanType = bool,
3437 class NumberIntegerType = std::int64_t,
3438 class NumberUnsignedType = std::uint64_t,
3439 class NumberFloatType = double,
3440 template<typename U> class AllocatorType = std::allocator,
3441 template<typename T, typename SFINAE = void> class JSONSerializer =
3443 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3444 class CustomBaseClass = void>
3445 class basic_json;
3446
3449 template<typename RefStringType>
3450 class json_pointer;
3451
3457
3460 template<class Key, class T, class IgnoredLess, class Allocator>
3461 struct ordered_map;
3462
3466
3468
3469#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3470
3471
3481namespace detail
3482{
3483
3485// helpers //
3487
3488// Note to maintainers:
3489//
3490// Every trait in this file expects a non CV-qualified type.
3491// The only exceptions are in the 'aliases for detected' section
3492// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3493//
3494// In this case, T has to be properly CV-qualified to constraint the function arguments
3495// (e.g. to_json(BasicJsonType&, const T&))
3496
3497template<typename> struct is_basic_json : std::false_type {};
3498
3500struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3501
3502// used by exceptions create() member functions
3503// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3504// false_type otherwise
3505template<typename BasicJsonContext>
3507 std::integral_constant < bool,
3508 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3509 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3510{};
3511
3513// json_ref helpers //
3515
3516template<typename>
3517class json_ref;
3518
3519template<typename>
3520struct is_json_ref : std::false_type {};
3521
3522template<typename T>
3523struct is_json_ref<json_ref<T>> : std::true_type {};
3524
3526// aliases for detected //
3528
3529template<typename T>
3530using mapped_type_t = typename T::mapped_type;
3531
3532template<typename T>
3533using key_type_t = typename T::key_type;
3534
3535template<typename T>
3536using value_type_t = typename T::value_type;
3537
3538template<typename T>
3539using difference_type_t = typename T::difference_type;
3540
3541template<typename T>
3542using pointer_t = typename T::pointer;
3543
3544template<typename T>
3545using reference_t = typename T::reference;
3546
3547template<typename T>
3548using iterator_category_t = typename T::iterator_category;
3549
3550template<typename T, typename... Args>
3551using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3552
3553template<typename T, typename... Args>
3554using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3555
3556template<typename T, typename U>
3557using get_template_function = decltype(std::declval<T>().template get<U>());
3558
3559// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3560template<typename BasicJsonType, typename T, typename = void>
3561struct has_from_json : std::false_type {};
3562
3563// trait checking if j.get<T> is valid
3564// use this trait instead of std::is_constructible or std::is_convertible,
3565// both rely on, or make use of implicit conversions, and thus fail when T
3566// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3567template <typename BasicJsonType, typename T>
3569{
3571};
3572
3573template<typename BasicJsonType, typename T>
3574struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3575{
3576 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3577
3578 static constexpr bool value =
3580 const BasicJsonType&, T&>::value;
3581};
3582
3583// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3584// this overload is used for non-default-constructible user-defined-types
3585template<typename BasicJsonType, typename T, typename = void>
3586struct has_non_default_from_json : std::false_type {};
3587
3588template<typename BasicJsonType, typename T>
3589struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3590{
3591 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3592
3593 static constexpr bool value =
3595 const BasicJsonType&>::value;
3596};
3597
3598// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3599// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3600template<typename BasicJsonType, typename T, typename = void>
3601struct has_to_json : std::false_type {};
3602
3603template<typename BasicJsonType, typename T>
3604struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3605{
3606 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3607
3608 static constexpr bool value =
3609 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3610 T>::value;
3611};
3612
3613template<typename T>
3614using detect_key_compare = typename T::key_compare;
3615
3616template<typename T>
3617struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3618
3619// obtains the actual object key comparator
3620template<typename BasicJsonType>
3622{
3623 using object_t = typename BasicJsonType::object_t;
3624 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3625 using type = typename std::conditional < has_key_compare<object_t>::value,
3626 typename object_t::key_compare, object_comparator_t>::type;
3627};
3628
3629template<typename BasicJsonType>
3631
3633// char_traits //
3635
3636// Primary template of char_traits calls std char_traits
3637template<typename T>
3638struct char_traits : std::char_traits<T>
3639{};
3640
3641// Explicitly define char traits for unsigned char since it is not standard
3642template<>
3643struct char_traits<unsigned char> : std::char_traits<char>
3644{
3645 using char_type = unsigned char;
3647
3648 // Redefine to_int_type function
3649 static int_type to_int_type(char_type c) noexcept
3650 {
3651 return static_cast<int_type>(c);
3652 }
3653
3655 {
3656 return static_cast<char_type>(i);
3657 }
3658
3659 static constexpr int_type eof() noexcept
3660 {
3661 return static_cast<int_type>(EOF);
3662 }
3663};
3664
3665// Explicitly define char traits for signed char since it is not standard
3666template<>
3667struct char_traits<signed char> : std::char_traits<char>
3668{
3669 using char_type = signed char;
3671
3672 // Redefine to_int_type function
3673 static int_type to_int_type(char_type c) noexcept
3674 {
3675 return static_cast<int_type>(c);
3676 }
3677
3679 {
3680 return static_cast<char_type>(i);
3681 }
3682
3683 static constexpr int_type eof() noexcept
3684 {
3685 return static_cast<int_type>(EOF);
3686 }
3687};
3688
3690// is_ functions //
3692
3693// https://en.cppreference.com/w/cpp/types/conjunction
3694template<class...> struct conjunction : std::true_type { };
3695template<class B> struct conjunction<B> : B { };
3696template<class B, class... Bn>
3697struct conjunction<B, Bn...>
3698: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3699
3700// https://en.cppreference.com/w/cpp/types/negation
3701template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3702
3703// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3704// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3705// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3706template <typename T>
3707struct is_default_constructible : std::is_default_constructible<T> {};
3708
3709template <typename T1, typename T2>
3710struct is_default_constructible<std::pair<T1, T2>>
3711 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3712
3713template <typename T1, typename T2>
3714struct is_default_constructible<const std::pair<T1, T2>>
3715 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3716
3717template <typename... Ts>
3718struct is_default_constructible<std::tuple<Ts...>>
3719 : conjunction<is_default_constructible<Ts>...> {};
3720
3721template <typename... Ts>
3722struct is_default_constructible<const std::tuple<Ts...>>
3723 : conjunction<is_default_constructible<Ts>...> {};
3724
3725template <typename T, typename... Args>
3726struct is_constructible : std::is_constructible<T, Args...> {};
3727
3728template <typename T1, typename T2>
3729struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3730
3731template <typename T1, typename T2>
3732struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3733
3734template <typename... Ts>
3735struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3736
3737template <typename... Ts>
3738struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3739
3740template<typename T, typename = void>
3741struct is_iterator_traits : std::false_type {};
3742
3743template<typename T>
3745{
3746 private:
3747 using traits = iterator_traits<T>;
3748
3749 public:
3750 static constexpr auto value =
3756};
3757
3758template<typename T>
3760{
3761 private:
3762 using t_ref = typename std::add_lvalue_reference<T>::type;
3763
3764 using iterator = detected_t<result_of_begin, t_ref>;
3765 using sentinel = detected_t<result_of_end, t_ref>;
3766
3767 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3768 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3769 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3770 static constexpr auto is_iterator_begin =
3772
3773 public:
3774 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3775};
3776
3777template<typename R>
3778using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3779
3780template<typename T>
3782
3783// The following implementation of is_complete_type is taken from
3784// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3785// and is written by Xiang Fan who agreed to using it in this library.
3786
3787template<typename T, typename = void>
3788struct is_complete_type : std::false_type {};
3789
3790template<typename T>
3791struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3792
3793template<typename BasicJsonType, typename CompatibleObjectType,
3794 typename = void>
3795struct is_compatible_object_type_impl : std::false_type {};
3796
3797template<typename BasicJsonType, typename CompatibleObjectType>
3799 BasicJsonType, CompatibleObjectType,
3800 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3801 is_detected<key_type_t, CompatibleObjectType>::value >>
3802{
3803 using object_t = typename BasicJsonType::object_t;
3804
3805 // macOS's is_constructible does not play well with nonesuch...
3806 static constexpr bool value =
3807 is_constructible<typename object_t::key_type,
3808 typename CompatibleObjectType::key_type>::value &&
3809 is_constructible<typename object_t::mapped_type,
3810 typename CompatibleObjectType::mapped_type>::value;
3811};
3812
3813template<typename BasicJsonType, typename CompatibleObjectType>
3815 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3816
3817template<typename BasicJsonType, typename ConstructibleObjectType,
3818 typename = void>
3819struct is_constructible_object_type_impl : std::false_type {};
3820
3821template<typename BasicJsonType, typename ConstructibleObjectType>
3823 BasicJsonType, ConstructibleObjectType,
3824 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3825 is_detected<key_type_t, ConstructibleObjectType>::value >>
3826{
3827 using object_t = typename BasicJsonType::object_t;
3828
3829 static constexpr bool value =
3831 (std::is_move_assignable<ConstructibleObjectType>::value ||
3832 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3833 (is_constructible<typename ConstructibleObjectType::key_type,
3834 typename object_t::key_type>::value &&
3835 std::is_same <
3836 typename object_t::mapped_type,
3837 typename ConstructibleObjectType::mapped_type >::value)) ||
3838 (has_from_json<BasicJsonType,
3839 typename ConstructibleObjectType::mapped_type>::value ||
3841 BasicJsonType,
3842 typename ConstructibleObjectType::mapped_type >::value);
3843};
3844
3845template<typename BasicJsonType, typename ConstructibleObjectType>
3847 : is_constructible_object_type_impl<BasicJsonType,
3848 ConstructibleObjectType> {};
3849
3850template<typename BasicJsonType, typename CompatibleStringType>
3852{
3853 static constexpr auto value =
3855};
3856
3857template<typename BasicJsonType, typename ConstructibleStringType>
3859{
3860 // launder type through decltype() to fix compilation failure on ICPC
3861#ifdef __INTEL_COMPILER
3862 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3863#else
3864 using laundered_type = ConstructibleStringType;
3865#endif
3866
3867 static constexpr auto value =
3868 conjunction <
3870 is_detected_exact<typename BasicJsonType::string_t::value_type,
3872};
3873
3874template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3875struct is_compatible_array_type_impl : std::false_type {};
3876
3877template<typename BasicJsonType, typename CompatibleArrayType>
3879 BasicJsonType, CompatibleArrayType,
3880 enable_if_t <
3881 is_detected<iterator_t, CompatibleArrayType>::value&&
3882 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3883// special case for types like std::filesystem::path whose iterator's value_type are themselves
3884// c.f. https://github.com/nlohmann/json/pull/3073
3885 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3886{
3887 static constexpr bool value =
3888 is_constructible<BasicJsonType,
3890};
3891
3892template<typename BasicJsonType, typename CompatibleArrayType>
3894 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3895
3896template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3897struct is_constructible_array_type_impl : std::false_type {};
3898
3899template<typename BasicJsonType, typename ConstructibleArrayType>
3901 BasicJsonType, ConstructibleArrayType,
3902 enable_if_t<std::is_same<ConstructibleArrayType,
3903 typename BasicJsonType::value_type>::value >>
3904 : std::true_type {};
3905
3906template<typename BasicJsonType, typename ConstructibleArrayType>
3908 BasicJsonType, ConstructibleArrayType,
3909 enable_if_t < !std::is_same<ConstructibleArrayType,
3910 typename BasicJsonType::value_type>::value&&
3911 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3912 is_default_constructible<ConstructibleArrayType>::value&&
3913(std::is_move_assignable<ConstructibleArrayType>::value ||
3914 std::is_copy_assignable<ConstructibleArrayType>::value)&&
3915is_detected<iterator_t, ConstructibleArrayType>::value&&
3916is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3917is_detected<range_value_t, ConstructibleArrayType>::value&&
3918// special case for types like std::filesystem::path whose iterator's value_type are themselves
3919// c.f. https://github.com/nlohmann/json/pull/3073
3920!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3922 detected_t<range_value_t, ConstructibleArrayType >>::value >>
3923{
3925
3926 static constexpr bool value =
3927 std::is_same<value_type,
3928 typename BasicJsonType::array_t::value_type>::value ||
3929 has_from_json<BasicJsonType,
3932 BasicJsonType,
3934};
3935
3936template<typename BasicJsonType, typename ConstructibleArrayType>
3938 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3939
3940template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3941 typename = void>
3942struct is_compatible_integer_type_impl : std::false_type {};
3943
3944template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3946 RealIntegerType, CompatibleNumberIntegerType,
3947 enable_if_t < std::is_integral<RealIntegerType>::value&&
3948 std::is_integral<CompatibleNumberIntegerType>::value&&
3949 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3950{
3951 // is there an assert somewhere on overflows?
3952 using RealLimits = std::numeric_limits<RealIntegerType>;
3953 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3954
3955 static constexpr auto value =
3956 is_constructible<RealIntegerType,
3957 CompatibleNumberIntegerType>::value &&
3958 CompatibleLimits::is_integer &&
3959 RealLimits::is_signed == CompatibleLimits::is_signed;
3960};
3961
3962template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3964 : is_compatible_integer_type_impl<RealIntegerType,
3965 CompatibleNumberIntegerType> {};
3966
3967template<typename BasicJsonType, typename CompatibleType, typename = void>
3968struct is_compatible_type_impl: std::false_type {};
3969
3970template<typename BasicJsonType, typename CompatibleType>
3972 BasicJsonType, CompatibleType,
3973 enable_if_t<is_complete_type<CompatibleType>::value >>
3974{
3975 static constexpr bool value =
3977};
3978
3979template<typename BasicJsonType, typename CompatibleType>
3981 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3982
3983template<typename T1, typename T2>
3984struct is_constructible_tuple : std::false_type {};
3985
3986template<typename T1, typename... Args>
3987struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3988
3989template<typename BasicJsonType, typename T>
3990struct is_json_iterator_of : std::false_type {};
3991
3992template<typename BasicJsonType>
3993struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
3994
3995template<typename BasicJsonType>
3996struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
3997{};
3998
3999// checks if a given type T is a template specialization of Primary
4000template<template <typename...> class Primary, typename T>
4001struct is_specialization_of : std::false_type {};
4002
4003template<template <typename...> class Primary, typename... Args>
4004struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
4005
4006template<typename T>
4008
4009// checks if A and B are comparable using Compare functor
4010template<typename Compare, typename A, typename B, typename = void>
4011struct is_comparable : std::false_type {};
4012
4013template<typename Compare, typename A, typename B>
4014struct is_comparable<Compare, A, B, void_t<
4015decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
4016decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
4017>> : std::true_type {};
4018
4019template<typename T>
4020using detect_is_transparent = typename T::is_transparent;
4021
4022// type trait to check if KeyType can be used as object key (without a BasicJsonType)
4023// see is_usable_as_basic_json_key_type below
4024template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4025 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4026using is_usable_as_key_type = typename std::conditional <
4028 && !(ExcludeObjectKeyType && std::is_same<KeyType,
4029 ObjectKeyType>::value)
4030 && (!RequireTransparentComparator
4031 || is_detected <detect_is_transparent, Comparator>::value)
4033 std::true_type,
4034 std::false_type >::type;
4035
4036// type trait to check if KeyType can be used as object key
4037// true if:
4038// - KeyType is comparable with BasicJsonType::object_t::key_type
4039// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4040// - the comparator is transparent or RequireTransparentComparator is false
4041// - KeyType is not a JSON iterator or json_pointer
4042template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4043 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4044using is_usable_as_basic_json_key_type = typename std::conditional <
4045 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4046 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4047 RequireTransparentComparator, ExcludeObjectKeyType>::value
4049 std::true_type,
4050 std::false_type >::type;
4051
4052template<typename ObjectType, typename KeyType>
4053using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4054
4055// type trait to check if object_t has an erase() member functions accepting KeyType
4056template<typename BasicJsonType, typename KeyType>
4057using has_erase_with_key_type = typename std::conditional <
4058 is_detected <
4060 typename BasicJsonType::object_t, KeyType >::value,
4061 std::true_type,
4062 std::false_type >::type;
4063
4064// a naive helper to check if a type is an ordered_map (exploits the fact that
4065// ordered_map inherits capacity() from std::vector)
4066template <typename T>
4068{
4069 using one = char;
4070
4071 struct two
4072 {
4073 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4074 };
4075
4076 template <typename C> static one test( decltype(&C::capacity) ) ;
4077 template <typename C> static two test(...);
4078
4079 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4080};
4081
4082// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4083template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4085{
4086 return static_cast<T>(value);
4087}
4088
4089template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4091{
4092 return value;
4093}
4094
4095template<typename... Types>
4097
4098template<typename... Types>
4100
4101template<typename... Types>
4103
4104// there's a disjunction trait in another PR; replace when merged
4105template<typename... Types>
4106using same_sign = std::integral_constant < bool,
4107 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4108
4109template<typename OfType, typename T>
4110using never_out_of_range = std::integral_constant < bool,
4111 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4112 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4113
4114template<typename OfType, typename T,
4115 bool OfTypeSigned = std::is_signed<OfType>::value,
4116 bool TSigned = std::is_signed<T>::value>
4118
4119template<typename OfType, typename T>
4120struct value_in_range_of_impl2<OfType, T, false, false>
4121{
4122 static constexpr bool test(T val)
4123 {
4124 using CommonType = typename std::common_type<OfType, T>::type;
4125 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4126 }
4127};
4128
4129template<typename OfType, typename T>
4130struct value_in_range_of_impl2<OfType, T, true, false>
4131{
4132 static constexpr bool test(T val)
4133 {
4134 using CommonType = typename std::common_type<OfType, T>::type;
4135 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4136 }
4137};
4138
4139template<typename OfType, typename T>
4140struct value_in_range_of_impl2<OfType, T, false, true>
4141{
4142 static constexpr bool test(T val)
4143 {
4144 using CommonType = typename std::common_type<OfType, T>::type;
4145 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4146 }
4147};
4148
4149template<typename OfType, typename T>
4150struct value_in_range_of_impl2<OfType, T, true, true>
4151{
4152 static constexpr bool test(T val)
4153 {
4154 using CommonType = typename std::common_type<OfType, T>::type;
4155 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4156 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4157 }
4158};
4159
4160template<typename OfType, typename T,
4161 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4164
4165template<typename OfType, typename T>
4166struct value_in_range_of_impl1<OfType, T, false>
4167{
4168 static constexpr bool test(T val)
4169 {
4171 }
4172};
4173
4174template<typename OfType, typename T>
4175struct value_in_range_of_impl1<OfType, T, true>
4176{
4177 static constexpr bool test(T /*val*/)
4178 {
4179 return true;
4180 }
4181};
4182
4183template<typename OfType, typename T>
4184constexpr bool value_in_range_of(T val)
4185{
4187}
4188
4189template<bool Value>
4190using bool_constant = std::integral_constant<bool, Value>;
4191
4193// is_c_string
4195
4196namespace impl
4197{
4198
4199template<typename T>
4200constexpr bool is_c_string()
4201{
4202 using TUnExt = typename std::remove_extent<T>::type;
4203 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4204 using TUnPtr = typename std::remove_pointer<T>::type;
4205 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4206 return
4207 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4208 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4209}
4210
4211} // namespace impl
4212
4213// checks whether T is a [cv] char */[cv] char[] C string
4214template<typename T>
4215struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4216
4217template<typename T>
4219
4221// is_transparent
4223
4224namespace impl
4225{
4226
4227template<typename T>
4228constexpr bool is_transparent()
4229{
4231}
4232
4233} // namespace impl
4234
4235// checks whether T has a member named is_transparent
4236template<typename T>
4237struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4238
4240
4241} // namespace detail
4243
4244// #include <nlohmann/detail/string_concat.hpp>
4245// __ _____ _____ _____
4246// __| | __| | | | JSON for Modern C++
4247// | | |__ | | | | | | version 3.11.3
4248// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4249//
4250// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4251// SPDX-License-Identifier: MIT
4252
4253
4254
4255#include <cstring> // strlen
4256#include <string> // string
4257#include <utility> // forward
4258
4259// #include <nlohmann/detail/meta/cpp_future.hpp>
4260
4261// #include <nlohmann/detail/meta/detected.hpp>
4262
4263
4265namespace detail
4266{
4267
4268inline std::size_t concat_length()
4269{
4270 return 0;
4271}
4272
4273template<typename... Args>
4274inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4275
4276template<typename StringType, typename... Args>
4277inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4278
4279template<typename... Args>
4280inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4281{
4282 return 1 + concat_length(rest...);
4283}
4284
4285template<typename... Args>
4286inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4287{
4288 // cppcheck-suppress ignoredReturnValue
4289 return ::strlen(cstr) + concat_length(rest...);
4290}
4291
4292template<typename StringType, typename... Args>
4293inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4294{
4295 return str.size() + concat_length(rest...);
4296}
4297
4298template<typename OutStringType>
4299inline void concat_into(OutStringType& /*out*/)
4300{}
4301
4302template<typename StringType, typename Arg>
4303using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4304
4305template<typename StringType, typename Arg>
4307
4308template<typename StringType, typename Arg>
4309using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4310
4311template<typename StringType, typename Arg>
4313
4314template<typename StringType, typename Arg>
4315using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4316
4317template<typename StringType, typename Arg>
4319
4320template<typename StringType, typename Arg>
4321using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4322
4323template<typename StringType, typename Arg>
4325
4326template < typename OutStringType, typename Arg, typename... Args,
4327 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4329inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4330
4331template < typename OutStringType, typename Arg, typename... Args,
4332 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4335inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4336
4337template < typename OutStringType, typename Arg, typename... Args,
4338 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4342inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4343
4344template<typename OutStringType, typename Arg, typename... Args,
4346inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4347{
4348 out.append(std::forward<Arg>(arg));
4349 concat_into(out, std::forward<Args>(rest)...);
4350}
4351
4352template < typename OutStringType, typename Arg, typename... Args,
4353 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4354 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4355inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4356{
4357 out += std::forward<Arg>(arg);
4358 concat_into(out, std::forward<Args>(rest)...);
4359}
4360
4361template < typename OutStringType, typename Arg, typename... Args,
4362 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4363 && !detect_string_can_append_op<OutStringType, Arg>::value
4364 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4365inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4366{
4367 out.append(arg.begin(), arg.end());
4368 concat_into(out, std::forward<Args>(rest)...);
4369}
4370
4371template < typename OutStringType, typename Arg, typename... Args,
4372 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4373 && !detect_string_can_append_op<OutStringType, Arg>::value
4374 && !detect_string_can_append_iter<OutStringType, Arg>::value
4375 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4376inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4377{
4378 out.append(arg.data(), arg.size());
4379 concat_into(out, std::forward<Args>(rest)...);
4380}
4381
4382template<typename OutStringType = std::string, typename... Args>
4383inline OutStringType concat(Args && ... args)
4384{
4385 OutStringType str;
4386 str.reserve(concat_length(args...));
4387 concat_into(str, std::forward<Args>(args)...);
4388 return str;
4389}
4390
4391} // namespace detail
4393
4394
4395// With -Wweak-vtables, Clang will complain about the exception classes as they
4396// have no out-of-line virtual method definitions and their vtable will be
4397// emitted in every translation unit. This issue cannot be fixed with a
4398// header-only library as there is no implementation file to move these
4399// functions to. As a result, we suppress this warning here to avoid client
4400// code to stumble over this. See https://github.com/nlohmann/json/issues/4087
4401// for a discussion.
4402#if defined(__clang__)
4403 #pragma clang diagnostic push
4404 #pragma clang diagnostic ignored "-Wweak-vtables"
4405#endif
4406
4408namespace detail
4409{
4410
4412// exceptions //
4414
4417class exception : public std::exception
4418{
4419 public:
4421 const char* what() const noexcept override
4422 {
4423 return m.what();
4424 }
4425
4427 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4428
4429 protected:
4431 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4432
4433 static std::string name(const std::string& ename, int id_)
4434 {
4435 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4436 }
4437
4438 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4439 {
4440 return "";
4441 }
4442
4443 template<typename BasicJsonType>
4444 static std::string diagnostics(const BasicJsonType* leaf_element)
4445 {
4446#if JSON_DIAGNOSTICS
4447 std::vector<std::string> tokens;
4448 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4449 {
4450 switch (current->m_parent->type())
4451 {
4452 case value_t::array:
4453 {
4454 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4455 {
4456 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4457 {
4458 tokens.emplace_back(std::to_string(i));
4459 break;
4460 }
4461 }
4462 break;
4463 }
4464
4465 case value_t::object:
4466 {
4467 for (const auto& element : *current->m_parent->m_data.m_value.object)
4468 {
4469 if (&element.second == current)
4470 {
4471 tokens.emplace_back(element.first.c_str());
4472 break;
4473 }
4474 }
4475 break;
4476 }
4477
4478 case value_t::null: // LCOV_EXCL_LINE
4479 case value_t::string: // LCOV_EXCL_LINE
4480 case value_t::boolean: // LCOV_EXCL_LINE
4481 case value_t::number_integer: // LCOV_EXCL_LINE
4482 case value_t::number_unsigned: // LCOV_EXCL_LINE
4483 case value_t::number_float: // LCOV_EXCL_LINE
4484 case value_t::binary: // LCOV_EXCL_LINE
4485 case value_t::discarded: // LCOV_EXCL_LINE
4486 default: // LCOV_EXCL_LINE
4487 break; // LCOV_EXCL_LINE
4488 }
4489 }
4490
4491 if (tokens.empty())
4492 {
4493 return "";
4494 }
4495
4496 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4497 [](const std::string & a, const std::string & b)
4498 {
4499 return concat(a, '/', detail::escape(b));
4500 });
4501 return concat('(', str, ") ");
4502#else
4503 static_cast<void>(leaf_element);
4504 return "";
4505#endif
4506 }
4507
4508 private:
4510 std::runtime_error m;
4511};
4512
4516{
4517 public:
4527 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4528 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4529 {
4530 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4531 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4532 return {id_, pos.chars_read_total, w.c_str()};
4533 }
4534
4535 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4536 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4537 {
4538 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4539 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4540 ": ", exception::diagnostics(context), what_arg);
4541 return {id_, byte_, w.c_str()};
4542 }
4543
4553 const std::size_t byte;
4554
4555 private:
4556 parse_error(int id_, std::size_t byte_, const char* what_arg)
4557 : exception(id_, what_arg), byte(byte_) {}
4558
4559 static std::string position_string(const position_t& pos)
4560 {
4561 return concat(" at line ", std::to_string(pos.lines_read + 1),
4562 ", column ", std::to_string(pos.chars_read_current_line));
4563 }
4564};
4565
4569{
4570 public:
4571 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4572 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4573 {
4574 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4575 return {id_, w.c_str()};
4576 }
4577
4578 private:
4580 invalid_iterator(int id_, const char* what_arg)
4581 : exception(id_, what_arg) {}
4582};
4583
4586class type_error : public exception
4587{
4588 public:
4589 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4590 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4591 {
4592 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4593 return {id_, w.c_str()};
4594 }
4595
4596 private:
4598 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4599};
4600
4604{
4605 public:
4606 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4607 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4608 {
4609 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4610 return {id_, w.c_str()};
4611 }
4612
4613 private:
4615 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4616};
4617
4621{
4622 public:
4623 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4624 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4625 {
4626 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4627 return {id_, w.c_str()};
4628 }
4629
4630 private:
4632 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4633};
4634
4635} // namespace detail
4637
4638#if defined(__clang__)
4639 #pragma clang diagnostic pop
4640#endif
4641
4642// #include <nlohmann/detail/macro_scope.hpp>
4643
4644// #include <nlohmann/detail/meta/cpp_future.hpp>
4645
4646// #include <nlohmann/detail/meta/identity_tag.hpp>
4647// __ _____ _____ _____
4648// __| | __| | | | JSON for Modern C++
4649// | | |__ | | | | | | version 3.11.3
4650// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4651//
4652// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4653// SPDX-License-Identifier: MIT
4654
4655
4656
4657// #include <nlohmann/detail/abi_macros.hpp>
4658
4659
4661namespace detail
4662{
4663
4664// dispatching helper struct
4665template <class T> struct identity_tag {};
4666
4667} // namespace detail
4669
4670// #include <nlohmann/detail/meta/std_fs.hpp>
4671// __ _____ _____ _____
4672// __| | __| | | | JSON for Modern C++
4673// | | |__ | | | | | | version 3.11.3
4674// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4675//
4676// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4677// SPDX-License-Identifier: MIT
4678
4679
4680
4681// #include <nlohmann/detail/macro_scope.hpp>
4682
4683
4684#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4685#include <experimental/filesystem>
4687namespace detail
4688{
4689namespace std_fs = std::experimental::filesystem;
4690} // namespace detail
4692#elif JSON_HAS_FILESYSTEM
4693#include <filesystem> // NOLINT(build/c++17)
4695namespace detail
4696{
4697namespace std_fs = std::filesystem;
4698} // namespace detail
4700#endif
4701
4702// #include <nlohmann/detail/meta/type_traits.hpp>
4703
4704// #include <nlohmann/detail/string_concat.hpp>
4705
4706// #include <nlohmann/detail/value_t.hpp>
4707
4708
4710namespace detail
4711{
4712
4713template<typename BasicJsonType>
4714inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4715{
4716 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4717 {
4718 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4719 }
4720 n = nullptr;
4721}
4722
4723#ifdef JSON_HAS_CPP_17
4724#ifndef JSON_USE_IMPLICIT_CONVERSIONS
4725template<typename BasicJsonType, typename T>
4726void from_json(const BasicJsonType& j, std::optional<T>& opt)
4727{
4728 if (j.is_null())
4729 {
4730 opt = std::nullopt;
4731 }
4732 else
4733 {
4734 opt.emplace(j.template get<T>());
4735 }
4736}
4737
4738#endif // JSON_USE_IMPLICIT_CONVERSIONS
4739#endif // JSON_HAS_CPP_17
4740
4741// overloads for basic_json template parameters
4742template < typename BasicJsonType, typename ArithmeticType,
4743 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4744 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4745 int > = 0 >
4746void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4747{
4748 switch (static_cast<value_t>(j))
4749 {
4751 {
4752 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4753 break;
4754 }
4756 {
4757 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4758 break;
4759 }
4761 {
4762 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4763 break;
4764 }
4765
4766 case value_t::null:
4767 case value_t::object:
4768 case value_t::array:
4769 case value_t::string:
4770 case value_t::boolean:
4771 case value_t::binary:
4772 case value_t::discarded:
4773 default:
4774 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4775 }
4776}
4777
4778template<typename BasicJsonType>
4779inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4780{
4781 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4782 {
4783 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4784 }
4785 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4786}
4787
4788template<typename BasicJsonType>
4789inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4790{
4791 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4792 {
4793 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4794 }
4795 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4796}
4797
4798template <
4799 typename BasicJsonType, typename StringType,
4800 enable_if_t <
4801 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4802 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4803 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4804 && !is_json_ref<StringType>::value, int > = 0 >
4805inline void from_json(const BasicJsonType& j, StringType& s)
4806{
4807 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4808 {
4809 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4810 }
4811
4812 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4813}
4814
4815template<typename BasicJsonType>
4816inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4817{
4818 get_arithmetic_value(j, val);
4819}
4820
4821template<typename BasicJsonType>
4822inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4823{
4824 get_arithmetic_value(j, val);
4825}
4826
4827template<typename BasicJsonType>
4828inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4829{
4830 get_arithmetic_value(j, val);
4831}
4832
4833#if !JSON_DISABLE_ENUM_SERIALIZATION
4834template<typename BasicJsonType, typename EnumType,
4835 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4836inline void from_json(const BasicJsonType& j, EnumType& e)
4837{
4838 typename std::underlying_type<EnumType>::type val;
4839 get_arithmetic_value(j, val);
4840 e = static_cast<EnumType>(val);
4841}
4842#endif // JSON_DISABLE_ENUM_SERIALIZATION
4843
4844// forward_list doesn't have an insert method
4845template<typename BasicJsonType, typename T, typename Allocator,
4846 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4847inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4848{
4849 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4850 {
4851 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4852 }
4853 l.clear();
4854 std::transform(j.rbegin(), j.rend(),
4855 std::front_inserter(l), [](const BasicJsonType & i)
4856 {
4857 return i.template get<T>();
4858 });
4859}
4860
4861// valarray doesn't have an insert method
4862template<typename BasicJsonType, typename T,
4863 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4864inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4865{
4866 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4867 {
4868 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4869 }
4870 l.resize(j.size());
4871 std::transform(j.begin(), j.end(), std::begin(l),
4872 [](const BasicJsonType & elem)
4873 {
4874 return elem.template get<T>();
4875 });
4876}
4877
4878template<typename BasicJsonType, typename T, std::size_t N>
4879auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4880-> decltype(j.template get<T>(), void())
4881{
4882 for (std::size_t i = 0; i < N; ++i)
4883 {
4884 arr[i] = j.at(i).template get<T>();
4885 }
4886}
4887
4888template<typename BasicJsonType>
4889inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
4890{
4891 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4892}
4893
4894template<typename BasicJsonType, typename T, std::size_t N>
4895auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
4896 priority_tag<2> /*unused*/)
4897-> decltype(j.template get<T>(), void())
4898{
4899 for (std::size_t i = 0; i < N; ++i)
4900 {
4901 arr[i] = j.at(i).template get<T>();
4902 }
4903}
4904
4905template<typename BasicJsonType, typename ConstructibleArrayType,
4907 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4908 int> = 0>
4909auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4910-> decltype(
4911 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4912 j.template get<typename ConstructibleArrayType::value_type>(),
4913 void())
4914{
4915 using std::end;
4916
4917 ConstructibleArrayType ret;
4918 ret.reserve(j.size());
4919 std::transform(j.begin(), j.end(),
4920 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4921 {
4922 // get<BasicJsonType>() returns *this, this won't call a from_json
4923 // method when value_type is BasicJsonType
4924 return i.template get<typename ConstructibleArrayType::value_type>();
4925 });
4926 arr = std::move(ret);
4927}
4928
4929template<typename BasicJsonType, typename ConstructibleArrayType,
4931 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4932 int> = 0>
4933inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4934 priority_tag<0> /*unused*/)
4935{
4936 using std::end;
4937
4938 ConstructibleArrayType ret;
4939 std::transform(
4940 j.begin(), j.end(), std::inserter(ret, end(ret)),
4941 [](const BasicJsonType & i)
4942 {
4943 // get<BasicJsonType>() returns *this, this won't call a from_json
4944 // method when value_type is BasicJsonType
4945 return i.template get<typename ConstructibleArrayType::value_type>();
4946 });
4947 arr = std::move(ret);
4948}
4949
4950template < typename BasicJsonType, typename ConstructibleArrayType,
4951 enable_if_t <
4952 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4953 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4955 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4956 !is_basic_json<ConstructibleArrayType>::value,
4957 int > = 0 >
4958auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4959-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4960j.template get<typename ConstructibleArrayType::value_type>(),
4961void())
4962{
4963 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4964 {
4965 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4966 }
4967
4968 from_json_array_impl(j, arr, priority_tag<3> {});
4969}
4970
4971template < typename BasicJsonType, typename T, std::size_t... Idx >
4972std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4973 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4974{
4975 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4976}
4977
4978template < typename BasicJsonType, typename T, std::size_t N >
4979auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4980-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4981{
4982 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4983 {
4984 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4985 }
4986
4987 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4988}
4989
4990template<typename BasicJsonType>
4991inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4992{
4993 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4994 {
4995 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
4996 }
4997
4998 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4999}
5000
5001template<typename BasicJsonType, typename ConstructibleObjectType,
5002 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
5003inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
5004{
5005 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
5006 {
5007 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
5008 }
5009
5010 ConstructibleObjectType ret;
5011 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
5012 using value_type = typename ConstructibleObjectType::value_type;
5013 std::transform(
5014 inner_object->begin(), inner_object->end(),
5015 std::inserter(ret, ret.begin()),
5016 [](typename BasicJsonType::object_t::value_type const & p)
5017 {
5018 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
5019 });
5020 obj = std::move(ret);
5021}
5022
5023// overload for arithmetic types, not chosen for basic_json template arguments
5024// (BooleanType, etc..); note: Is it really necessary to provide explicit
5025// overloads for boolean_t etc. in case of a custom BooleanType which is not
5026// an arithmetic type?
5027template < typename BasicJsonType, typename ArithmeticType,
5028 enable_if_t <
5029 std::is_arithmetic<ArithmeticType>::value&&
5030 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
5031 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
5032 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
5033 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
5034 int > = 0 >
5035inline void from_json(const BasicJsonType& j, ArithmeticType& val)
5036{
5037 switch (static_cast<value_t>(j))
5038 {
5040 {
5041 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
5042 break;
5043 }
5045 {
5046 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5047 break;
5048 }
5050 {
5051 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5052 break;
5053 }
5054 case value_t::boolean:
5055 {
5056 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5057 break;
5058 }
5059
5060 case value_t::null:
5061 case value_t::object:
5062 case value_t::array:
5063 case value_t::string:
5064 case value_t::binary:
5065 case value_t::discarded:
5066 default:
5067 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5068 }
5069}
5070
5071template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5072std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5073{
5074 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5075}
5076
5077template < typename BasicJsonType, class A1, class A2 >
5078std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5079{
5080 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5081 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5082}
5083
5084template<typename BasicJsonType, typename A1, typename A2>
5085inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5086{
5087 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5088}
5089
5090template<typename BasicJsonType, typename... Args>
5091std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5092{
5093 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5094}
5095
5096template<typename BasicJsonType, typename... Args>
5097inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5098{
5099 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5100}
5101
5102template<typename BasicJsonType, typename TupleRelated>
5103auto from_json(BasicJsonType&& j, TupleRelated&& t)
5104-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5105{
5106 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5107 {
5108 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5109 }
5110
5111 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5112}
5113
5114template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5115 typename = enable_if_t < !std::is_constructible <
5116 typename BasicJsonType::string_t, Key >::value >>
5117inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5118{
5119 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5120 {
5121 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5122 }
5123 m.clear();
5124 for (const auto& p : j)
5125 {
5126 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5127 {
5128 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5129 }
5130 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5131 }
5132}
5133
5134template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5135 typename = enable_if_t < !std::is_constructible <
5136 typename BasicJsonType::string_t, Key >::value >>
5137inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5138{
5139 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5140 {
5141 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5142 }
5143 m.clear();
5144 for (const auto& p : j)
5145 {
5146 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5147 {
5148 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5149 }
5150 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5151 }
5152}
5153
5154#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5155template<typename BasicJsonType>
5156inline void from_json(const BasicJsonType& j, std_fs::path& p)
5157{
5158 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5159 {
5160 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5161 }
5162 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5163}
5164#endif
5165
5167{
5168 template<typename BasicJsonType, typename T>
5169 auto operator()(const BasicJsonType& j, T&& val) const
5170 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5171 -> decltype(from_json(j, std::forward<T>(val)))
5172 {
5173 return from_json(j, std::forward<T>(val));
5174 }
5175};
5176
5177} // namespace detail
5178
5179#ifndef JSON_HAS_CPP_17
5183namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5184{
5185#endif
5186JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5188#ifndef JSON_HAS_CPP_17
5189} // namespace
5190#endif
5191
5193
5194// #include <nlohmann/detail/conversions/to_json.hpp>
5195// __ _____ _____ _____
5196// __| | __| | | | JSON for Modern C++
5197// | | |__ | | | | | | version 3.11.3
5198// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5199//
5200// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5201// SPDX-License-Identifier: MIT
5202
5203
5204
5205#include <algorithm> // copy
5206#include <iterator> // begin, end
5207#ifdef JSON_HAS_CPP_17
5208 #include <optional> // optional
5209#endif
5210#include <string> // string
5211#include <tuple> // tuple, get
5212#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5213#include <utility> // move, forward, declval, pair
5214#include <valarray> // valarray
5215#include <vector> // vector
5216
5217// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5218// __ _____ _____ _____
5219// __| | __| | | | JSON for Modern C++
5220// | | |__ | | | | | | version 3.11.3
5221// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5222//
5223// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5224// SPDX-License-Identifier: MIT
5225
5226
5227
5228#include <cstddef> // size_t
5229#include <iterator> // forward_iterator_tag
5230#include <string> // string, to_string
5231#include <tuple> // tuple_size, get, tuple_element
5232#include <utility> // move
5233
5234#if JSON_HAS_RANGES
5235 #include <ranges> // enable_borrowed_range
5236#endif
5237
5238// #include <nlohmann/detail/abi_macros.hpp>
5239
5240// #include <nlohmann/detail/meta/type_traits.hpp>
5241
5242// #include <nlohmann/detail/value_t.hpp>
5243
5244
5246namespace detail
5247{
5248
5249template<typename string_type>
5250void int_to_string( string_type& target, std::size_t value )
5251{
5252 // For ADL
5253 using std::to_string;
5254 target = to_string(value);
5255}
5256template<typename IteratorType> class iteration_proxy_value
5257{
5258 public:
5259 using difference_type = std::ptrdiff_t;
5263 using iterator_category = std::forward_iterator_tag;
5264 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5265
5266 private:
5268 IteratorType anchor{};
5270 std::size_t array_index = 0;
5272 mutable std::size_t array_index_last = 0;
5274 mutable string_type array_index_str = "0";
5276 string_type empty_str{};
5277
5278 public:
5279 explicit iteration_proxy_value() = default;
5280 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5281 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5282 && std::is_nothrow_default_constructible<string_type>::value)
5283 : anchor(std::move(it))
5284 , array_index(array_index_)
5285 {}
5286
5289 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5291 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5292 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5294 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5295 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5297
5299 const iteration_proxy_value& operator*() const
5300 {
5301 return *this;
5302 }
5303
5306 {
5307 ++anchor;
5308 ++array_index;
5309
5310 return *this;
5311 }
5312
5313 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5314 {
5315 auto tmp = iteration_proxy_value(anchor, array_index);
5316 ++anchor;
5317 ++array_index;
5318 return tmp;
5319 }
5320
5323 {
5324 return anchor == o.anchor;
5325 }
5326
5329 {
5330 return anchor != o.anchor;
5331 }
5332
5334 const string_type& key() const
5335 {
5336 JSON_ASSERT(anchor.m_object != nullptr);
5337
5338 switch (anchor.m_object->type())
5339 {
5340 // use integer array index as key
5341 case value_t::array:
5342 {
5343 if (array_index != array_index_last)
5344 {
5345 int_to_string( array_index_str, array_index );
5346 array_index_last = array_index;
5347 }
5348 return array_index_str;
5349 }
5350
5351 // use key from the object
5352 case value_t::object:
5353 return anchor.key();
5354
5355 // use an empty key for all primitive types
5356 case value_t::null:
5357 case value_t::string:
5358 case value_t::boolean:
5362 case value_t::binary:
5363 case value_t::discarded:
5364 default:
5365 return empty_str;
5366 }
5367 }
5368
5370 typename IteratorType::reference value() const
5371 {
5372 return anchor.value();
5373 }
5374};
5375
5377template<typename IteratorType> class iteration_proxy
5378{
5379 private:
5381 typename IteratorType::pointer container = nullptr;
5382
5383 public:
5384 explicit iteration_proxy() = default;
5385
5387 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5388 : container(&cont) {}
5389
5392 iteration_proxy(iteration_proxy&&) noexcept = default;
5393 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5394 ~iteration_proxy() = default;
5395
5397 iteration_proxy_value<IteratorType> begin() const noexcept
5398 {
5399 return iteration_proxy_value<IteratorType>(container->begin());
5400 }
5401
5404 {
5405 return iteration_proxy_value<IteratorType>(container->end());
5406 }
5407};
5408
5409// Structured Bindings Support
5410// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5411// And see https://github.com/nlohmann/json/pull/1391
5412template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5413auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5414{
5415 return i.key();
5416}
5417// Structured Bindings Support
5418// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5419// And see https://github.com/nlohmann/json/pull/1391
5420template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5421auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5422{
5423 return i.value();
5424}
5425
5426} // namespace detail
5428
5429// The Addition to the STD Namespace is required to add
5430// Structured Bindings Support to the iteration_proxy_value class
5431// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5432// And see https://github.com/nlohmann/json/pull/1391
5433namespace std
5434{
5435
5436#if defined(__clang__)
5437 // Fix: https://github.com/nlohmann/json/issues/1401
5438 #pragma clang diagnostic push
5439 #pragma clang diagnostic ignored "-Wmismatched-tags"
5440#endif
5441template<typename IteratorType>
5442class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5443 : public std::integral_constant<std::size_t, 2> {};
5444
5445template<std::size_t N, typename IteratorType>
5446class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5447{
5448 public:
5449 using type = decltype(
5450 get<N>(std::declval <
5451 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5452};
5453#if defined(__clang__)
5454 #pragma clang diagnostic pop
5455#endif
5456
5457} // namespace std
5458
5459#if JSON_HAS_RANGES
5460 template <typename IteratorType>
5461 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5462#endif
5463
5464// #include <nlohmann/detail/macro_scope.hpp>
5465
5466// #include <nlohmann/detail/meta/cpp_future.hpp>
5467
5468// #include <nlohmann/detail/meta/std_fs.hpp>
5469
5470// #include <nlohmann/detail/meta/type_traits.hpp>
5471
5472// #include <nlohmann/detail/value_t.hpp>
5473
5474
5476namespace detail
5477{
5478
5480// constructors //
5482
5483/*
5484 * Note all external_constructor<>::construct functions need to call
5485 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5486 * allocated value (e.g., a string). See bug issue
5487 * https://github.com/nlohmann/json/issues/2865 for more information.
5488 */
5489
5490template<value_t> struct external_constructor;
5491
5492template<>
5494{
5495 template<typename BasicJsonType>
5496 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5497 {
5498 j.m_data.m_value.destroy(j.m_data.m_type);
5499 j.m_data.m_type = value_t::boolean;
5500 j.m_data.m_value = b;
5501 j.assert_invariant();
5502 }
5503};
5504
5505template<>
5507{
5508 template<typename BasicJsonType>
5509 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5510 {
5511 j.m_data.m_value.destroy(j.m_data.m_type);
5512 j.m_data.m_type = value_t::string;
5513 j.m_data.m_value = s;
5514 j.assert_invariant();
5515 }
5516
5517 template<typename BasicJsonType>
5518 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5519 {
5520 j.m_data.m_value.destroy(j.m_data.m_type);
5521 j.m_data.m_type = value_t::string;
5522 j.m_data.m_value = std::move(s);
5523 j.assert_invariant();
5524 }
5525
5526 template < typename BasicJsonType, typename CompatibleStringType,
5527 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5528 int > = 0 >
5529 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5530 {
5531 j.m_data.m_value.destroy(j.m_data.m_type);
5532 j.m_data.m_type = value_t::string;
5533 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5534 j.assert_invariant();
5535 }
5536};
5537
5538template<>
5540{
5541 template<typename BasicJsonType>
5542 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5543 {
5544 j.m_data.m_value.destroy(j.m_data.m_type);
5545 j.m_data.m_type = value_t::binary;
5546 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5547 j.assert_invariant();
5548 }
5549
5550 template<typename BasicJsonType>
5551 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5552 {
5553 j.m_data.m_value.destroy(j.m_data.m_type);
5554 j.m_data.m_type = value_t::binary;
5555 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5556 j.assert_invariant();
5557 }
5558};
5559
5560template<>
5562{
5563 template<typename BasicJsonType>
5564 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5565 {
5566 j.m_data.m_value.destroy(j.m_data.m_type);
5567 j.m_data.m_type = value_t::number_float;
5568 j.m_data.m_value = val;
5569 j.assert_invariant();
5570 }
5571};
5572
5573template<>
5575{
5576 template<typename BasicJsonType>
5577 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5578 {
5579 j.m_data.m_value.destroy(j.m_data.m_type);
5580 j.m_data.m_type = value_t::number_unsigned;
5581 j.m_data.m_value = val;
5582 j.assert_invariant();
5583 }
5584};
5585
5586template<>
5588{
5589 template<typename BasicJsonType>
5590 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5591 {
5592 j.m_data.m_value.destroy(j.m_data.m_type);
5593 j.m_data.m_type = value_t::number_integer;
5594 j.m_data.m_value = val;
5595 j.assert_invariant();
5596 }
5597};
5598
5599template<>
5601{
5602 template<typename BasicJsonType>
5603 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5604 {
5605 j.m_data.m_value.destroy(j.m_data.m_type);
5606 j.m_data.m_type = value_t::array;
5607 j.m_data.m_value = arr;
5608 j.set_parents();
5609 j.assert_invariant();
5610 }
5611
5612 template<typename BasicJsonType>
5613 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5614 {
5615 j.m_data.m_value.destroy(j.m_data.m_type);
5616 j.m_data.m_type = value_t::array;
5617 j.m_data.m_value = std::move(arr);
5618 j.set_parents();
5619 j.assert_invariant();
5620 }
5621
5622 template < typename BasicJsonType, typename CompatibleArrayType,
5623 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5624 int > = 0 >
5625 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5626 {
5627 using std::begin;
5628 using std::end;
5629
5630 j.m_data.m_value.destroy(j.m_data.m_type);
5631 j.m_data.m_type = value_t::array;
5632 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5633 j.set_parents();
5634 j.assert_invariant();
5635 }
5636
5637 template<typename BasicJsonType>
5638 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5639 {
5640 j.m_data.m_value.destroy(j.m_data.m_type);
5641 j.m_data.m_type = value_t::array;
5642 j.m_data.m_value = value_t::array;
5643 j.m_data.m_value.array->reserve(arr.size());
5644 for (const bool x : arr)
5645 {
5646 j.m_data.m_value.array->push_back(x);
5647 j.set_parent(j.m_data.m_value.array->back());
5648 }
5649 j.assert_invariant();
5650 }
5651
5652 template<typename BasicJsonType, typename T,
5654 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5655 {
5656 j.m_data.m_value.destroy(j.m_data.m_type);
5657 j.m_data.m_type = value_t::array;
5658 j.m_data.m_value = value_t::array;
5659 j.m_data.m_value.array->resize(arr.size());
5660 if (arr.size() > 0)
5661 {
5662 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5663 }
5664 j.set_parents();
5665 j.assert_invariant();
5666 }
5667};
5668
5669template<>
5671{
5672 template<typename BasicJsonType>
5673 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5674 {
5675 j.m_data.m_value.destroy(j.m_data.m_type);
5676 j.m_data.m_type = value_t::object;
5677 j.m_data.m_value = obj;
5678 j.set_parents();
5679 j.assert_invariant();
5680 }
5681
5682 template<typename BasicJsonType>
5683 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5684 {
5685 j.m_data.m_value.destroy(j.m_data.m_type);
5686 j.m_data.m_type = value_t::object;
5687 j.m_data.m_value = std::move(obj);
5688 j.set_parents();
5689 j.assert_invariant();
5690 }
5691
5692 template < typename BasicJsonType, typename CompatibleObjectType,
5693 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5694 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5695 {
5696 using std::begin;
5697 using std::end;
5698
5699 j.m_data.m_value.destroy(j.m_data.m_type);
5700 j.m_data.m_type = value_t::object;
5701 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5702 j.set_parents();
5703 j.assert_invariant();
5704 }
5705};
5706
5708// to_json //
5710
5711#ifdef JSON_HAS_CPP_17
5712template<typename BasicJsonType, typename T,
5713 enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
5714void to_json(BasicJsonType& j, const std::optional<T>& opt)
5715{
5716 if (opt.has_value())
5717 {
5718 j = *opt;
5719 }
5720 else
5721 {
5722 j = nullptr;
5723 }
5724}
5725#endif
5726
5727template<typename BasicJsonType, typename T,
5728 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5729inline void to_json(BasicJsonType& j, T b) noexcept
5730{
5732}
5733
5734template < typename BasicJsonType, typename BoolRef,
5735 enable_if_t <
5736 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5737 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5738 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5739 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5740 typename BasicJsonType::boolean_t >::value))
5741 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5742inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5743{
5744 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5745}
5746
5747template<typename BasicJsonType, typename CompatibleString,
5748 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5749inline void to_json(BasicJsonType& j, const CompatibleString& s)
5750{
5752}
5753
5754template<typename BasicJsonType>
5755inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5756{
5758}
5759
5760template<typename BasicJsonType, typename FloatType,
5761 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5762inline void to_json(BasicJsonType& j, FloatType val) noexcept
5763{
5764 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5765}
5766
5767template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5768 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5769inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5770{
5771 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5772}
5773
5774template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5775 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5776inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5777{
5778 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5779}
5780
5781#if !JSON_DISABLE_ENUM_SERIALIZATION
5782template<typename BasicJsonType, typename EnumType,
5783 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5784inline void to_json(BasicJsonType& j, EnumType e) noexcept
5785{
5786 using underlying_type = typename std::underlying_type<EnumType>::type;
5787 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
5788 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
5789}
5790#endif // JSON_DISABLE_ENUM_SERIALIZATION
5791
5792template<typename BasicJsonType>
5793inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5794{
5796}
5797
5798template < typename BasicJsonType, typename CompatibleArrayType,
5799 enable_if_t < is_compatible_array_type<BasicJsonType,
5800 CompatibleArrayType>::value&&
5801 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
5803 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
5804 !is_basic_json<CompatibleArrayType>::value,
5805 int > = 0 >
5806inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
5807{
5809}
5810
5811template<typename BasicJsonType>
5812inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
5813{
5815}
5816
5817template<typename BasicJsonType, typename T,
5818 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5819inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
5820{
5822}
5823
5824template<typename BasicJsonType>
5825inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5826{
5828}
5829
5830template < typename BasicJsonType, typename CompatibleObjectType,
5831 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
5832inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
5833{
5835}
5836
5837template<typename BasicJsonType>
5838inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5839{
5841}
5842
5843template <
5844 typename BasicJsonType, typename T, std::size_t N,
5845 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
5846 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5847 int > = 0 >
5848inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5849{
5851}
5852
5853template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
5854inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
5855{
5856 j = { p.first, p.second };
5857}
5858
5859// for https://github.com/nlohmann/json/pull/1134
5860template<typename BasicJsonType, typename T,
5861 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
5862inline void to_json(BasicJsonType& j, const T& b)
5863{
5864 j = { {b.key(), b.value()} };
5865}
5866
5867template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
5868inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
5869{
5870 j = { std::get<Idx>(t)... };
5871}
5872
5873template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
5874inline void to_json(BasicJsonType& j, const T& t)
5875{
5876 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5877}
5878
5879#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5880template<typename BasicJsonType>
5881inline void to_json(BasicJsonType& j, const std_fs::path& p)
5882{
5883 j = p.string();
5884}
5885#endif
5886
5888{
5889 template<typename BasicJsonType, typename T>
5890 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
5891 -> decltype(to_json(j, std::forward<T>(val)), void())
5892 {
5893 return to_json(j, std::forward<T>(val));
5894 }
5895};
5896} // namespace detail
5897
5898#ifndef JSON_HAS_CPP_17
5902namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5903{
5904#endif
5905JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
5907#ifndef JSON_HAS_CPP_17
5908} // namespace
5909#endif
5910
5912
5913// #include <nlohmann/detail/meta/identity_tag.hpp>
5914
5915
5917
5919template<typename ValueType, typename>
5921{
5924 template<typename BasicJsonType, typename TargetType = ValueType>
5925 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
5926 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5927 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
5928 {
5929 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5930 }
5931
5934 template<typename BasicJsonType, typename TargetType = ValueType>
5935 static auto from_json(BasicJsonType && j) noexcept(
5936 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
5937 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
5938 {
5939 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
5940 }
5941
5944 template<typename BasicJsonType, typename TargetType = ValueType>
5945 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
5946 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5947 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
5948 {
5949 ::nlohmann::to_json(j, std::forward<TargetType>(val));
5950 }
5951};
5952
5954
5955// #include <nlohmann/byte_container_with_subtype.hpp>
5956// __ _____ _____ _____
5957// __| | __| | | | JSON for Modern C++
5958// | | |__ | | | | | | version 3.11.3
5959// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5960//
5961// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5962// SPDX-License-Identifier: MIT
5963
5964
5965
5966#include <cstdint> // uint8_t, uint64_t
5967#include <tuple> // tie
5968#include <utility> // move
5969
5970// #include <nlohmann/detail/abi_macros.hpp>
5971
5972
5974
5977template<typename BinaryType>
5978class byte_container_with_subtype : public BinaryType
5979{
5980 public:
5981 using container_type = BinaryType;
5982 using subtype_type = std::uint64_t;
5983
5986 : container_type()
5987 {}
5988
5991 : container_type(b)
5992 {}
5993
5995 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
5996 : container_type(std::move(b))
5997 {}
5998
6001 : container_type(b)
6002 , m_subtype(subtype_)
6003 , m_has_subtype(true)
6004 {}
6005
6007 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
6008 : container_type(std::move(b))
6009 , m_subtype(subtype_)
6010 , m_has_subtype(true)
6011 {}
6012
6014 {
6015 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
6016 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
6017 }
6018
6020 {
6021 return !(rhs == *this);
6022 }
6023
6026 void set_subtype(subtype_type subtype_) noexcept
6027 {
6028 m_subtype = subtype_;
6029 m_has_subtype = true;
6030 }
6031
6034 constexpr subtype_type subtype() const noexcept
6035 {
6036 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
6037 }
6038
6041 constexpr bool has_subtype() const noexcept
6042 {
6043 return m_has_subtype;
6044 }
6045
6048 void clear_subtype() noexcept
6049 {
6050 m_subtype = 0;
6051 m_has_subtype = false;
6052 }
6053
6054 private:
6055 subtype_type m_subtype = 0;
6056 bool m_has_subtype = false;
6057};
6058
6060
6061// #include <nlohmann/detail/conversions/from_json.hpp>
6062
6063// #include <nlohmann/detail/conversions/to_json.hpp>
6064
6065// #include <nlohmann/detail/exceptions.hpp>
6066
6067// #include <nlohmann/detail/hash.hpp>
6068// __ _____ _____ _____
6069// __| | __| | | | JSON for Modern C++
6070// | | |__ | | | | | | version 3.11.3
6071// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6072//
6073// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6074// SPDX-License-Identifier: MIT
6075
6076
6077
6078#include <cstdint> // uint8_t
6079#include <cstddef> // size_t
6080#include <functional> // hash
6081
6082// #include <nlohmann/detail/abi_macros.hpp>
6083
6084// #include <nlohmann/detail/value_t.hpp>
6085
6086
6088namespace detail
6089{
6090
6091// boost::hash_combine
6092inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6093{
6094 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6095 return seed;
6096}
6097
6109template<typename BasicJsonType>
6110std::size_t hash(const BasicJsonType& j)
6111{
6112 using string_t = typename BasicJsonType::string_t;
6113 using number_integer_t = typename BasicJsonType::number_integer_t;
6114 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6115 using number_float_t = typename BasicJsonType::number_float_t;
6116
6117 const auto type = static_cast<std::size_t>(j.type());
6118 switch (j.type())
6119 {
6120 case BasicJsonType::value_t::null:
6121 case BasicJsonType::value_t::discarded:
6122 {
6123 return combine(type, 0);
6124 }
6125
6126 case BasicJsonType::value_t::object:
6127 {
6128 auto seed = combine(type, j.size());
6129 for (const auto& element : j.items())
6130 {
6131 const auto h = std::hash<string_t> {}(element.key());
6132 seed = combine(seed, h);
6133 seed = combine(seed, hash(element.value()));
6134 }
6135 return seed;
6136 }
6137
6138 case BasicJsonType::value_t::array:
6139 {
6140 auto seed = combine(type, j.size());
6141 for (const auto& element : j)
6142 {
6143 seed = combine(seed, hash(element));
6144 }
6145 return seed;
6146 }
6147
6148 case BasicJsonType::value_t::string:
6149 {
6150 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6151 return combine(type, h);
6152 }
6153
6154 case BasicJsonType::value_t::boolean:
6155 {
6156 const auto h = std::hash<bool> {}(j.template get<bool>());
6157 return combine(type, h);
6158 }
6159
6160 case BasicJsonType::value_t::number_integer:
6161 {
6162 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6163 return combine(type, h);
6164 }
6165
6166 case BasicJsonType::value_t::number_unsigned:
6167 {
6168 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6169 return combine(type, h);
6170 }
6171
6172 case BasicJsonType::value_t::number_float:
6173 {
6174 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6175 return combine(type, h);
6176 }
6177
6178 case BasicJsonType::value_t::binary:
6179 {
6180 auto seed = combine(type, j.get_binary().size());
6181 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6182 seed = combine(seed, h);
6183 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6184 for (const auto byte : j.get_binary())
6185 {
6186 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6187 }
6188 return seed;
6189 }
6190
6191 default: // LCOV_EXCL_LINE
6192 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6193 return 0; // LCOV_EXCL_LINE
6194 }
6195}
6196
6197} // namespace detail
6199
6200// #include <nlohmann/detail/input/binary_reader.hpp>
6201// __ _____ _____ _____
6202// __| | __| | | | JSON for Modern C++
6203// | | |__ | | | | | | version 3.11.3
6204// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6205//
6206// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6207// SPDX-License-Identifier: MIT
6208
6209
6210
6211#include <algorithm> // generate_n
6212#include <array> // array
6213#include <cmath> // ldexp
6214#include <cstddef> // size_t
6215#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6216#include <cstdio> // snprintf
6217#include <cstring> // memcpy
6218#include <iterator> // back_inserter
6219#include <limits> // numeric_limits
6220#include <string> // char_traits, string
6221#include <utility> // make_pair, move
6222#include <vector> // vector
6223
6224// #include <nlohmann/detail/exceptions.hpp>
6225
6226// #include <nlohmann/detail/input/input_adapters.hpp>
6227// __ _____ _____ _____
6228// __| | __| | | | JSON for Modern C++
6229// | | |__ | | | | | | version 3.11.3
6230// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6231//
6232// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6233// SPDX-License-Identifier: MIT
6234
6235
6236
6237#include <array> // array
6238#include <cstddef> // size_t
6239#include <cstring> // strlen
6240#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6241#include <memory> // shared_ptr, make_shared, addressof
6242#include <numeric> // accumulate
6243#include <string> // string, char_traits
6244#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6245#include <utility> // pair, declval
6246
6247#ifndef JSON_NO_IO
6248 #include <cstdio> // FILE *
6249 #include <istream> // istream
6250#endif // JSON_NO_IO
6251
6252// #include <nlohmann/detail/exceptions.hpp>
6253
6254// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6255
6256// #include <nlohmann/detail/macro_scope.hpp>
6257
6258// #include <nlohmann/detail/meta/type_traits.hpp>
6259
6260
6262namespace detail
6263{
6264
6267
6269// input adapters //
6271
6272#ifndef JSON_NO_IO
6278{
6279 public:
6280 using char_type = char;
6281
6283 explicit file_input_adapter(std::FILE* f) noexcept
6284 : m_file(f)
6285 {
6286 JSON_ASSERT(m_file != nullptr);
6287 }
6288
6289 // make class move-only
6292 file_input_adapter& operator=(const file_input_adapter&) = delete;
6295
6296 std::char_traits<char>::int_type get_character() noexcept
6297 {
6298 return std::fgetc(m_file);
6299 }
6300
6301 private:
6303 std::FILE* m_file;
6304};
6305
6316{
6317 public:
6318 using char_type = char;
6319
6321 {
6322 // clear stream flags; we use underlying streambuf I/O, do not
6323 // maintain ifstream flags, except eof
6324 if (is != nullptr)
6325 {
6326 is->clear(is->rdstate() & std::ios::eofbit);
6327 }
6328 }
6329
6330 explicit input_stream_adapter(std::istream& i)
6331 : is(&i), sb(i.rdbuf())
6332 {}
6333
6334 // delete because of pointer members
6338
6340 : is(rhs.is), sb(rhs.sb)
6341 {
6342 rhs.is = nullptr;
6343 rhs.sb = nullptr;
6344 }
6345
6346 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6347 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6348 // end up as the same value, e.g. 0xFFFFFFFF.
6349 std::char_traits<char>::int_type get_character()
6350 {
6351 auto res = sb->sbumpc();
6352 // set eof manually, as we don't use the istream interface.
6353 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6354 {
6355 is->clear(is->rdstate() | std::ios::eofbit);
6356 }
6357 return res;
6358 }
6359
6360 private:
6362 std::istream* is = nullptr;
6363 std::streambuf* sb = nullptr;
6364};
6365#endif // JSON_NO_IO
6366
6367// General-purpose iterator-based adapter. It might not be as fast as
6368// theoretically possible for some containers, but it is extremely versatile.
6369template<typename IteratorType>
6371{
6372 public:
6373 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6374
6375 iterator_input_adapter(IteratorType first, IteratorType last)
6376 : current(std::move(first)), end(std::move(last))
6377 {}
6378
6380 {
6381 if (JSON_HEDLEY_LIKELY(current != end))
6382 {
6383 auto result = char_traits<char_type>::to_int_type(*current);
6384 std::advance(current, 1);
6385 return result;
6386 }
6387
6389 }
6390
6391 private:
6392 IteratorType current;
6393 IteratorType end;
6394
6395 template<typename BaseInputAdapter, size_t T>
6397
6398 bool empty() const
6399 {
6400 return current == end;
6401 }
6402};
6403
6404template<typename BaseInputAdapter, size_t T>
6406
6407template<typename BaseInputAdapter>
6408struct wide_string_input_helper<BaseInputAdapter, 4>
6409{
6410 // UTF-32
6411 static void fill_buffer(BaseInputAdapter& input,
6412 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6413 size_t& utf8_bytes_index,
6414 size_t& utf8_bytes_filled)
6415 {
6416 utf8_bytes_index = 0;
6417
6418 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6419 {
6420 utf8_bytes[0] = std::char_traits<char>::eof();
6421 utf8_bytes_filled = 1;
6422 }
6423 else
6424 {
6425 // get the current character
6426 const auto wc = input.get_character();
6427
6428 // UTF-32 to UTF-8 encoding
6429 if (wc < 0x80)
6430 {
6431 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6432 utf8_bytes_filled = 1;
6433 }
6434 else if (wc <= 0x7FF)
6435 {
6436 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6437 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6438 utf8_bytes_filled = 2;
6439 }
6440 else if (wc <= 0xFFFF)
6441 {
6442 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6443 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6444 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6445 utf8_bytes_filled = 3;
6446 }
6447 else if (wc <= 0x10FFFF)
6448 {
6449 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6450 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6451 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6452 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6453 utf8_bytes_filled = 4;
6454 }
6455 else
6456 {
6457 // unknown character
6458 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6459 utf8_bytes_filled = 1;
6460 }
6461 }
6462 }
6463};
6464
6465template<typename BaseInputAdapter>
6466struct wide_string_input_helper<BaseInputAdapter, 2>
6467{
6468 // UTF-16
6469 static void fill_buffer(BaseInputAdapter& input,
6470 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6471 size_t& utf8_bytes_index,
6472 size_t& utf8_bytes_filled)
6473 {
6474 utf8_bytes_index = 0;
6475
6476 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6477 {
6478 utf8_bytes[0] = std::char_traits<char>::eof();
6479 utf8_bytes_filled = 1;
6480 }
6481 else
6482 {
6483 // get the current character
6484 const auto wc = input.get_character();
6485
6486 // UTF-16 to UTF-8 encoding
6487 if (wc < 0x80)
6488 {
6489 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6490 utf8_bytes_filled = 1;
6491 }
6492 else if (wc <= 0x7FF)
6493 {
6494 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6495 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6496 utf8_bytes_filled = 2;
6497 }
6498 else if (0xD800 > wc || wc >= 0xE000)
6499 {
6500 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6501 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6502 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6503 utf8_bytes_filled = 3;
6504 }
6505 else
6506 {
6507 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6508 {
6509 const auto wc2 = static_cast<unsigned int>(input.get_character());
6510 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6511 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6512 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6513 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6514 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6515 utf8_bytes_filled = 4;
6516 }
6517 else
6518 {
6519 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6520 utf8_bytes_filled = 1;
6521 }
6522 }
6523 }
6524 }
6525};
6526
6527// Wraps another input adapter to convert wide character types into individual bytes.
6528template<typename BaseInputAdapter, typename WideCharType>
6530{
6531 public:
6532 using char_type = char;
6533
6534 wide_string_input_adapter(BaseInputAdapter base)
6535 : base_adapter(base) {}
6536
6537 typename std::char_traits<char>::int_type get_character() noexcept
6538 {
6539 // check if buffer needs to be filled
6540 if (utf8_bytes_index == utf8_bytes_filled)
6541 {
6542 fill_buffer<sizeof(WideCharType)>();
6543
6544 JSON_ASSERT(utf8_bytes_filled > 0);
6545 JSON_ASSERT(utf8_bytes_index == 0);
6546 }
6547
6548 // use buffer
6549 JSON_ASSERT(utf8_bytes_filled > 0);
6550 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6551 return utf8_bytes[utf8_bytes_index++];
6552 }
6553
6554 private:
6555 BaseInputAdapter base_adapter;
6556
6557 template<size_t T>
6558 void fill_buffer()
6559 {
6560 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6561 }
6562
6564 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6565
6567 std::size_t utf8_bytes_index = 0;
6569 std::size_t utf8_bytes_filled = 0;
6570};
6571
6572template<typename IteratorType, typename Enable = void>
6574{
6575 using iterator_type = IteratorType;
6576 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6578
6579 static adapter_type create(IteratorType first, IteratorType last)
6580 {
6581 return adapter_type(std::move(first), std::move(last));
6582 }
6583};
6584
6585template<typename T>
6587{
6588 using value_type = typename std::iterator_traits<T>::value_type;
6589 enum
6590 {
6591 value = sizeof(value_type) > 1
6592 };
6593};
6594
6595template<typename IteratorType>
6597{
6598 using iterator_type = IteratorType;
6599 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6602
6603 static adapter_type create(IteratorType first, IteratorType last)
6604 {
6605 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6606 }
6607};
6608
6609// General purpose iterator-based input
6610template<typename IteratorType>
6612{
6614 return factory_type::create(first, last);
6615}
6616
6617// Convenience shorthand from container to iterator
6618// Enables ADL on begin(container) and end(container)
6619// Encloses the using declarations in namespace for not to leak them to outside scope
6620
6621namespace container_input_adapter_factory_impl
6622{
6623
6624using std::begin;
6625using std::end;
6626
6627template<typename ContainerType, typename Enable = void>
6629
6630template<typename ContainerType>
6632 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6633 {
6634 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6635
6636 static adapter_type create(const ContainerType& container)
6637{
6638 return input_adapter(begin(container), end(container));
6639}
6640 };
6641
6642} // namespace container_input_adapter_factory_impl
6643
6644template<typename ContainerType>
6646{
6648}
6649
6650#ifndef JSON_NO_IO
6651// Special cases with fast paths
6652inline file_input_adapter input_adapter(std::FILE* file)
6653{
6654 if (file == nullptr)
6655 {
6656 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));
6657 }
6658 return file_input_adapter(file);
6659}
6660
6661inline input_stream_adapter input_adapter(std::istream& stream)
6662{
6663 return input_stream_adapter(stream);
6664}
6665
6666inline input_stream_adapter input_adapter(std::istream&& stream)
6667{
6668 return input_stream_adapter(stream);
6669}
6670#endif // JSON_NO_IO
6671
6672using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6673
6674// Null-delimited strings, and the like.
6675template < typename CharT,
6676 typename std::enable_if <
6677 std::is_pointer<CharT>::value&&
6678 !std::is_array<CharT>::value&&
6679 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6680 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6681 int >::type = 0 >
6683{
6684 if (b == nullptr)
6685 {
6686 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));
6687 }
6688 auto length = std::strlen(reinterpret_cast<const char*>(b));
6689 const auto* ptr = reinterpret_cast<const char*>(b);
6690 return input_adapter(ptr, ptr + length);
6691}
6692
6693template<typename T, std::size_t N>
6694auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6695{
6696 return input_adapter(array, array + N);
6697}
6698
6699// This class only handles inputs of input_buffer_adapter type.
6700// It's required so that expressions like {ptr, len} can be implicitly cast
6701// to the correct adapter.
6703{
6704 public:
6705 template < typename CharT,
6706 typename std::enable_if <
6707 std::is_pointer<CharT>::value&&
6708 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6709 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6710 int >::type = 0 >
6711 span_input_adapter(CharT b, std::size_t l)
6712 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6713
6714 template<class IteratorType,
6715 typename std::enable_if<
6716 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6717 int>::type = 0>
6718 span_input_adapter(IteratorType first, IteratorType last)
6719 : ia(input_adapter(first, last)) {}
6720
6722 {
6723 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6724 }
6725
6726 private:
6728};
6729
6730} // namespace detail
6732
6733// #include <nlohmann/detail/input/json_sax.hpp>
6734// __ _____ _____ _____
6735// __| | __| | | | JSON for Modern C++
6736// | | |__ | | | | | | version 3.11.3
6737// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6738//
6739// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6740// SPDX-License-Identifier: MIT
6741
6742
6743
6744#include <cstddef>
6745#include <string> // string
6746#include <utility> // move
6747#include <vector> // vector
6748
6749// #include <nlohmann/detail/exceptions.hpp>
6750
6751// #include <nlohmann/detail/macro_scope.hpp>
6752
6753// #include <nlohmann/detail/string_concat.hpp>
6754
6755
6757
6766template<typename BasicJsonType>
6768{
6769 using number_integer_t = typename BasicJsonType::number_integer_t;
6770 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6771 using number_float_t = typename BasicJsonType::number_float_t;
6772 using string_t = typename BasicJsonType::string_t;
6773 using binary_t = typename BasicJsonType::binary_t;
6774
6779 virtual bool null() = 0;
6780
6786 virtual bool boolean(bool val) = 0;
6787
6793 virtual bool number_integer(number_integer_t val) = 0;
6794
6800 virtual bool number_unsigned(number_unsigned_t val) = 0;
6801
6808 virtual bool number_float(number_float_t val, const string_t& s) = 0;
6809
6816 virtual bool string(string_t& val) = 0;
6817
6824 virtual bool binary(binary_t& val) = 0;
6825
6832 virtual bool start_object(std::size_t elements) = 0;
6833
6840 virtual bool key(string_t& val) = 0;
6841
6846 virtual bool end_object() = 0;
6847
6854 virtual bool start_array(std::size_t elements) = 0;
6855
6860 virtual bool end_array() = 0;
6861
6869 virtual bool parse_error(std::size_t position,
6870 const std::string& last_token,
6871 const detail::exception& ex) = 0;
6872
6873 json_sax() = default;
6874 json_sax(const json_sax&) = default;
6875 json_sax(json_sax&&) noexcept = default;
6876 json_sax& operator=(const json_sax&) = default;
6877 json_sax& operator=(json_sax&&) noexcept = default;
6878 virtual ~json_sax() = default;
6879};
6880
6881namespace detail
6882{
6896template<typename BasicJsonType>
6898{
6899 public:
6900 using number_integer_t = typename BasicJsonType::number_integer_t;
6901 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6902 using number_float_t = typename BasicJsonType::number_float_t;
6903 using string_t = typename BasicJsonType::string_t;
6904 using binary_t = typename BasicJsonType::binary_t;
6905
6911 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
6912 : root(r), allow_exceptions(allow_exceptions_)
6913 {}
6914
6915 // make class move-only
6917 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6919 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6921
6922 bool null()
6923 {
6924 handle_value(nullptr);
6925 return true;
6926 }
6927
6928 bool boolean(bool val)
6929 {
6930 handle_value(val);
6931 return true;
6932 }
6933
6935 {
6936 handle_value(val);
6937 return true;
6938 }
6939
6941 {
6942 handle_value(val);
6943 return true;
6944 }
6945
6946 bool number_float(number_float_t val, const string_t& /*unused*/)
6947 {
6948 handle_value(val);
6949 return true;
6950 }
6951
6952 bool string(string_t& val)
6953 {
6954 handle_value(val);
6955 return true;
6956 }
6957
6958 bool binary(binary_t& val)
6959 {
6960 handle_value(std::move(val));
6961 return true;
6962 }
6963
6964 bool start_object(std::size_t len)
6965 {
6966 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
6967
6968 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6969 {
6970 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6971 }
6972
6973 return true;
6974 }
6975
6976 bool key(string_t& val)
6977 {
6978 JSON_ASSERT(!ref_stack.empty());
6979 JSON_ASSERT(ref_stack.back()->is_object());
6980
6981 // add null at given key and store the reference for later
6982 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
6983 return true;
6984 }
6985
6987 {
6988 JSON_ASSERT(!ref_stack.empty());
6989 JSON_ASSERT(ref_stack.back()->is_object());
6990
6991 ref_stack.back()->set_parents();
6992 ref_stack.pop_back();
6993 return true;
6994 }
6995
6996 bool start_array(std::size_t len)
6997 {
6998 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
6999
7000 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7001 {
7002 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
7003 }
7004
7005 return true;
7006 }
7007
7009 {
7010 JSON_ASSERT(!ref_stack.empty());
7011 JSON_ASSERT(ref_stack.back()->is_array());
7012
7013 ref_stack.back()->set_parents();
7014 ref_stack.pop_back();
7015 return true;
7016 }
7017
7018 template<class Exception>
7019 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7020 const Exception& ex)
7021 {
7022 errored = true;
7023 static_cast<void>(ex);
7024 if (allow_exceptions)
7025 {
7026 JSON_THROW(ex);
7027 }
7028 return false;
7029 }
7030
7031 constexpr bool is_errored() const
7032 {
7033 return errored;
7034 }
7035
7036 private:
7043 template<typename Value>
7045 BasicJsonType* handle_value(Value&& v)
7046 {
7047 if (ref_stack.empty())
7048 {
7049 root = BasicJsonType(std::forward<Value>(v));
7050 return &root;
7051 }
7052
7053 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7054
7055 if (ref_stack.back()->is_array())
7056 {
7057 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
7058 return &(ref_stack.back()->m_data.m_value.array->back());
7059 }
7060
7061 JSON_ASSERT(ref_stack.back()->is_object());
7062 JSON_ASSERT(object_element);
7063 *object_element = BasicJsonType(std::forward<Value>(v));
7064 return object_element;
7065 }
7066
7068 BasicJsonType& root;
7070 std::vector<BasicJsonType*> ref_stack {};
7072 BasicJsonType* object_element = nullptr;
7074 bool errored = false;
7076 const bool allow_exceptions = true;
7077};
7078
7079template<typename BasicJsonType>
7081{
7082 public:
7083 using number_integer_t = typename BasicJsonType::number_integer_t;
7084 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7085 using number_float_t = typename BasicJsonType::number_float_t;
7086 using string_t = typename BasicJsonType::string_t;
7087 using binary_t = typename BasicJsonType::binary_t;
7088 using parser_callback_t = typename BasicJsonType::parser_callback_t;
7089 using parse_event_t = typename BasicJsonType::parse_event_t;
7090
7093 const bool allow_exceptions_ = true)
7094 : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_)
7095 {
7096 keep_stack.push_back(true);
7097 }
7098
7099 // make class move-only
7101 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7103 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7105
7106 bool null()
7107 {
7108 handle_value(nullptr);
7109 return true;
7110 }
7111
7112 bool boolean(bool val)
7113 {
7114 handle_value(val);
7115 return true;
7116 }
7117
7119 {
7120 handle_value(val);
7121 return true;
7122 }
7123
7125 {
7126 handle_value(val);
7127 return true;
7128 }
7129
7130 bool number_float(number_float_t val, const string_t& /*unused*/)
7131 {
7132 handle_value(val);
7133 return true;
7134 }
7135
7136 bool string(string_t& val)
7137 {
7138 handle_value(val);
7139 return true;
7140 }
7141
7142 bool binary(binary_t& val)
7143 {
7144 handle_value(std::move(val));
7145 return true;
7146 }
7147
7148 bool start_object(std::size_t len)
7149 {
7150 // check callback for object start
7151 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
7152 keep_stack.push_back(keep);
7153
7154 auto val = handle_value(BasicJsonType::value_t::object, true);
7155 ref_stack.push_back(val.second);
7156
7157 // check object limit
7158 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7159 {
7160 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
7161 }
7162
7163 return true;
7164 }
7165
7166 bool key(string_t& val)
7167 {
7168 BasicJsonType k = BasicJsonType(val);
7169
7170 // check callback for key
7171 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
7172 key_keep_stack.push_back(keep);
7173
7174 // add discarded value at given key and store the reference for later
7175 if (keep && ref_stack.back())
7176 {
7177 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
7178 }
7179
7180 return true;
7181 }
7182
7184 {
7185 if (ref_stack.back())
7186 {
7187 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
7188 {
7189 // discard object
7190 *ref_stack.back() = discarded;
7191 }
7192 else
7193 {
7194 ref_stack.back()->set_parents();
7195 }
7196 }
7197
7198 JSON_ASSERT(!ref_stack.empty());
7199 JSON_ASSERT(!keep_stack.empty());
7200 ref_stack.pop_back();
7201 keep_stack.pop_back();
7202
7203 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
7204 {
7205 // remove discarded value
7206 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
7207 {
7208 if (it->is_discarded())
7209 {
7210 ref_stack.back()->erase(it);
7211 break;
7212 }
7213 }
7214 }
7215
7216 return true;
7217 }
7218
7219 bool start_array(std::size_t len)
7220 {
7221 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
7222 keep_stack.push_back(keep);
7223
7224 auto val = handle_value(BasicJsonType::value_t::array, true);
7225 ref_stack.push_back(val.second);
7226
7227 // check array limit
7228 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7229 {
7230 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
7231 }
7232
7233 return true;
7234 }
7235
7237 {
7238 bool keep = true;
7239
7240 if (ref_stack.back())
7241 {
7242 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
7243 if (keep)
7244 {
7245 ref_stack.back()->set_parents();
7246 }
7247 else
7248 {
7249 // discard array
7250 *ref_stack.back() = discarded;
7251 }
7252 }
7253
7254 JSON_ASSERT(!ref_stack.empty());
7255 JSON_ASSERT(!keep_stack.empty());
7256 ref_stack.pop_back();
7257 keep_stack.pop_back();
7258
7259 // remove discarded value
7260 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
7261 {
7262 ref_stack.back()->m_data.m_value.array->pop_back();
7263 }
7264
7265 return true;
7266 }
7267
7268 template<class Exception>
7269 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7270 const Exception& ex)
7271 {
7272 errored = true;
7273 static_cast<void>(ex);
7274 if (allow_exceptions)
7275 {
7276 JSON_THROW(ex);
7277 }
7278 return false;
7279 }
7280
7281 constexpr bool is_errored() const
7282 {
7283 return errored;
7284 }
7285
7286 private:
7302 template<typename Value>
7303 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
7304 {
7305 JSON_ASSERT(!keep_stack.empty());
7306
7307 // do not handle this value if we know it would be added to a discarded
7308 // container
7309 if (!keep_stack.back())
7310 {
7311 return {false, nullptr};
7312 }
7313
7314 // create value
7315 auto value = BasicJsonType(std::forward<Value>(v));
7316
7317 // check callback
7318 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
7319
7320 // do not handle this value if we just learnt it shall be discarded
7321 if (!keep)
7322 {
7323 return {false, nullptr};
7324 }
7325
7326 if (ref_stack.empty())
7327 {
7328 root = std::move(value);
7329 return {true, & root};
7330 }
7331
7332 // skip this value if we already decided to skip the parent
7333 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
7334 if (!ref_stack.back())
7335 {
7336 return {false, nullptr};
7337 }
7338
7339 // we now only expect arrays and objects
7340 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7341
7342 // array
7343 if (ref_stack.back()->is_array())
7344 {
7345 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
7346 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
7347 }
7348
7349 // object
7350 JSON_ASSERT(ref_stack.back()->is_object());
7351 // check if we should store an element for the current key
7352 JSON_ASSERT(!key_keep_stack.empty());
7353 const bool store_element = key_keep_stack.back();
7354 key_keep_stack.pop_back();
7355
7356 if (!store_element)
7357 {
7358 return {false, nullptr};
7359 }
7360
7361 JSON_ASSERT(object_element);
7362 *object_element = std::move(value);
7363 return {true, object_element};
7364 }
7365
7367 BasicJsonType& root;
7369 std::vector<BasicJsonType*> ref_stack {};
7371 std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
7373 std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
7375 BasicJsonType* object_element = nullptr;
7377 bool errored = false;
7379 const parser_callback_t callback = nullptr;
7381 const bool allow_exceptions = true;
7383 BasicJsonType discarded = BasicJsonType::value_t::discarded;
7384};
7385
7386template<typename BasicJsonType>
7388{
7389 public:
7390 using number_integer_t = typename BasicJsonType::number_integer_t;
7391 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7392 using number_float_t = typename BasicJsonType::number_float_t;
7393 using string_t = typename BasicJsonType::string_t;
7394 using binary_t = typename BasicJsonType::binary_t;
7395
7396 bool null()
7397 {
7398 return true;
7399 }
7400
7401 bool boolean(bool /*unused*/)
7402 {
7403 return true;
7404 }
7405
7407 {
7408 return true;
7409 }
7410
7412 {
7413 return true;
7414 }
7415
7416 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
7417 {
7418 return true;
7419 }
7420
7421 bool string(string_t& /*unused*/)
7422 {
7423 return true;
7424 }
7425
7426 bool binary(binary_t& /*unused*/)
7427 {
7428 return true;
7429 }
7430
7431 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7432 {
7433 return true;
7434 }
7435
7436 bool key(string_t& /*unused*/)
7437 {
7438 return true;
7439 }
7440
7442 {
7443 return true;
7444 }
7445
7446 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7447 {
7448 return true;
7449 }
7450
7452 {
7453 return true;
7454 }
7455
7456 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
7457 {
7458 return false;
7459 }
7460};
7461
7462} // namespace detail
7464
7465// #include <nlohmann/detail/input/lexer.hpp>
7466// __ _____ _____ _____
7467// __| | __| | | | JSON for Modern C++
7468// | | |__ | | | | | | version 3.11.3
7469// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7470//
7471// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
7472// SPDX-License-Identifier: MIT
7473
7474
7475
7476#include <array> // array
7477#include <clocale> // localeconv
7478#include <cstddef> // size_t
7479#include <cstdio> // snprintf
7480#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7481#include <initializer_list> // initializer_list
7482#include <string> // char_traits, string
7483#include <utility> // move
7484#include <vector> // vector
7485
7486// #include <nlohmann/detail/input/input_adapters.hpp>
7487
7488// #include <nlohmann/detail/input/position_t.hpp>
7489
7490// #include <nlohmann/detail/macro_scope.hpp>
7491
7492// #include <nlohmann/detail/meta/type_traits.hpp>
7493
7494
7496namespace detail
7497{
7498
7500// lexer //
7502
7503template<typename BasicJsonType>
7505{
7506 public:
7508 enum class token_type
7509 {
7510 uninitialized,
7511 literal_true,
7512 literal_false,
7513 literal_null,
7514 value_string,
7515 value_unsigned,
7516 value_integer,
7517 value_float,
7518 begin_array,
7519 begin_object,
7520 end_array,
7521 end_object,
7522 name_separator,
7523 value_separator,
7524 parse_error,
7525 end_of_input,
7526 literal_or_value
7527 };
7528
7532 static const char* token_type_name(const token_type t) noexcept
7533 {
7534 switch (t)
7535 {
7536 case token_type::uninitialized:
7537 return "<uninitialized>";
7538 case token_type::literal_true:
7539 return "true literal";
7540 case token_type::literal_false:
7541 return "false literal";
7542 case token_type::literal_null:
7543 return "null literal";
7544 case token_type::value_string:
7545 return "string literal";
7546 case token_type::value_unsigned:
7547 case token_type::value_integer:
7548 case token_type::value_float:
7549 return "number literal";
7550 case token_type::begin_array:
7551 return "'['";
7552 case token_type::begin_object:
7553 return "'{'";
7554 case token_type::end_array:
7555 return "']'";
7556 case token_type::end_object:
7557 return "'}'";
7558 case token_type::name_separator:
7559 return "':'";
7560 case token_type::value_separator:
7561 return "','";
7562 case token_type::parse_error:
7563 return "<parse error>";
7564 case token_type::end_of_input:
7565 return "end of input";
7566 case token_type::literal_or_value:
7567 return "'[', '{', or a literal";
7568 // LCOV_EXCL_START
7569 default: // catch non-enum values
7570 return "unknown token";
7571 // LCOV_EXCL_STOP
7572 }
7573 }
7574};
7580template<typename BasicJsonType, typename InputAdapterType>
7581class lexer : public lexer_base<BasicJsonType>
7582{
7583 using number_integer_t = typename BasicJsonType::number_integer_t;
7584 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7585 using number_float_t = typename BasicJsonType::number_float_t;
7586 using string_t = typename BasicJsonType::string_t;
7587 using char_type = typename InputAdapterType::char_type;
7588 using char_int_type = typename char_traits<char_type>::int_type;
7589
7590 public:
7592
7593 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7594 : ia(std::move(adapter))
7595 , ignore_comments(ignore_comments_)
7596 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7597 {}
7598
7599 // delete because of pointer members
7600 lexer(const lexer&) = delete;
7601 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7602 lexer& operator=(lexer&) = delete;
7603 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7604 ~lexer() = default;
7605
7606 private:
7608 // locales
7610
7613 static char get_decimal_point() noexcept
7614 {
7615 const auto* loc = localeconv();
7616 JSON_ASSERT(loc != nullptr);
7617 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7618 }
7619
7621 // scan functions
7623
7639 int get_codepoint()
7640 {
7641 // this function only makes sense after reading `\u`
7642 JSON_ASSERT(current == 'u');
7643 int codepoint = 0;
7644
7645 const auto factors = { 12u, 8u, 4u, 0u };
7646 for (const auto factor : factors)
7647 {
7648 get();
7649
7650 if (current >= '0' && current <= '9')
7651 {
7652 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7653 }
7654 else if (current >= 'A' && current <= 'F')
7655 {
7656 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7657 }
7658 else if (current >= 'a' && current <= 'f')
7659 {
7660 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7661 }
7662 else
7663 {
7664 return -1;
7665 }
7666 }
7667
7668 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7669 return codepoint;
7670 }
7671
7687 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7688 {
7689 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7690 add(current);
7691
7692 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7693 {
7694 get();
7695 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7696 {
7697 add(current);
7698 }
7699 else
7700 {
7701 error_message = "invalid string: ill-formed UTF-8 byte";
7702 return false;
7703 }
7704 }
7705
7706 return true;
7707 }
7708
7724 token_type scan_string()
7725 {
7726 // reset token_buffer (ignore opening quote)
7727 reset();
7728
7729 // we entered the function by reading an open quote
7730 JSON_ASSERT(current == '\"');
7731
7732 while (true)
7733 {
7734 // get next character
7735 switch (get())
7736 {
7737 // end of file while parsing string
7738 case char_traits<char_type>::eof():
7739 {
7740 error_message = "invalid string: missing closing quote";
7741 return token_type::parse_error;
7742 }
7743
7744 // closing quote
7745 case '\"':
7746 {
7747 return token_type::value_string;
7748 }
7749
7750 // escapes
7751 case '\\':
7752 {
7753 switch (get())
7754 {
7755 // quotation mark
7756 case '\"':
7757 add('\"');
7758 break;
7759 // reverse solidus
7760 case '\\':
7761 add('\\');
7762 break;
7763 // solidus
7764 case '/':
7765 add('/');
7766 break;
7767 // backspace
7768 case 'b':
7769 add('\b');
7770 break;
7771 // form feed
7772 case 'f':
7773 add('\f');
7774 break;
7775 // line feed
7776 case 'n':
7777 add('\n');
7778 break;
7779 // carriage return
7780 case 'r':
7781 add('\r');
7782 break;
7783 // tab
7784 case 't':
7785 add('\t');
7786 break;
7787
7788 // unicode escapes
7789 case 'u':
7790 {
7791 const int codepoint1 = get_codepoint();
7792 int codepoint = codepoint1; // start with codepoint1
7793
7794 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7795 {
7796 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7797 return token_type::parse_error;
7798 }
7799
7800 // check if code point is a high surrogate
7801 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7802 {
7803 // expect next \uxxxx entry
7804 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7805 {
7806 const int codepoint2 = get_codepoint();
7807
7808 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7809 {
7810 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7811 return token_type::parse_error;
7812 }
7813
7814 // check if codepoint2 is a low surrogate
7815 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7816 {
7817 // overwrite codepoint
7818 codepoint = static_cast<int>(
7819 // high surrogate occupies the most significant 22 bits
7820 (static_cast<unsigned int>(codepoint1) << 10u)
7821 // low surrogate occupies the least significant 15 bits
7822 + static_cast<unsigned int>(codepoint2)
7823 // there is still the 0xD800, 0xDC00 and 0x10000 noise
7824 // in the result, so we have to subtract with:
7825 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7826 - 0x35FDC00u);
7827 }
7828 else
7829 {
7830 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7831 return token_type::parse_error;
7832 }
7833 }
7834 else
7835 {
7836 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7837 return token_type::parse_error;
7838 }
7839 }
7840 else
7841 {
7842 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7843 {
7844 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7845 return token_type::parse_error;
7846 }
7847 }
7848
7849 // result of the above calculation yields a proper codepoint
7850 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7851
7852 // translate codepoint into bytes
7853 if (codepoint < 0x80)
7854 {
7855 // 1-byte characters: 0xxxxxxx (ASCII)
7856 add(static_cast<char_int_type>(codepoint));
7857 }
7858 else if (codepoint <= 0x7FF)
7859 {
7860 // 2-byte characters: 110xxxxx 10xxxxxx
7861 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7862 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7863 }
7864 else if (codepoint <= 0xFFFF)
7865 {
7866 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7867 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7868 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7869 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7870 }
7871 else
7872 {
7873 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7874 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7875 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7876 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7877 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7878 }
7879
7880 break;
7881 }
7882
7883 // other characters after escape
7884 default:
7885 error_message = "invalid string: forbidden character after backslash";
7886 return token_type::parse_error;
7887 }
7888
7889 break;
7890 }
7891
7892 // invalid control characters
7893 case 0x00:
7894 {
7895 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7896 return token_type::parse_error;
7897 }
7898
7899 case 0x01:
7900 {
7901 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7902 return token_type::parse_error;
7903 }
7904
7905 case 0x02:
7906 {
7907 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7908 return token_type::parse_error;
7909 }
7910
7911 case 0x03:
7912 {
7913 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7914 return token_type::parse_error;
7915 }
7916
7917 case 0x04:
7918 {
7919 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7920 return token_type::parse_error;
7921 }
7922
7923 case 0x05:
7924 {
7925 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7926 return token_type::parse_error;
7927 }
7928
7929 case 0x06:
7930 {
7931 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7932 return token_type::parse_error;
7933 }
7934
7935 case 0x07:
7936 {
7937 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7938 return token_type::parse_error;
7939 }
7940
7941 case 0x08:
7942 {
7943 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7944 return token_type::parse_error;
7945 }
7946
7947 case 0x09:
7948 {
7949 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7950 return token_type::parse_error;
7951 }
7952
7953 case 0x0A:
7954 {
7955 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7956 return token_type::parse_error;
7957 }
7958
7959 case 0x0B:
7960 {
7961 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7962 return token_type::parse_error;
7963 }
7964
7965 case 0x0C:
7966 {
7967 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7968 return token_type::parse_error;
7969 }
7970
7971 case 0x0D:
7972 {
7973 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7974 return token_type::parse_error;
7975 }
7976
7977 case 0x0E:
7978 {
7979 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7980 return token_type::parse_error;
7981 }
7982
7983 case 0x0F:
7984 {
7985 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7986 return token_type::parse_error;
7987 }
7988
7989 case 0x10:
7990 {
7991 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7992 return token_type::parse_error;
7993 }
7994
7995 case 0x11:
7996 {
7997 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7998 return token_type::parse_error;
7999 }
8000
8001 case 0x12:
8002 {
8003 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
8004 return token_type::parse_error;
8005 }
8006
8007 case 0x13:
8008 {
8009 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
8010 return token_type::parse_error;
8011 }
8012
8013 case 0x14:
8014 {
8015 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
8016 return token_type::parse_error;
8017 }
8018
8019 case 0x15:
8020 {
8021 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
8022 return token_type::parse_error;
8023 }
8024
8025 case 0x16:
8026 {
8027 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
8028 return token_type::parse_error;
8029 }
8030
8031 case 0x17:
8032 {
8033 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
8034 return token_type::parse_error;
8035 }
8036
8037 case 0x18:
8038 {
8039 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
8040 return token_type::parse_error;
8041 }
8042
8043 case 0x19:
8044 {
8045 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
8046 return token_type::parse_error;
8047 }
8048
8049 case 0x1A:
8050 {
8051 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
8052 return token_type::parse_error;
8053 }
8054
8055 case 0x1B:
8056 {
8057 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
8058 return token_type::parse_error;
8059 }
8060
8061 case 0x1C:
8062 {
8063 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
8064 return token_type::parse_error;
8065 }
8066
8067 case 0x1D:
8068 {
8069 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
8070 return token_type::parse_error;
8071 }
8072
8073 case 0x1E:
8074 {
8075 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
8076 return token_type::parse_error;
8077 }
8078
8079 case 0x1F:
8080 {
8081 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
8082 return token_type::parse_error;
8083 }
8084
8085 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
8086 case 0x20:
8087 case 0x21:
8088 case 0x23:
8089 case 0x24:
8090 case 0x25:
8091 case 0x26:
8092 case 0x27:
8093 case 0x28:
8094 case 0x29:
8095 case 0x2A:
8096 case 0x2B:
8097 case 0x2C:
8098 case 0x2D:
8099 case 0x2E:
8100 case 0x2F:
8101 case 0x30:
8102 case 0x31:
8103 case 0x32:
8104 case 0x33:
8105 case 0x34:
8106 case 0x35:
8107 case 0x36:
8108 case 0x37:
8109 case 0x38:
8110 case 0x39:
8111 case 0x3A:
8112 case 0x3B:
8113 case 0x3C:
8114 case 0x3D:
8115 case 0x3E:
8116 case 0x3F:
8117 case 0x40:
8118 case 0x41:
8119 case 0x42:
8120 case 0x43:
8121 case 0x44:
8122 case 0x45:
8123 case 0x46:
8124 case 0x47:
8125 case 0x48:
8126 case 0x49:
8127 case 0x4A:
8128 case 0x4B:
8129 case 0x4C:
8130 case 0x4D:
8131 case 0x4E:
8132 case 0x4F:
8133 case 0x50:
8134 case 0x51:
8135 case 0x52:
8136 case 0x53:
8137 case 0x54:
8138 case 0x55:
8139 case 0x56:
8140 case 0x57:
8141 case 0x58:
8142 case 0x59:
8143 case 0x5A:
8144 case 0x5B:
8145 case 0x5D:
8146 case 0x5E:
8147 case 0x5F:
8148 case 0x60:
8149 case 0x61:
8150 case 0x62:
8151 case 0x63:
8152 case 0x64:
8153 case 0x65:
8154 case 0x66:
8155 case 0x67:
8156 case 0x68:
8157 case 0x69:
8158 case 0x6A:
8159 case 0x6B:
8160 case 0x6C:
8161 case 0x6D:
8162 case 0x6E:
8163 case 0x6F:
8164 case 0x70:
8165 case 0x71:
8166 case 0x72:
8167 case 0x73:
8168 case 0x74:
8169 case 0x75:
8170 case 0x76:
8171 case 0x77:
8172 case 0x78:
8173 case 0x79:
8174 case 0x7A:
8175 case 0x7B:
8176 case 0x7C:
8177 case 0x7D:
8178 case 0x7E:
8179 case 0x7F:
8180 {
8181 add(current);
8182 break;
8183 }
8184
8185 // U+0080..U+07FF: bytes C2..DF 80..BF
8186 case 0xC2:
8187 case 0xC3:
8188 case 0xC4:
8189 case 0xC5:
8190 case 0xC6:
8191 case 0xC7:
8192 case 0xC8:
8193 case 0xC9:
8194 case 0xCA:
8195 case 0xCB:
8196 case 0xCC:
8197 case 0xCD:
8198 case 0xCE:
8199 case 0xCF:
8200 case 0xD0:
8201 case 0xD1:
8202 case 0xD2:
8203 case 0xD3:
8204 case 0xD4:
8205 case 0xD5:
8206 case 0xD6:
8207 case 0xD7:
8208 case 0xD8:
8209 case 0xD9:
8210 case 0xDA:
8211 case 0xDB:
8212 case 0xDC:
8213 case 0xDD:
8214 case 0xDE:
8215 case 0xDF:
8216 {
8217 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
8218 {
8219 return token_type::parse_error;
8220 }
8221 break;
8222 }
8223
8224 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
8225 case 0xE0:
8226 {
8227 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
8228 {
8229 return token_type::parse_error;
8230 }
8231 break;
8232 }
8233
8234 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
8235 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
8236 case 0xE1:
8237 case 0xE2:
8238 case 0xE3:
8239 case 0xE4:
8240 case 0xE5:
8241 case 0xE6:
8242 case 0xE7:
8243 case 0xE8:
8244 case 0xE9:
8245 case 0xEA:
8246 case 0xEB:
8247 case 0xEC:
8248 case 0xEE:
8249 case 0xEF:
8250 {
8251 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
8252 {
8253 return token_type::parse_error;
8254 }
8255 break;
8256 }
8257
8258 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
8259 case 0xED:
8260 {
8261 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
8262 {
8263 return token_type::parse_error;
8264 }
8265 break;
8266 }
8267
8268 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
8269 case 0xF0:
8270 {
8271 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8272 {
8273 return token_type::parse_error;
8274 }
8275 break;
8276 }
8277
8278 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
8279 case 0xF1:
8280 case 0xF2:
8281 case 0xF3:
8282 {
8283 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8284 {
8285 return token_type::parse_error;
8286 }
8287 break;
8288 }
8289
8290 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
8291 case 0xF4:
8292 {
8293 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
8294 {
8295 return token_type::parse_error;
8296 }
8297 break;
8298 }
8299
8300 // remaining bytes (80..C1 and F5..FF) are ill-formed
8301 default:
8302 {
8303 error_message = "invalid string: ill-formed UTF-8 byte";
8304 return token_type::parse_error;
8305 }
8306 }
8307 }
8308 }
8309
8314 bool scan_comment()
8315 {
8316 switch (get())
8317 {
8318 // single-line comments skip input until a newline or EOF is read
8319 case '/':
8320 {
8321 while (true)
8322 {
8323 switch (get())
8324 {
8325 case '\n':
8326 case '\r':
8327 case char_traits<char_type>::eof():
8328 case '\0':
8329 return true;
8330
8331 default:
8332 break;
8333 }
8334 }
8335 }
8336
8337 // multi-line comments skip input until */ is read
8338 case '*':
8339 {
8340 while (true)
8341 {
8342 switch (get())
8343 {
8344 case char_traits<char_type>::eof():
8345 case '\0':
8346 {
8347 error_message = "invalid comment; missing closing '*/'";
8348 return false;
8349 }
8350
8351 case '*':
8352 {
8353 switch (get())
8354 {
8355 case '/':
8356 return true;
8357
8358 default:
8359 {
8360 unget();
8361 continue;
8362 }
8363 }
8364 }
8365
8366 default:
8367 continue;
8368 }
8369 }
8370 }
8371
8372 // unexpected character after reading '/'
8373 default:
8374 {
8375 error_message = "invalid comment; expecting '/' or '*' after '/'";
8376 return false;
8377 }
8378 }
8379 }
8380
8382 static void strtof(float& f, const char* str, char** endptr) noexcept
8383 {
8384 f = std::strtof(str, endptr);
8385 }
8386
8388 static void strtof(double& f, const char* str, char** endptr) noexcept
8389 {
8390 f = std::strtod(str, endptr);
8391 }
8392
8394 static void strtof(long double& f, const char* str, char** endptr) noexcept
8395 {
8396 f = std::strtold(str, endptr);
8397 }
8398
8439 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.
8440 {
8441 // reset token_buffer to store the number's bytes
8442 reset();
8443
8444 // the type of the parsed number; initially set to unsigned; will be
8445 // changed if minus sign, decimal point or exponent is read
8446 token_type number_type = token_type::value_unsigned;
8447
8448 // state (init): we just found out we need to scan a number
8449 switch (current)
8450 {
8451 case '-':
8452 {
8453 add(current);
8454 goto scan_number_minus;
8455 }
8456
8457 case '0':
8458 {
8459 add(current);
8460 goto scan_number_zero;
8461 }
8462
8463 case '1':
8464 case '2':
8465 case '3':
8466 case '4':
8467 case '5':
8468 case '6':
8469 case '7':
8470 case '8':
8471 case '9':
8472 {
8473 add(current);
8474 goto scan_number_any1;
8475 }
8476
8477 // all other characters are rejected outside scan_number()
8478 default: // LCOV_EXCL_LINE
8479 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8480 }
8481
8482scan_number_minus:
8483 // state: we just parsed a leading minus sign
8484 number_type = token_type::value_integer;
8485 switch (get())
8486 {
8487 case '0':
8488 {
8489 add(current);
8490 goto scan_number_zero;
8491 }
8492
8493 case '1':
8494 case '2':
8495 case '3':
8496 case '4':
8497 case '5':
8498 case '6':
8499 case '7':
8500 case '8':
8501 case '9':
8502 {
8503 add(current);
8504 goto scan_number_any1;
8505 }
8506
8507 default:
8508 {
8509 error_message = "invalid number; expected digit after '-'";
8510 return token_type::parse_error;
8511 }
8512 }
8513
8514scan_number_zero:
8515 // state: we just parse a zero (maybe with a leading minus sign)
8516 switch (get())
8517 {
8518 case '.':
8519 {
8520 add(decimal_point_char);
8521 goto scan_number_decimal1;
8522 }
8523
8524 case 'e':
8525 case 'E':
8526 {
8527 add(current);
8528 goto scan_number_exponent;
8529 }
8530
8531 default:
8532 goto scan_number_done;
8533 }
8534
8535scan_number_any1:
8536 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8537 switch (get())
8538 {
8539 case '0':
8540 case '1':
8541 case '2':
8542 case '3':
8543 case '4':
8544 case '5':
8545 case '6':
8546 case '7':
8547 case '8':
8548 case '9':
8549 {
8550 add(current);
8551 goto scan_number_any1;
8552 }
8553
8554 case '.':
8555 {
8556 add(decimal_point_char);
8557 goto scan_number_decimal1;
8558 }
8559
8560 case 'e':
8561 case 'E':
8562 {
8563 add(current);
8564 goto scan_number_exponent;
8565 }
8566
8567 default:
8568 goto scan_number_done;
8569 }
8570
8571scan_number_decimal1:
8572 // state: we just parsed a decimal point
8573 number_type = token_type::value_float;
8574 switch (get())
8575 {
8576 case '0':
8577 case '1':
8578 case '2':
8579 case '3':
8580 case '4':
8581 case '5':
8582 case '6':
8583 case '7':
8584 case '8':
8585 case '9':
8586 {
8587 add(current);
8588 goto scan_number_decimal2;
8589 }
8590
8591 default:
8592 {
8593 error_message = "invalid number; expected digit after '.'";
8594 return token_type::parse_error;
8595 }
8596 }
8597
8598scan_number_decimal2:
8599 // we just parsed at least one number after a decimal point
8600 switch (get())
8601 {
8602 case '0':
8603 case '1':
8604 case '2':
8605 case '3':
8606 case '4':
8607 case '5':
8608 case '6':
8609 case '7':
8610 case '8':
8611 case '9':
8612 {
8613 add(current);
8614 goto scan_number_decimal2;
8615 }
8616
8617 case 'e':
8618 case 'E':
8619 {
8620 add(current);
8621 goto scan_number_exponent;
8622 }
8623
8624 default:
8625 goto scan_number_done;
8626 }
8627
8628scan_number_exponent:
8629 // we just parsed an exponent
8630 number_type = token_type::value_float;
8631 switch (get())
8632 {
8633 case '+':
8634 case '-':
8635 {
8636 add(current);
8637 goto scan_number_sign;
8638 }
8639
8640 case '0':
8641 case '1':
8642 case '2':
8643 case '3':
8644 case '4':
8645 case '5':
8646 case '6':
8647 case '7':
8648 case '8':
8649 case '9':
8650 {
8651 add(current);
8652 goto scan_number_any2;
8653 }
8654
8655 default:
8656 {
8657 error_message =
8658 "invalid number; expected '+', '-', or digit after exponent";
8659 return token_type::parse_error;
8660 }
8661 }
8662
8663scan_number_sign:
8664 // we just parsed an exponent sign
8665 switch (get())
8666 {
8667 case '0':
8668 case '1':
8669 case '2':
8670 case '3':
8671 case '4':
8672 case '5':
8673 case '6':
8674 case '7':
8675 case '8':
8676 case '9':
8677 {
8678 add(current);
8679 goto scan_number_any2;
8680 }
8681
8682 default:
8683 {
8684 error_message = "invalid number; expected digit after exponent sign";
8685 return token_type::parse_error;
8686 }
8687 }
8688
8689scan_number_any2:
8690 // we just parsed a number after the exponent or exponent sign
8691 switch (get())
8692 {
8693 case '0':
8694 case '1':
8695 case '2':
8696 case '3':
8697 case '4':
8698 case '5':
8699 case '6':
8700 case '7':
8701 case '8':
8702 case '9':
8703 {
8704 add(current);
8705 goto scan_number_any2;
8706 }
8707
8708 default:
8709 goto scan_number_done;
8710 }
8711
8712scan_number_done:
8713 // unget the character after the number (we only read it to know that
8714 // we are done scanning a number)
8715 unget();
8716
8717 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8718 errno = 0;
8719
8720 // try to parse integers first and fall back to floats
8721 if (number_type == token_type::value_unsigned)
8722 {
8723 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8724
8725 // we checked the number format before
8726 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8727
8728 if (errno == 0)
8729 {
8730 value_unsigned = static_cast<number_unsigned_t>(x);
8731 if (value_unsigned == x)
8732 {
8733 return token_type::value_unsigned;
8734 }
8735 }
8736 }
8737 else if (number_type == token_type::value_integer)
8738 {
8739 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8740
8741 // we checked the number format before
8742 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8743
8744 if (errno == 0)
8745 {
8746 value_integer = static_cast<number_integer_t>(x);
8747 if (value_integer == x)
8748 {
8749 return token_type::value_integer;
8750 }
8751 }
8752 }
8753
8754 // this code is reached if we parse a floating-point number or if an
8755 // integer conversion above failed
8756 strtof(value_float, token_buffer.data(), &endptr);
8757
8758 // we checked the number format before
8759 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8760
8761 return token_type::value_float;
8762 }
8763
8770 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8771 token_type return_type)
8772 {
8773 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8774 for (std::size_t i = 1; i < length; ++i)
8775 {
8776 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8777 {
8778 error_message = "invalid literal";
8779 return token_type::parse_error;
8780 }
8781 }
8782 return return_type;
8783 }
8784
8786 // input management
8788
8790 void reset() noexcept
8791 {
8792 token_buffer.clear();
8793 token_string.clear();
8794 token_string.push_back(char_traits<char_type>::to_char_type(current));
8795 }
8796
8797 /*
8798 @brief get next character from the input
8799
8800 This function provides the interface to the used input adapter. It does
8801 not throw in case the input reached EOF, but returns a
8802 `char_traits<char>::eof()` in that case. Stores the scanned characters
8803 for use in error messages.
8804
8805 @return character read from the input
8806 */
8807 char_int_type get()
8808 {
8809 ++position.chars_read_total;
8810 ++position.chars_read_current_line;
8811
8812 if (next_unget)
8813 {
8814 // just reset the next_unget variable and work with current
8815 next_unget = false;
8816 }
8817 else
8818 {
8819 current = ia.get_character();
8820 }
8821
8822 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8823 {
8824 token_string.push_back(char_traits<char_type>::to_char_type(current));
8825 }
8826
8827 if (current == '\n')
8828 {
8829 ++position.lines_read;
8830 position.chars_read_current_line = 0;
8831 }
8832
8833 return current;
8834 }
8835
8844 void unget()
8845 {
8846 next_unget = true;
8847
8848 --position.chars_read_total;
8849
8850 // in case we "unget" a newline, we have to also decrement the lines_read
8851 if (position.chars_read_current_line == 0)
8852 {
8853 if (position.lines_read > 0)
8854 {
8855 --position.lines_read;
8856 }
8857 }
8858 else
8859 {
8860 --position.chars_read_current_line;
8861 }
8862
8863 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8864 {
8865 JSON_ASSERT(!token_string.empty());
8866 token_string.pop_back();
8867 }
8868 }
8869
8871 void add(char_int_type c)
8872 {
8873 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8874 }
8875
8876 public:
8878 // value getters
8880
8882 constexpr number_integer_t get_number_integer() const noexcept
8883 {
8884 return value_integer;
8885 }
8886
8888 constexpr number_unsigned_t get_number_unsigned() const noexcept
8889 {
8890 return value_unsigned;
8891 }
8892
8894 constexpr number_float_t get_number_float() const noexcept
8895 {
8896 return value_float;
8897 }
8898
8900 string_t& get_string()
8901 {
8902 return token_buffer;
8903 }
8904
8906 // diagnostics
8908
8910 constexpr position_t get_position() const noexcept
8911 {
8912 return position;
8913 }
8914
8918 std::string get_token_string() const
8919 {
8920 // escape control characters
8921 std::string result;
8922 for (const auto c : token_string)
8923 {
8924 if (static_cast<unsigned char>(c) <= '\x1F')
8925 {
8926 // escape control characters
8927 std::array<char, 9> cs{{}};
8928 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8929 result += cs.data();
8930 }
8931 else
8932 {
8933 // add character as is
8934 result.push_back(static_cast<std::string::value_type>(c));
8935 }
8936 }
8937
8938 return result;
8939 }
8940
8943 constexpr const char* get_error_message() const noexcept
8944 {
8945 return error_message;
8946 }
8947
8949 // actual scanner
8951
8957 {
8958 if (get() == 0xEF)
8959 {
8960 // check if we completely parse the BOM
8961 return get() == 0xBB && get() == 0xBF;
8962 }
8963
8964 // the first character is not the beginning of the BOM; unget it to
8965 // process is later
8966 unget();
8967 return true;
8968 }
8969
8971 {
8972 do
8973 {
8974 get();
8975 }
8976 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8977 }
8978
8980 {
8981 // initially, skip the BOM
8982 if (position.chars_read_total == 0 && !skip_bom())
8983 {
8984 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8985 return token_type::parse_error;
8986 }
8987
8988 // read next character and ignore whitespace
8989 skip_whitespace();
8990
8991 // ignore comments
8992 while (ignore_comments && current == '/')
8993 {
8994 if (!scan_comment())
8995 {
8996 return token_type::parse_error;
8997 }
8998
8999 // skip following whitespace
9000 skip_whitespace();
9001 }
9002
9003 switch (current)
9004 {
9005 // structural characters
9006 case '[':
9007 return token_type::begin_array;
9008 case ']':
9009 return token_type::end_array;
9010 case '{':
9011 return token_type::begin_object;
9012 case '}':
9013 return token_type::end_object;
9014 case ':':
9015 return token_type::name_separator;
9016 case ',':
9017 return token_type::value_separator;
9018
9019 // literals
9020 case 't':
9021 {
9022 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')}};
9023 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
9024 }
9025 case 'f':
9026 {
9027 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')}};
9028 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
9029 }
9030 case 'n':
9031 {
9032 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')}};
9033 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
9034 }
9035
9036 // string
9037 case '\"':
9038 return scan_string();
9039
9040 // number
9041 case '-':
9042 case '0':
9043 case '1':
9044 case '2':
9045 case '3':
9046 case '4':
9047 case '5':
9048 case '6':
9049 case '7':
9050 case '8':
9051 case '9':
9052 return scan_number();
9053
9054 // end of input (the null byte is needed when parsing from
9055 // string literals)
9056 case '\0':
9058 return token_type::end_of_input;
9059
9060 // error
9061 default:
9062 error_message = "invalid literal";
9063 return token_type::parse_error;
9064 }
9065 }
9066
9067 private:
9069 InputAdapterType ia;
9070
9072 const bool ignore_comments = false;
9073
9075 char_int_type current = char_traits<char_type>::eof();
9076
9078 bool next_unget = false;
9079
9081 position_t position {};
9082
9084 std::vector<char_type> token_string {};
9085
9087 string_t token_buffer {};
9088
9090 const char* error_message = "";
9091
9092 // number values
9093 number_integer_t value_integer = 0;
9094 number_unsigned_t value_unsigned = 0;
9095 number_float_t value_float = 0;
9096
9098 const char_int_type decimal_point_char = '.';
9099};
9100
9101} // namespace detail
9103
9104// #include <nlohmann/detail/macro_scope.hpp>
9105
9106// #include <nlohmann/detail/meta/is_sax.hpp>
9107// __ _____ _____ _____
9108// __| | __| | | | JSON for Modern C++
9109// | | |__ | | | | | | version 3.11.3
9110// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9111//
9112// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
9113// SPDX-License-Identifier: MIT
9114
9115
9116
9117#include <cstdint> // size_t
9118#include <utility> // declval
9119#include <string> // string
9120
9121// #include <nlohmann/detail/abi_macros.hpp>
9122
9123// #include <nlohmann/detail/meta/detected.hpp>
9124
9125// #include <nlohmann/detail/meta/type_traits.hpp>
9126
9127
9129namespace detail
9130{
9131
9132template<typename T>
9133using null_function_t = decltype(std::declval<T&>().null());
9134
9135template<typename T>
9137 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9138
9139template<typename T, typename Integer>
9141 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9142
9143template<typename T, typename Unsigned>
9145 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9146
9147template<typename T, typename Float, typename String>
9148using number_float_function_t = decltype(std::declval<T&>().number_float(
9149 std::declval<Float>(), std::declval<const String&>()));
9150
9151template<typename T, typename String>
9153 decltype(std::declval<T&>().string(std::declval<String&>()));
9154
9155template<typename T, typename Binary>
9157 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9158
9159template<typename T>
9161 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9162
9163template<typename T, typename String>
9165 decltype(std::declval<T&>().key(std::declval<String&>()));
9166
9167template<typename T>
9168using end_object_function_t = decltype(std::declval<T&>().end_object());
9169
9170template<typename T>
9172 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9173
9174template<typename T>
9175using end_array_function_t = decltype(std::declval<T&>().end_array());
9176
9177template<typename T, typename Exception>
9178using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9179 std::declval<std::size_t>(), std::declval<const std::string&>(),
9180 std::declval<const Exception&>()));
9181
9182template<typename SAX, typename BasicJsonType>
9184{
9185 private:
9187 "BasicJsonType must be of type basic_json<...>");
9188
9189 using number_integer_t = typename BasicJsonType::number_integer_t;
9190 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9191 using number_float_t = typename BasicJsonType::number_float_t;
9192 using string_t = typename BasicJsonType::string_t;
9193 using binary_t = typename BasicJsonType::binary_t;
9194 using exception_t = typename BasicJsonType::exception;
9195
9196 public:
9197 static constexpr bool value =
9211};
9212
9213template<typename SAX, typename BasicJsonType>
9215{
9216 private:
9218 "BasicJsonType must be of type basic_json<...>");
9219
9220 using number_integer_t = typename BasicJsonType::number_integer_t;
9221 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9222 using number_float_t = typename BasicJsonType::number_float_t;
9223 using string_t = typename BasicJsonType::string_t;
9224 using binary_t = typename BasicJsonType::binary_t;
9225 using exception_t = typename BasicJsonType::exception;
9226
9227 public:
9229 "Missing/invalid function: bool null()");
9231 "Missing/invalid function: bool boolean(bool)");
9233 "Missing/invalid function: bool boolean(bool)");
9234 static_assert(
9236 number_integer_t>::value,
9237 "Missing/invalid function: bool number_integer(number_integer_t)");
9238 static_assert(
9240 number_unsigned_t>::value,
9241 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9242 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9243 number_float_t, string_t>::value,
9244 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9245 static_assert(
9247 "Missing/invalid function: bool string(string_t&)");
9248 static_assert(
9250 "Missing/invalid function: bool binary(binary_t&)");
9252 "Missing/invalid function: bool start_object(std::size_t)");
9254 "Missing/invalid function: bool key(string_t&)");
9256 "Missing/invalid function: bool end_object()");
9258 "Missing/invalid function: bool start_array(std::size_t)");
9260 "Missing/invalid function: bool end_array()");
9261 static_assert(
9263 "Missing/invalid function: bool parse_error(std::size_t, const "
9264 "std::string&, const exception&)");
9265};
9266
9267} // namespace detail
9269
9270// #include <nlohmann/detail/meta/type_traits.hpp>
9271
9272// #include <nlohmann/detail/string_concat.hpp>
9273
9274// #include <nlohmann/detail/value_t.hpp>
9275
9276
9278namespace detail
9279{
9280
9283{
9284 error,
9285 ignore,
9286 store
9287};
9288
9296static inline bool little_endianness(int num = 1) noexcept
9297{
9298 return *reinterpret_cast<char*>(&num) == 1;
9299}
9300
9302// binary reader //
9304
9308template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
9310{
9311 using number_integer_t = typename BasicJsonType::number_integer_t;
9312 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9313 using number_float_t = typename BasicJsonType::number_float_t;
9314 using string_t = typename BasicJsonType::string_t;
9315 using binary_t = typename BasicJsonType::binary_t;
9316 using json_sax_t = SAX;
9317 using char_type = typename InputAdapterType::char_type;
9318 using char_int_type = typename char_traits<char_type>::int_type;
9319
9320 public:
9326 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9327 {
9329 }
9330
9331 // make class move-only
9333 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9335 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9336 ~binary_reader() = default;
9337
9347 bool sax_parse(const input_format_t format,
9348 json_sax_t* sax_,
9349 const bool strict = true,
9350 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9351 {
9352 sax = sax_;
9353 bool result = false;
9354
9355 switch (format)
9356 {
9358 result = parse_bson_internal();
9359 break;
9360
9362 result = parse_cbor_internal(true, tag_handler);
9363 break;
9364
9366 result = parse_msgpack_internal();
9367 break;
9368
9371 result = parse_ubjson_internal();
9372 break;
9373
9374 case input_format_t::json: // LCOV_EXCL_LINE
9375 default: // LCOV_EXCL_LINE
9376 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9377 }
9378
9379 // strict mode: next byte must be EOF
9380 if (result && strict)
9381 {
9382 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9383 {
9384 get_ignore_noop();
9385 }
9386 else
9387 {
9388 get();
9389 }
9390
9392 {
9393 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9394 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9395 }
9396 }
9397
9398 return result;
9399 }
9400
9401 private:
9403 // BSON //
9405
9410 bool parse_bson_internal()
9411 {
9412 std::int32_t document_size{};
9413 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9414
9415 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
9416 {
9417 return false;
9418 }
9419
9420 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9421 {
9422 return false;
9423 }
9424
9425 return sax->end_object();
9426 }
9427
9435 bool get_bson_cstr(string_t& result)
9436 {
9437 auto out = std::back_inserter(result);
9438 while (true)
9439 {
9440 get();
9441 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
9442 {
9443 return false;
9444 }
9445 if (current == 0x00)
9446 {
9447 return true;
9448 }
9449 *out++ = static_cast<typename string_t::value_type>(current);
9450 }
9451 }
9452
9464 template<typename NumberType>
9465 bool get_bson_string(const NumberType len, string_t& result)
9466 {
9467 if (JSON_HEDLEY_UNLIKELY(len < 1))
9468 {
9469 auto last_token = get_token_string();
9470 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9471 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
9472 }
9473
9474 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
9475 }
9476
9486 template<typename NumberType>
9487 bool get_bson_binary(const NumberType len, binary_t& result)
9488 {
9489 if (JSON_HEDLEY_UNLIKELY(len < 0))
9490 {
9491 auto last_token = get_token_string();
9492 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9493 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
9494 }
9495
9496 // All BSON binary values have a subtype
9497 std::uint8_t subtype{};
9498 get_number<std::uint8_t>(input_format_t::bson, subtype);
9499 result.set_subtype(subtype);
9500
9501 return get_binary(input_format_t::bson, len, result);
9502 }
9503
9514 bool parse_bson_element_internal(const char_int_type element_type,
9515 const std::size_t element_type_parse_position)
9516 {
9517 switch (element_type)
9518 {
9519 case 0x01: // double
9520 {
9521 double number{};
9522 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9523 }
9524
9525 case 0x02: // string
9526 {
9527 std::int32_t len{};
9528 string_t value;
9529 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
9530 }
9531
9532 case 0x03: // object
9533 {
9534 return parse_bson_internal();
9535 }
9536
9537 case 0x04: // array
9538 {
9539 return parse_bson_array();
9540 }
9541
9542 case 0x05: // binary
9543 {
9544 std::int32_t len{};
9545 binary_t value;
9546 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9547 }
9548
9549 case 0x08: // boolean
9550 {
9551 return sax->boolean(get() != 0);
9552 }
9553
9554 case 0x0A: // null
9555 {
9556 return sax->null();
9557 }
9558
9559 case 0x10: // int32
9560 {
9561 std::int32_t value{};
9562 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9563 }
9564
9565 case 0x12: // int64
9566 {
9567 std::int64_t value{};
9568 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9569 }
9570
9571 default: // anything else not supported (yet)
9572 {
9573 std::array<char, 3> cr{{}};
9574 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9575 const std::string cr_str{cr.data()};
9576 return sax->parse_error(element_type_parse_position, cr_str,
9577 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
9578 }
9579 }
9580 }
9581
9594 bool parse_bson_element_list(const bool is_array)
9595 {
9596 string_t key;
9597
9598 while (auto element_type = get())
9599 {
9600 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
9601 {
9602 return false;
9603 }
9604
9605 const std::size_t element_type_parse_position = chars_read;
9606 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
9607 {
9608 return false;
9609 }
9610
9611 if (!is_array && !sax->key(key))
9612 {
9613 return false;
9614 }
9615
9616 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
9617 {
9618 return false;
9619 }
9620
9621 // get_bson_cstr only appends
9622 key.clear();
9623 }
9624
9625 return true;
9626 }
9627
9632 bool parse_bson_array()
9633 {
9634 std::int32_t document_size{};
9635 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9636
9637 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
9638 {
9639 return false;
9640 }
9641
9642 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
9643 {
9644 return false;
9645 }
9646
9647 return sax->end_array();
9648 }
9649
9651 // CBOR //
9653
9662 bool parse_cbor_internal(const bool get_char,
9663 const cbor_tag_handler_t tag_handler)
9664 {
9665 switch (get_char ? get() : current)
9666 {
9667 // EOF
9668 case char_traits<char_type>::eof():
9669 return unexpect_eof(input_format_t::cbor, "value");
9670
9671 // Integer 0x00..0x17 (0..23)
9672 case 0x00:
9673 case 0x01:
9674 case 0x02:
9675 case 0x03:
9676 case 0x04:
9677 case 0x05:
9678 case 0x06:
9679 case 0x07:
9680 case 0x08:
9681 case 0x09:
9682 case 0x0A:
9683 case 0x0B:
9684 case 0x0C:
9685 case 0x0D:
9686 case 0x0E:
9687 case 0x0F:
9688 case 0x10:
9689 case 0x11:
9690 case 0x12:
9691 case 0x13:
9692 case 0x14:
9693 case 0x15:
9694 case 0x16:
9695 case 0x17:
9696 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9697
9698 case 0x18: // Unsigned integer (one-byte uint8_t follows)
9699 {
9700 std::uint8_t number{};
9701 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9702 }
9703
9704 case 0x19: // Unsigned integer (two-byte uint16_t follows)
9705 {
9706 std::uint16_t number{};
9707 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9708 }
9709
9710 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9711 {
9712 std::uint32_t number{};
9713 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9714 }
9715
9716 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9717 {
9718 std::uint64_t number{};
9719 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9720 }
9721
9722 // Negative integer -1-0x00..-1-0x17 (-1..-24)
9723 case 0x20:
9724 case 0x21:
9725 case 0x22:
9726 case 0x23:
9727 case 0x24:
9728 case 0x25:
9729 case 0x26:
9730 case 0x27:
9731 case 0x28:
9732 case 0x29:
9733 case 0x2A:
9734 case 0x2B:
9735 case 0x2C:
9736 case 0x2D:
9737 case 0x2E:
9738 case 0x2F:
9739 case 0x30:
9740 case 0x31:
9741 case 0x32:
9742 case 0x33:
9743 case 0x34:
9744 case 0x35:
9745 case 0x36:
9746 case 0x37:
9747 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9748
9749 case 0x38: // Negative integer (one-byte uint8_t follows)
9750 {
9751 std::uint8_t number{};
9752 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9753 }
9754
9755 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9756 {
9757 std::uint16_t number{};
9758 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9759 }
9760
9761 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9762 {
9763 std::uint32_t number{};
9764 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9765 }
9766
9767 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9768 {
9769 std::uint64_t number{};
9770 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
9771 - static_cast<number_integer_t>(number));
9772 }
9773
9774 // Binary data (0x00..0x17 bytes follow)
9775 case 0x40:
9776 case 0x41:
9777 case 0x42:
9778 case 0x43:
9779 case 0x44:
9780 case 0x45:
9781 case 0x46:
9782 case 0x47:
9783 case 0x48:
9784 case 0x49:
9785 case 0x4A:
9786 case 0x4B:
9787 case 0x4C:
9788 case 0x4D:
9789 case 0x4E:
9790 case 0x4F:
9791 case 0x50:
9792 case 0x51:
9793 case 0x52:
9794 case 0x53:
9795 case 0x54:
9796 case 0x55:
9797 case 0x56:
9798 case 0x57:
9799 case 0x58: // Binary data (one-byte uint8_t for n follows)
9800 case 0x59: // Binary data (two-byte uint16_t for n follow)
9801 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9802 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9803 case 0x5F: // Binary data (indefinite length)
9804 {
9805 binary_t b;
9806 return get_cbor_binary(b) && sax->binary(b);
9807 }
9808
9809 // UTF-8 string (0x00..0x17 bytes follow)
9810 case 0x60:
9811 case 0x61:
9812 case 0x62:
9813 case 0x63:
9814 case 0x64:
9815 case 0x65:
9816 case 0x66:
9817 case 0x67:
9818 case 0x68:
9819 case 0x69:
9820 case 0x6A:
9821 case 0x6B:
9822 case 0x6C:
9823 case 0x6D:
9824 case 0x6E:
9825 case 0x6F:
9826 case 0x70:
9827 case 0x71:
9828 case 0x72:
9829 case 0x73:
9830 case 0x74:
9831 case 0x75:
9832 case 0x76:
9833 case 0x77:
9834 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9835 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9836 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9837 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9838 case 0x7F: // UTF-8 string (indefinite length)
9839 {
9840 string_t s;
9841 return get_cbor_string(s) && sax->string(s);
9842 }
9843
9844 // array (0x00..0x17 data items follow)
9845 case 0x80:
9846 case 0x81:
9847 case 0x82:
9848 case 0x83:
9849 case 0x84:
9850 case 0x85:
9851 case 0x86:
9852 case 0x87:
9853 case 0x88:
9854 case 0x89:
9855 case 0x8A:
9856 case 0x8B:
9857 case 0x8C:
9858 case 0x8D:
9859 case 0x8E:
9860 case 0x8F:
9861 case 0x90:
9862 case 0x91:
9863 case 0x92:
9864 case 0x93:
9865 case 0x94:
9866 case 0x95:
9867 case 0x96:
9868 case 0x97:
9869 return get_cbor_array(
9870 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9871
9872 case 0x98: // array (one-byte uint8_t for n follows)
9873 {
9874 std::uint8_t len{};
9875 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9876 }
9877
9878 case 0x99: // array (two-byte uint16_t for n follow)
9879 {
9880 std::uint16_t len{};
9881 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9882 }
9883
9884 case 0x9A: // array (four-byte uint32_t for n follow)
9885 {
9886 std::uint32_t len{};
9887 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9888 }
9889
9890 case 0x9B: // array (eight-byte uint64_t for n follow)
9891 {
9892 std::uint64_t len{};
9893 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9894 }
9895
9896 case 0x9F: // array (indefinite length)
9897 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
9898
9899 // map (0x00..0x17 pairs of data items follow)
9900 case 0xA0:
9901 case 0xA1:
9902 case 0xA2:
9903 case 0xA3:
9904 case 0xA4:
9905 case 0xA5:
9906 case 0xA6:
9907 case 0xA7:
9908 case 0xA8:
9909 case 0xA9:
9910 case 0xAA:
9911 case 0xAB:
9912 case 0xAC:
9913 case 0xAD:
9914 case 0xAE:
9915 case 0xAF:
9916 case 0xB0:
9917 case 0xB1:
9918 case 0xB2:
9919 case 0xB3:
9920 case 0xB4:
9921 case 0xB5:
9922 case 0xB6:
9923 case 0xB7:
9924 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9925
9926 case 0xB8: // map (one-byte uint8_t for n follows)
9927 {
9928 std::uint8_t len{};
9929 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9930 }
9931
9932 case 0xB9: // map (two-byte uint16_t for n follow)
9933 {
9934 std::uint16_t len{};
9935 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9936 }
9937
9938 case 0xBA: // map (four-byte uint32_t for n follow)
9939 {
9940 std::uint32_t len{};
9941 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9942 }
9943
9944 case 0xBB: // map (eight-byte uint64_t for n follow)
9945 {
9946 std::uint64_t len{};
9947 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9948 }
9949
9950 case 0xBF: // map (indefinite length)
9951 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
9952
9953 case 0xC6: // tagged item
9954 case 0xC7:
9955 case 0xC8:
9956 case 0xC9:
9957 case 0xCA:
9958 case 0xCB:
9959 case 0xCC:
9960 case 0xCD:
9961 case 0xCE:
9962 case 0xCF:
9963 case 0xD0:
9964 case 0xD1:
9965 case 0xD2:
9966 case 0xD3:
9967 case 0xD4:
9968 case 0xD8: // tagged item (1 bytes follow)
9969 case 0xD9: // tagged item (2 bytes follow)
9970 case 0xDA: // tagged item (4 bytes follow)
9971 case 0xDB: // tagged item (8 bytes follow)
9972 {
9973 switch (tag_handler)
9974 {
9976 {
9977 auto last_token = get_token_string();
9978 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9979 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9980 }
9981
9983 {
9984 // ignore binary subtype
9985 switch (current)
9986 {
9987 case 0xD8:
9988 {
9989 std::uint8_t subtype_to_ignore{};
9990 get_number(input_format_t::cbor, subtype_to_ignore);
9991 break;
9992 }
9993 case 0xD9:
9994 {
9995 std::uint16_t subtype_to_ignore{};
9996 get_number(input_format_t::cbor, subtype_to_ignore);
9997 break;
9998 }
9999 case 0xDA:
10000 {
10001 std::uint32_t subtype_to_ignore{};
10002 get_number(input_format_t::cbor, subtype_to_ignore);
10003 break;
10004 }
10005 case 0xDB:
10006 {
10007 std::uint64_t subtype_to_ignore{};
10008 get_number(input_format_t::cbor, subtype_to_ignore);
10009 break;
10010 }
10011 default:
10012 break;
10013 }
10014 return parse_cbor_internal(true, tag_handler);
10015 }
10016
10018 {
10019 binary_t b;
10020 // use binary subtype and store in binary container
10021 switch (current)
10022 {
10023 case 0xD8:
10024 {
10025 std::uint8_t subtype{};
10026 get_number(input_format_t::cbor, subtype);
10027 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10028 break;
10029 }
10030 case 0xD9:
10031 {
10032 std::uint16_t subtype{};
10033 get_number(input_format_t::cbor, subtype);
10034 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10035 break;
10036 }
10037 case 0xDA:
10038 {
10039 std::uint32_t subtype{};
10040 get_number(input_format_t::cbor, subtype);
10041 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10042 break;
10043 }
10044 case 0xDB:
10045 {
10046 std::uint64_t subtype{};
10047 get_number(input_format_t::cbor, subtype);
10048 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10049 break;
10050 }
10051 default:
10052 return parse_cbor_internal(true, tag_handler);
10053 }
10054 get();
10055 return get_cbor_binary(b) && sax->binary(b);
10056 }
10057
10058 default: // LCOV_EXCL_LINE
10059 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10060 return false; // LCOV_EXCL_LINE
10061 }
10062 }
10063
10064 case 0xF4: // false
10065 return sax->boolean(false);
10066
10067 case 0xF5: // true
10068 return sax->boolean(true);
10069
10070 case 0xF6: // null
10071 return sax->null();
10072
10073 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10074 {
10075 const auto byte1_raw = get();
10076 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10077 {
10078 return false;
10079 }
10080 const auto byte2_raw = get();
10081 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10082 {
10083 return false;
10084 }
10085
10086 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10087 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10088
10089 // code from RFC 7049, Appendix D, Figure 3:
10090 // As half-precision floating-point numbers were only added
10091 // to IEEE 754 in 2008, today's programming platforms often
10092 // still only have limited support for them. It is very
10093 // easy to include at least decoding support for them even
10094 // without such support. An example of a small decoder for
10095 // half-precision floating-point numbers in the C language
10096 // is shown in Fig. 3.
10097 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10098 const double val = [&half]
10099 {
10100 const int exp = (half >> 10u) & 0x1Fu;
10101 const unsigned int mant = half & 0x3FFu;
10102 JSON_ASSERT(0 <= exp&& exp <= 32);
10103 JSON_ASSERT(mant <= 1024);
10104 switch (exp)
10105 {
10106 case 0:
10107 return std::ldexp(mant, -24);
10108 case 31:
10109 return (mant == 0)
10110 ? std::numeric_limits<double>::infinity()
10111 : std::numeric_limits<double>::quiet_NaN();
10112 default:
10113 return std::ldexp(mant + 1024, exp - 25);
10114 }
10115 }();
10116 return sax->number_float((half & 0x8000u) != 0
10117 ? static_cast<number_float_t>(-val)
10118 : static_cast<number_float_t>(val), "");
10119 }
10120
10121 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10122 {
10123 float number{};
10124 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10125 }
10126
10127 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10128 {
10129 double number{};
10130 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10131 }
10132
10133 default: // anything else (0xFF is handled inside the other types)
10134 {
10135 auto last_token = get_token_string();
10136 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10137 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10138 }
10139 }
10140 }
10141
10153 bool get_cbor_string(string_t& result)
10154 {
10155 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10156 {
10157 return false;
10158 }
10159
10160 switch (current)
10161 {
10162 // UTF-8 string (0x00..0x17 bytes follow)
10163 case 0x60:
10164 case 0x61:
10165 case 0x62:
10166 case 0x63:
10167 case 0x64:
10168 case 0x65:
10169 case 0x66:
10170 case 0x67:
10171 case 0x68:
10172 case 0x69:
10173 case 0x6A:
10174 case 0x6B:
10175 case 0x6C:
10176 case 0x6D:
10177 case 0x6E:
10178 case 0x6F:
10179 case 0x70:
10180 case 0x71:
10181 case 0x72:
10182 case 0x73:
10183 case 0x74:
10184 case 0x75:
10185 case 0x76:
10186 case 0x77:
10187 {
10188 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10189 }
10190
10191 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10192 {
10193 std::uint8_t len{};
10194 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10195 }
10196
10197 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10198 {
10199 std::uint16_t len{};
10200 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10201 }
10202
10203 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10204 {
10205 std::uint32_t len{};
10206 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10207 }
10208
10209 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10210 {
10211 std::uint64_t len{};
10212 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10213 }
10214
10215 case 0x7F: // UTF-8 string (indefinite length)
10216 {
10217 while (get() != 0xFF)
10218 {
10219 string_t chunk;
10220 if (!get_cbor_string(chunk))
10221 {
10222 return false;
10223 }
10224 result.append(chunk);
10225 }
10226 return true;
10227 }
10228
10229 default:
10230 {
10231 auto last_token = get_token_string();
10232 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10233 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10234 }
10235 }
10236 }
10237
10249 bool get_cbor_binary(binary_t& result)
10250 {
10251 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10252 {
10253 return false;
10254 }
10255
10256 switch (current)
10257 {
10258 // Binary data (0x00..0x17 bytes follow)
10259 case 0x40:
10260 case 0x41:
10261 case 0x42:
10262 case 0x43:
10263 case 0x44:
10264 case 0x45:
10265 case 0x46:
10266 case 0x47:
10267 case 0x48:
10268 case 0x49:
10269 case 0x4A:
10270 case 0x4B:
10271 case 0x4C:
10272 case 0x4D:
10273 case 0x4E:
10274 case 0x4F:
10275 case 0x50:
10276 case 0x51:
10277 case 0x52:
10278 case 0x53:
10279 case 0x54:
10280 case 0x55:
10281 case 0x56:
10282 case 0x57:
10283 {
10284 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10285 }
10286
10287 case 0x58: // Binary data (one-byte uint8_t for n follows)
10288 {
10289 std::uint8_t len{};
10290 return get_number(input_format_t::cbor, len) &&
10291 get_binary(input_format_t::cbor, len, result);
10292 }
10293
10294 case 0x59: // Binary data (two-byte uint16_t for n follow)
10295 {
10296 std::uint16_t len{};
10297 return get_number(input_format_t::cbor, len) &&
10298 get_binary(input_format_t::cbor, len, result);
10299 }
10300
10301 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10302 {
10303 std::uint32_t len{};
10304 return get_number(input_format_t::cbor, len) &&
10305 get_binary(input_format_t::cbor, len, result);
10306 }
10307
10308 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10309 {
10310 std::uint64_t len{};
10311 return get_number(input_format_t::cbor, len) &&
10312 get_binary(input_format_t::cbor, len, result);
10313 }
10314
10315 case 0x5F: // Binary data (indefinite length)
10316 {
10317 while (get() != 0xFF)
10318 {
10319 binary_t chunk;
10320 if (!get_cbor_binary(chunk))
10321 {
10322 return false;
10323 }
10324 result.insert(result.end(), chunk.begin(), chunk.end());
10325 }
10326 return true;
10327 }
10328
10329 default:
10330 {
10331 auto last_token = get_token_string();
10332 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10333 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));
10334 }
10335 }
10336 }
10337
10344 bool get_cbor_array(const std::size_t len,
10345 const cbor_tag_handler_t tag_handler)
10346 {
10347 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10348 {
10349 return false;
10350 }
10351
10352 if (len != static_cast<std::size_t>(-1))
10353 {
10354 for (std::size_t i = 0; i < len; ++i)
10355 {
10356 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10357 {
10358 return false;
10359 }
10360 }
10361 }
10362 else
10363 {
10364 while (get() != 0xFF)
10365 {
10366 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10367 {
10368 return false;
10369 }
10370 }
10371 }
10372
10373 return sax->end_array();
10374 }
10375
10382 bool get_cbor_object(const std::size_t len,
10383 const cbor_tag_handler_t tag_handler)
10384 {
10385 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10386 {
10387 return false;
10388 }
10389
10390 if (len != 0)
10391 {
10392 string_t key;
10393 if (len != static_cast<std::size_t>(-1))
10394 {
10395 for (std::size_t i = 0; i < len; ++i)
10396 {
10397 get();
10398 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10399 {
10400 return false;
10401 }
10402
10403 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10404 {
10405 return false;
10406 }
10407 key.clear();
10408 }
10409 }
10410 else
10411 {
10412 while (get() != 0xFF)
10413 {
10414 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10415 {
10416 return false;
10417 }
10418
10419 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10420 {
10421 return false;
10422 }
10423 key.clear();
10424 }
10425 }
10426 }
10427
10428 return sax->end_object();
10429 }
10430
10432 // MsgPack //
10434
10438 bool parse_msgpack_internal()
10439 {
10440 switch (get())
10441 {
10442 // EOF
10443 case char_traits<char_type>::eof():
10444 return unexpect_eof(input_format_t::msgpack, "value");
10445
10446 // positive fixint
10447 case 0x00:
10448 case 0x01:
10449 case 0x02:
10450 case 0x03:
10451 case 0x04:
10452 case 0x05:
10453 case 0x06:
10454 case 0x07:
10455 case 0x08:
10456 case 0x09:
10457 case 0x0A:
10458 case 0x0B:
10459 case 0x0C:
10460 case 0x0D:
10461 case 0x0E:
10462 case 0x0F:
10463 case 0x10:
10464 case 0x11:
10465 case 0x12:
10466 case 0x13:
10467 case 0x14:
10468 case 0x15:
10469 case 0x16:
10470 case 0x17:
10471 case 0x18:
10472 case 0x19:
10473 case 0x1A:
10474 case 0x1B:
10475 case 0x1C:
10476 case 0x1D:
10477 case 0x1E:
10478 case 0x1F:
10479 case 0x20:
10480 case 0x21:
10481 case 0x22:
10482 case 0x23:
10483 case 0x24:
10484 case 0x25:
10485 case 0x26:
10486 case 0x27:
10487 case 0x28:
10488 case 0x29:
10489 case 0x2A:
10490 case 0x2B:
10491 case 0x2C:
10492 case 0x2D:
10493 case 0x2E:
10494 case 0x2F:
10495 case 0x30:
10496 case 0x31:
10497 case 0x32:
10498 case 0x33:
10499 case 0x34:
10500 case 0x35:
10501 case 0x36:
10502 case 0x37:
10503 case 0x38:
10504 case 0x39:
10505 case 0x3A:
10506 case 0x3B:
10507 case 0x3C:
10508 case 0x3D:
10509 case 0x3E:
10510 case 0x3F:
10511 case 0x40:
10512 case 0x41:
10513 case 0x42:
10514 case 0x43:
10515 case 0x44:
10516 case 0x45:
10517 case 0x46:
10518 case 0x47:
10519 case 0x48:
10520 case 0x49:
10521 case 0x4A:
10522 case 0x4B:
10523 case 0x4C:
10524 case 0x4D:
10525 case 0x4E:
10526 case 0x4F:
10527 case 0x50:
10528 case 0x51:
10529 case 0x52:
10530 case 0x53:
10531 case 0x54:
10532 case 0x55:
10533 case 0x56:
10534 case 0x57:
10535 case 0x58:
10536 case 0x59:
10537 case 0x5A:
10538 case 0x5B:
10539 case 0x5C:
10540 case 0x5D:
10541 case 0x5E:
10542 case 0x5F:
10543 case 0x60:
10544 case 0x61:
10545 case 0x62:
10546 case 0x63:
10547 case 0x64:
10548 case 0x65:
10549 case 0x66:
10550 case 0x67:
10551 case 0x68:
10552 case 0x69:
10553 case 0x6A:
10554 case 0x6B:
10555 case 0x6C:
10556 case 0x6D:
10557 case 0x6E:
10558 case 0x6F:
10559 case 0x70:
10560 case 0x71:
10561 case 0x72:
10562 case 0x73:
10563 case 0x74:
10564 case 0x75:
10565 case 0x76:
10566 case 0x77:
10567 case 0x78:
10568 case 0x79:
10569 case 0x7A:
10570 case 0x7B:
10571 case 0x7C:
10572 case 0x7D:
10573 case 0x7E:
10574 case 0x7F:
10575 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10576
10577 // fixmap
10578 case 0x80:
10579 case 0x81:
10580 case 0x82:
10581 case 0x83:
10582 case 0x84:
10583 case 0x85:
10584 case 0x86:
10585 case 0x87:
10586 case 0x88:
10587 case 0x89:
10588 case 0x8A:
10589 case 0x8B:
10590 case 0x8C:
10591 case 0x8D:
10592 case 0x8E:
10593 case 0x8F:
10594 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10595
10596 // fixarray
10597 case 0x90:
10598 case 0x91:
10599 case 0x92:
10600 case 0x93:
10601 case 0x94:
10602 case 0x95:
10603 case 0x96:
10604 case 0x97:
10605 case 0x98:
10606 case 0x99:
10607 case 0x9A:
10608 case 0x9B:
10609 case 0x9C:
10610 case 0x9D:
10611 case 0x9E:
10612 case 0x9F:
10613 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10614
10615 // fixstr
10616 case 0xA0:
10617 case 0xA1:
10618 case 0xA2:
10619 case 0xA3:
10620 case 0xA4:
10621 case 0xA5:
10622 case 0xA6:
10623 case 0xA7:
10624 case 0xA8:
10625 case 0xA9:
10626 case 0xAA:
10627 case 0xAB:
10628 case 0xAC:
10629 case 0xAD:
10630 case 0xAE:
10631 case 0xAF:
10632 case 0xB0:
10633 case 0xB1:
10634 case 0xB2:
10635 case 0xB3:
10636 case 0xB4:
10637 case 0xB5:
10638 case 0xB6:
10639 case 0xB7:
10640 case 0xB8:
10641 case 0xB9:
10642 case 0xBA:
10643 case 0xBB:
10644 case 0xBC:
10645 case 0xBD:
10646 case 0xBE:
10647 case 0xBF:
10648 case 0xD9: // str 8
10649 case 0xDA: // str 16
10650 case 0xDB: // str 32
10651 {
10652 string_t s;
10653 return get_msgpack_string(s) && sax->string(s);
10654 }
10655
10656 case 0xC0: // nil
10657 return sax->null();
10658
10659 case 0xC2: // false
10660 return sax->boolean(false);
10661
10662 case 0xC3: // true
10663 return sax->boolean(true);
10664
10665 case 0xC4: // bin 8
10666 case 0xC5: // bin 16
10667 case 0xC6: // bin 32
10668 case 0xC7: // ext 8
10669 case 0xC8: // ext 16
10670 case 0xC9: // ext 32
10671 case 0xD4: // fixext 1
10672 case 0xD5: // fixext 2
10673 case 0xD6: // fixext 4
10674 case 0xD7: // fixext 8
10675 case 0xD8: // fixext 16
10676 {
10677 binary_t b;
10678 return get_msgpack_binary(b) && sax->binary(b);
10679 }
10680
10681 case 0xCA: // float 32
10682 {
10683 float number{};
10684 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10685 }
10686
10687 case 0xCB: // float 64
10688 {
10689 double number{};
10690 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10691 }
10692
10693 case 0xCC: // uint 8
10694 {
10695 std::uint8_t number{};
10696 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10697 }
10698
10699 case 0xCD: // uint 16
10700 {
10701 std::uint16_t number{};
10702 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10703 }
10704
10705 case 0xCE: // uint 32
10706 {
10707 std::uint32_t number{};
10708 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10709 }
10710
10711 case 0xCF: // uint 64
10712 {
10713 std::uint64_t number{};
10714 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10715 }
10716
10717 case 0xD0: // int 8
10718 {
10719 std::int8_t number{};
10720 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10721 }
10722
10723 case 0xD1: // int 16
10724 {
10725 std::int16_t number{};
10726 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10727 }
10728
10729 case 0xD2: // int 32
10730 {
10731 std::int32_t number{};
10732 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10733 }
10734
10735 case 0xD3: // int 64
10736 {
10737 std::int64_t number{};
10738 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10739 }
10740
10741 case 0xDC: // array 16
10742 {
10743 std::uint16_t len{};
10744 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
10745 }
10746
10747 case 0xDD: // array 32
10748 {
10749 std::uint32_t len{};
10750 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10751 }
10752
10753 case 0xDE: // map 16
10754 {
10755 std::uint16_t len{};
10756 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
10757 }
10758
10759 case 0xDF: // map 32
10760 {
10761 std::uint32_t len{};
10762 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10763 }
10764
10765 // negative fixint
10766 case 0xE0:
10767 case 0xE1:
10768 case 0xE2:
10769 case 0xE3:
10770 case 0xE4:
10771 case 0xE5:
10772 case 0xE6:
10773 case 0xE7:
10774 case 0xE8:
10775 case 0xE9:
10776 case 0xEA:
10777 case 0xEB:
10778 case 0xEC:
10779 case 0xED:
10780 case 0xEE:
10781 case 0xEF:
10782 case 0xF0:
10783 case 0xF1:
10784 case 0xF2:
10785 case 0xF3:
10786 case 0xF4:
10787 case 0xF5:
10788 case 0xF6:
10789 case 0xF7:
10790 case 0xF8:
10791 case 0xF9:
10792 case 0xFA:
10793 case 0xFB:
10794 case 0xFC:
10795 case 0xFD:
10796 case 0xFE:
10797 case 0xFF:
10798 return sax->number_integer(static_cast<std::int8_t>(current));
10799
10800 default: // anything else
10801 {
10802 auto last_token = get_token_string();
10803 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10804 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
10805 }
10806 }
10807 }
10808
10819 bool get_msgpack_string(string_t& result)
10820 {
10821 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
10822 {
10823 return false;
10824 }
10825
10826 switch (current)
10827 {
10828 // fixstr
10829 case 0xA0:
10830 case 0xA1:
10831 case 0xA2:
10832 case 0xA3:
10833 case 0xA4:
10834 case 0xA5:
10835 case 0xA6:
10836 case 0xA7:
10837 case 0xA8:
10838 case 0xA9:
10839 case 0xAA:
10840 case 0xAB:
10841 case 0xAC:
10842 case 0xAD:
10843 case 0xAE:
10844 case 0xAF:
10845 case 0xB0:
10846 case 0xB1:
10847 case 0xB2:
10848 case 0xB3:
10849 case 0xB4:
10850 case 0xB5:
10851 case 0xB6:
10852 case 0xB7:
10853 case 0xB8:
10854 case 0xB9:
10855 case 0xBA:
10856 case 0xBB:
10857 case 0xBC:
10858 case 0xBD:
10859 case 0xBE:
10860 case 0xBF:
10861 {
10862 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
10863 }
10864
10865 case 0xD9: // str 8
10866 {
10867 std::uint8_t len{};
10868 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10869 }
10870
10871 case 0xDA: // str 16
10872 {
10873 std::uint16_t len{};
10874 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10875 }
10876
10877 case 0xDB: // str 32
10878 {
10879 std::uint32_t len{};
10880 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10881 }
10882
10883 default:
10884 {
10885 auto last_token = get_token_string();
10886 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10887 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
10888 }
10889 }
10890 }
10891
10902 bool get_msgpack_binary(binary_t& result)
10903 {
10904 // helper function to set the subtype
10905 auto assign_and_return_true = [&result](std::int8_t subtype)
10906 {
10907 result.set_subtype(static_cast<std::uint8_t>(subtype));
10908 return true;
10909 };
10910
10911 switch (current)
10912 {
10913 case 0xC4: // bin 8
10914 {
10915 std::uint8_t len{};
10916 return get_number(input_format_t::msgpack, len) &&
10917 get_binary(input_format_t::msgpack, len, result);
10918 }
10919
10920 case 0xC5: // bin 16
10921 {
10922 std::uint16_t len{};
10923 return get_number(input_format_t::msgpack, len) &&
10924 get_binary(input_format_t::msgpack, len, result);
10925 }
10926
10927 case 0xC6: // bin 32
10928 {
10929 std::uint32_t len{};
10930 return get_number(input_format_t::msgpack, len) &&
10931 get_binary(input_format_t::msgpack, len, result);
10932 }
10933
10934 case 0xC7: // ext 8
10935 {
10936 std::uint8_t len{};
10937 std::int8_t subtype{};
10938 return get_number(input_format_t::msgpack, len) &&
10939 get_number(input_format_t::msgpack, subtype) &&
10940 get_binary(input_format_t::msgpack, len, result) &&
10941 assign_and_return_true(subtype);
10942 }
10943
10944 case 0xC8: // ext 16
10945 {
10946 std::uint16_t len{};
10947 std::int8_t subtype{};
10948 return get_number(input_format_t::msgpack, len) &&
10949 get_number(input_format_t::msgpack, subtype) &&
10950 get_binary(input_format_t::msgpack, len, result) &&
10951 assign_and_return_true(subtype);
10952 }
10953
10954 case 0xC9: // ext 32
10955 {
10956 std::uint32_t len{};
10957 std::int8_t subtype{};
10958 return get_number(input_format_t::msgpack, len) &&
10959 get_number(input_format_t::msgpack, subtype) &&
10960 get_binary(input_format_t::msgpack, len, result) &&
10961 assign_and_return_true(subtype);
10962 }
10963
10964 case 0xD4: // fixext 1
10965 {
10966 std::int8_t subtype{};
10967 return get_number(input_format_t::msgpack, subtype) &&
10968 get_binary(input_format_t::msgpack, 1, result) &&
10969 assign_and_return_true(subtype);
10970 }
10971
10972 case 0xD5: // fixext 2
10973 {
10974 std::int8_t subtype{};
10975 return get_number(input_format_t::msgpack, subtype) &&
10976 get_binary(input_format_t::msgpack, 2, result) &&
10977 assign_and_return_true(subtype);
10978 }
10979
10980 case 0xD6: // fixext 4
10981 {
10982 std::int8_t subtype{};
10983 return get_number(input_format_t::msgpack, subtype) &&
10984 get_binary(input_format_t::msgpack, 4, result) &&
10985 assign_and_return_true(subtype);
10986 }
10987
10988 case 0xD7: // fixext 8
10989 {
10990 std::int8_t subtype{};
10991 return get_number(input_format_t::msgpack, subtype) &&
10992 get_binary(input_format_t::msgpack, 8, result) &&
10993 assign_and_return_true(subtype);
10994 }
10995
10996 case 0xD8: // fixext 16
10997 {
10998 std::int8_t subtype{};
10999 return get_number(input_format_t::msgpack, subtype) &&
11000 get_binary(input_format_t::msgpack, 16, result) &&
11001 assign_and_return_true(subtype);
11002 }
11003
11004 default: // LCOV_EXCL_LINE
11005 return false; // LCOV_EXCL_LINE
11006 }
11007 }
11008
11013 bool get_msgpack_array(const std::size_t len)
11014 {
11015 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
11016 {
11017 return false;
11018 }
11019
11020 for (std::size_t i = 0; i < len; ++i)
11021 {
11022 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11023 {
11024 return false;
11025 }
11026 }
11027
11028 return sax->end_array();
11029 }
11030
11035 bool get_msgpack_object(const std::size_t len)
11036 {
11037 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
11038 {
11039 return false;
11040 }
11041
11042 string_t key;
11043 for (std::size_t i = 0; i < len; ++i)
11044 {
11045 get();
11046 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
11047 {
11048 return false;
11049 }
11050
11051 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11052 {
11053 return false;
11054 }
11055 key.clear();
11056 }
11057
11058 return sax->end_object();
11059 }
11060
11062 // UBJSON //
11064
11072 bool parse_ubjson_internal(const bool get_char = true)
11073 {
11074 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11075 }
11076
11091 bool get_ubjson_string(string_t& result, const bool get_char = true)
11092 {
11093 if (get_char)
11094 {
11095 get(); // TODO(niels): may we ignore N here?
11096 }
11097
11098 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11099 {
11100 return false;
11101 }
11102
11103 switch (current)
11104 {
11105 case 'U':
11106 {
11107 std::uint8_t len{};
11108 return get_number(input_format, len) && get_string(input_format, len, result);
11109 }
11110
11111 case 'i':
11112 {
11113 std::int8_t len{};
11114 return get_number(input_format, len) && get_string(input_format, len, result);
11115 }
11116
11117 case 'I':
11118 {
11119 std::int16_t len{};
11120 return get_number(input_format, len) && get_string(input_format, len, result);
11121 }
11122
11123 case 'l':
11124 {
11125 std::int32_t len{};
11126 return get_number(input_format, len) && get_string(input_format, len, result);
11127 }
11128
11129 case 'L':
11130 {
11131 std::int64_t len{};
11132 return get_number(input_format, len) && get_string(input_format, len, result);
11133 }
11134
11135 case 'u':
11136 {
11137 if (input_format != input_format_t::bjdata)
11138 {
11139 break;
11140 }
11141 std::uint16_t len{};
11142 return get_number(input_format, len) && get_string(input_format, len, result);
11143 }
11144
11145 case 'm':
11146 {
11147 if (input_format != input_format_t::bjdata)
11148 {
11149 break;
11150 }
11151 std::uint32_t len{};
11152 return get_number(input_format, len) && get_string(input_format, len, result);
11153 }
11154
11155 case 'M':
11156 {
11157 if (input_format != input_format_t::bjdata)
11158 {
11159 break;
11160 }
11161 std::uint64_t len{};
11162 return get_number(input_format, len) && get_string(input_format, len, result);
11163 }
11164
11165 default:
11166 break;
11167 }
11168 auto last_token = get_token_string();
11169 std::string message;
11170
11171 if (input_format != input_format_t::bjdata)
11172 {
11173 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11174 }
11175 else
11176 {
11177 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11178 }
11179 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11180 }
11181
11186 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11187 {
11188 std::pair<std::size_t, char_int_type> size_and_type;
11189 size_t dimlen = 0;
11190 bool no_ndarray = true;
11191
11192 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11193 {
11194 return false;
11195 }
11196
11197 if (size_and_type.first != npos)
11198 {
11199 if (size_and_type.second != 0)
11200 {
11201 if (size_and_type.second != 'N')
11202 {
11203 for (std::size_t i = 0; i < size_and_type.first; ++i)
11204 {
11205 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11206 {
11207 return false;
11208 }
11209 dim.push_back(dimlen);
11210 }
11211 }
11212 }
11213 else
11214 {
11215 for (std::size_t i = 0; i < size_and_type.first; ++i)
11216 {
11217 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11218 {
11219 return false;
11220 }
11221 dim.push_back(dimlen);
11222 }
11223 }
11224 }
11225 else
11226 {
11227 while (current != ']')
11228 {
11229 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11230 {
11231 return false;
11232 }
11233 dim.push_back(dimlen);
11234 get_ignore_noop();
11235 }
11236 }
11237 return true;
11238 }
11239
11251 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11252 {
11253 if (prefix == 0)
11254 {
11255 prefix = get_ignore_noop();
11256 }
11257
11258 switch (prefix)
11259 {
11260 case 'U':
11261 {
11262 std::uint8_t number{};
11263 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11264 {
11265 return false;
11266 }
11267 result = static_cast<std::size_t>(number);
11268 return true;
11269 }
11270
11271 case 'i':
11272 {
11273 std::int8_t number{};
11274 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11275 {
11276 return false;
11277 }
11278 if (number < 0)
11279 {
11280 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11281 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11282 }
11283 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11284 return true;
11285 }
11286
11287 case 'I':
11288 {
11289 std::int16_t number{};
11290 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11291 {
11292 return false;
11293 }
11294 if (number < 0)
11295 {
11296 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11297 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11298 }
11299 result = static_cast<std::size_t>(number);
11300 return true;
11301 }
11302
11303 case 'l':
11304 {
11305 std::int32_t number{};
11306 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11307 {
11308 return false;
11309 }
11310 if (number < 0)
11311 {
11312 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11313 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11314 }
11315 result = static_cast<std::size_t>(number);
11316 return true;
11317 }
11318
11319 case 'L':
11320 {
11321 std::int64_t number{};
11322 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11323 {
11324 return false;
11325 }
11326 if (number < 0)
11327 {
11328 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11329 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11330 }
11331 if (!value_in_range_of<std::size_t>(number))
11332 {
11333 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11334 exception_message(input_format, "integer value overflow", "size"), nullptr));
11335 }
11336 result = static_cast<std::size_t>(number);
11337 return true;
11338 }
11339
11340 case 'u':
11341 {
11342 if (input_format != input_format_t::bjdata)
11343 {
11344 break;
11345 }
11346 std::uint16_t number{};
11347 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11348 {
11349 return false;
11350 }
11351 result = static_cast<std::size_t>(number);
11352 return true;
11353 }
11354
11355 case 'm':
11356 {
11357 if (input_format != input_format_t::bjdata)
11358 {
11359 break;
11360 }
11361 std::uint32_t number{};
11362 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11363 {
11364 return false;
11365 }
11366 result = conditional_static_cast<std::size_t>(number);
11367 return true;
11368 }
11369
11370 case 'M':
11371 {
11372 if (input_format != input_format_t::bjdata)
11373 {
11374 break;
11375 }
11376 std::uint64_t number{};
11377 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11378 {
11379 return false;
11380 }
11381 if (!value_in_range_of<std::size_t>(number))
11382 {
11383 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11384 exception_message(input_format, "integer value overflow", "size"), nullptr));
11385 }
11386 result = detail::conditional_static_cast<std::size_t>(number);
11387 return true;
11388 }
11389
11390 case '[':
11391 {
11392 if (input_format != input_format_t::bjdata)
11393 {
11394 break;
11395 }
11396 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11397 {
11398 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));
11399 }
11400 std::vector<size_t> dim;
11401 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11402 {
11403 return false;
11404 }
11405 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11406 {
11407 result = dim.at(dim.size() - 1);
11408 return true;
11409 }
11410 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11411 {
11412 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11413 {
11414 if ( i == 0 )
11415 {
11416 result = 0;
11417 return true;
11418 }
11419 }
11420
11421 string_t key = "_ArraySize_";
11422 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11423 {
11424 return false;
11425 }
11426 result = 1;
11427 for (auto i : dim)
11428 {
11429 result *= i;
11430 if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type()
11431 {
11432 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));
11433 }
11434 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11435 {
11436 return false;
11437 }
11438 }
11439 is_ndarray = true;
11440 return sax->end_array();
11441 }
11442 result = 0;
11443 return true;
11444 }
11445
11446 default:
11447 break;
11448 }
11449 auto last_token = get_token_string();
11450 std::string message;
11451
11452 if (input_format != input_format_t::bjdata)
11453 {
11454 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11455 }
11456 else
11457 {
11458 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11459 }
11460 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
11461 }
11462
11474 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
11475 {
11476 result.first = npos; // size
11477 result.second = 0; // type
11478 bool is_ndarray = false;
11479
11480 get_ignore_noop();
11481
11482 if (current == '$')
11483 {
11484 result.second = get(); // must not ignore 'N', because 'N' maybe the type
11485 if (input_format == input_format_t::bjdata
11486 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
11487 {
11488 auto last_token = get_token_string();
11489 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11490 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
11491 }
11492
11493 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
11494 {
11495 return false;
11496 }
11497
11498 get_ignore_noop();
11499 if (JSON_HEDLEY_UNLIKELY(current != '#'))
11500 {
11501 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11502 {
11503 return false;
11504 }
11505 auto last_token = get_token_string();
11506 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11507 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
11508 }
11509
11510 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11511 if (input_format == input_format_t::bjdata && is_ndarray)
11512 {
11513 if (inside_ndarray)
11514 {
11515 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11516 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
11517 }
11518 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
11519 }
11520 return is_error;
11521 }
11522
11523 if (current == '#')
11524 {
11525 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11526 if (input_format == input_format_t::bjdata && is_ndarray)
11527 {
11528 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11529 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
11530 }
11531 return is_error;
11532 }
11533
11534 return true;
11535 }
11536
11541 bool get_ubjson_value(const char_int_type prefix)
11542 {
11543 switch (prefix)
11544 {
11545 case char_traits<char_type>::eof(): // EOF
11546 return unexpect_eof(input_format, "value");
11547
11548 case 'T': // true
11549 return sax->boolean(true);
11550 case 'F': // false
11551 return sax->boolean(false);
11552
11553 case 'Z': // null
11554 return sax->null();
11555
11556 case 'U':
11557 {
11558 std::uint8_t number{};
11559 return get_number(input_format, number) && sax->number_unsigned(number);
11560 }
11561
11562 case 'i':
11563 {
11564 std::int8_t number{};
11565 return get_number(input_format, number) && sax->number_integer(number);
11566 }
11567
11568 case 'I':
11569 {
11570 std::int16_t number{};
11571 return get_number(input_format, number) && sax->number_integer(number);
11572 }
11573
11574 case 'l':
11575 {
11576 std::int32_t number{};
11577 return get_number(input_format, number) && sax->number_integer(number);
11578 }
11579
11580 case 'L':
11581 {
11582 std::int64_t number{};
11583 return get_number(input_format, number) && sax->number_integer(number);
11584 }
11585
11586 case 'u':
11587 {
11588 if (input_format != input_format_t::bjdata)
11589 {
11590 break;
11591 }
11592 std::uint16_t number{};
11593 return get_number(input_format, number) && sax->number_unsigned(number);
11594 }
11595
11596 case 'm':
11597 {
11598 if (input_format != input_format_t::bjdata)
11599 {
11600 break;
11601 }
11602 std::uint32_t number{};
11603 return get_number(input_format, number) && sax->number_unsigned(number);
11604 }
11605
11606 case 'M':
11607 {
11608 if (input_format != input_format_t::bjdata)
11609 {
11610 break;
11611 }
11612 std::uint64_t number{};
11613 return get_number(input_format, number) && sax->number_unsigned(number);
11614 }
11615
11616 case 'h':
11617 {
11618 if (input_format != input_format_t::bjdata)
11619 {
11620 break;
11621 }
11622 const auto byte1_raw = get();
11623 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11624 {
11625 return false;
11626 }
11627 const auto byte2_raw = get();
11628 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11629 {
11630 return false;
11631 }
11632
11633 const auto byte1 = static_cast<unsigned char>(byte1_raw);
11634 const auto byte2 = static_cast<unsigned char>(byte2_raw);
11635
11636 // code from RFC 7049, Appendix D, Figure 3:
11637 // As half-precision floating-point numbers were only added
11638 // to IEEE 754 in 2008, today's programming platforms often
11639 // still only have limited support for them. It is very
11640 // easy to include at least decoding support for them even
11641 // without such support. An example of a small decoder for
11642 // half-precision floating-point numbers in the C language
11643 // is shown in Fig. 3.
11644 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11645 const double val = [&half]
11646 {
11647 const int exp = (half >> 10u) & 0x1Fu;
11648 const unsigned int mant = half & 0x3FFu;
11649 JSON_ASSERT(0 <= exp&& exp <= 32);
11650 JSON_ASSERT(mant <= 1024);
11651 switch (exp)
11652 {
11653 case 0:
11654 return std::ldexp(mant, -24);
11655 case 31:
11656 return (mant == 0)
11657 ? std::numeric_limits<double>::infinity()
11658 : std::numeric_limits<double>::quiet_NaN();
11659 default:
11660 return std::ldexp(mant + 1024, exp - 25);
11661 }
11662 }();
11663 return sax->number_float((half & 0x8000u) != 0
11664 ? static_cast<number_float_t>(-val)
11665 : static_cast<number_float_t>(val), "");
11666 }
11667
11668 case 'd':
11669 {
11670 float number{};
11671 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11672 }
11673
11674 case 'D':
11675 {
11676 double number{};
11677 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11678 }
11679
11680 case 'H':
11681 {
11682 return get_ubjson_high_precision_number();
11683 }
11684
11685 case 'C': // char
11686 {
11687 get();
11688 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
11689 {
11690 return false;
11691 }
11692 if (JSON_HEDLEY_UNLIKELY(current > 127))
11693 {
11694 auto last_token = get_token_string();
11695 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11696 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
11697 }
11698 string_t s(1, static_cast<typename string_t::value_type>(current));
11699 return sax->string(s);
11700 }
11701
11702 case 'S': // string
11703 {
11704 string_t s;
11705 return get_ubjson_string(s) && sax->string(s);
11706 }
11707
11708 case '[': // array
11709 return get_ubjson_array();
11710
11711 case '{': // object
11712 return get_ubjson_object();
11713
11714 default: // anything else
11715 break;
11716 }
11717 auto last_token = get_token_string();
11718 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));
11719 }
11720
11724 bool get_ubjson_array()
11725 {
11726 std::pair<std::size_t, char_int_type> size_and_type;
11727 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11728 {
11729 return false;
11730 }
11731
11732 // 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):
11733 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
11734
11735 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11736 {
11737 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
11738 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)
11739 {
11740 return p.first < t;
11741 });
11742 string_t key = "_ArrayType_";
11743 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
11744 {
11745 auto last_token = get_token_string();
11746 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11747 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
11748 }
11749
11750 string_t type = it->second; // sax->string() takes a reference
11751 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
11752 {
11753 return false;
11754 }
11755
11756 if (size_and_type.second == 'C')
11757 {
11758 size_and_type.second = 'U';
11759 }
11760
11761 key = "_ArrayData_";
11762 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
11763 {
11764 return false;
11765 }
11766
11767 for (std::size_t i = 0; i < size_and_type.first; ++i)
11768 {
11769 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11770 {
11771 return false;
11772 }
11773 }
11774
11775 return (sax->end_array() && sax->end_object());
11776 }
11777
11778 if (size_and_type.first != npos)
11779 {
11780 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
11781 {
11782 return false;
11783 }
11784
11785 if (size_and_type.second != 0)
11786 {
11787 if (size_and_type.second != 'N')
11788 {
11789 for (std::size_t i = 0; i < size_and_type.first; ++i)
11790 {
11791 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11792 {
11793 return false;
11794 }
11795 }
11796 }
11797 }
11798 else
11799 {
11800 for (std::size_t i = 0; i < size_and_type.first; ++i)
11801 {
11802 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11803 {
11804 return false;
11805 }
11806 }
11807 }
11808 }
11809 else
11810 {
11811 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
11812 {
11813 return false;
11814 }
11815
11816 while (current != ']')
11817 {
11818 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
11819 {
11820 return false;
11821 }
11822 get_ignore_noop();
11823 }
11824 }
11825
11826 return sax->end_array();
11827 }
11828
11832 bool get_ubjson_object()
11833 {
11834 std::pair<std::size_t, char_int_type> size_and_type;
11835 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11836 {
11837 return false;
11838 }
11839
11840 // do not accept ND-array size in objects in BJData
11841 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11842 {
11843 auto last_token = get_token_string();
11844 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11845 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
11846 }
11847
11848 string_t key;
11849 if (size_and_type.first != npos)
11850 {
11851 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
11852 {
11853 return false;
11854 }
11855
11856 if (size_and_type.second != 0)
11857 {
11858 for (std::size_t i = 0; i < size_and_type.first; ++i)
11859 {
11860 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11861 {
11862 return false;
11863 }
11864 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11865 {
11866 return false;
11867 }
11868 key.clear();
11869 }
11870 }
11871 else
11872 {
11873 for (std::size_t i = 0; i < size_and_type.first; ++i)
11874 {
11875 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11876 {
11877 return false;
11878 }
11879 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11880 {
11881 return false;
11882 }
11883 key.clear();
11884 }
11885 }
11886 }
11887 else
11888 {
11889 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
11890 {
11891 return false;
11892 }
11893
11894 while (current != '}')
11895 {
11896 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
11897 {
11898 return false;
11899 }
11900 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11901 {
11902 return false;
11903 }
11904 get_ignore_noop();
11905 key.clear();
11906 }
11907 }
11908
11909 return sax->end_object();
11910 }
11911
11912 // Note, no reader for UBJSON binary types is implemented because they do
11913 // not exist
11914
11915 bool get_ubjson_high_precision_number()
11916 {
11917 // get size of following number string
11918 std::size_t size{};
11919 bool no_ndarray = true;
11920 auto res = get_ubjson_size_value(size, no_ndarray);
11921 if (JSON_HEDLEY_UNLIKELY(!res))
11922 {
11923 return res;
11924 }
11925
11926 // get number string
11927 std::vector<char> number_vector;
11928 for (std::size_t i = 0; i < size; ++i)
11929 {
11930 get();
11931 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11932 {
11933 return false;
11934 }
11935 number_vector.push_back(static_cast<char>(current));
11936 }
11937
11938 // parse number string
11939 using ia_type = decltype(detail::input_adapter(number_vector));
11940 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11941 const auto result_number = number_lexer.scan();
11942 const auto number_string = number_lexer.get_token_string();
11943 const auto result_remainder = number_lexer.scan();
11944
11946
11947 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
11948 {
11949 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11950 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11951 }
11952
11953 switch (result_number)
11954 {
11955 case token_type::value_integer:
11956 return sax->number_integer(number_lexer.get_number_integer());
11957 case token_type::value_unsigned:
11958 return sax->number_unsigned(number_lexer.get_number_unsigned());
11959 case token_type::value_float:
11960 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11961 case token_type::uninitialized:
11962 case token_type::literal_true:
11963 case token_type::literal_false:
11964 case token_type::literal_null:
11965 case token_type::value_string:
11966 case token_type::begin_array:
11967 case token_type::begin_object:
11968 case token_type::end_array:
11969 case token_type::end_object:
11970 case token_type::name_separator:
11971 case token_type::value_separator:
11972 case token_type::parse_error:
11973 case token_type::end_of_input:
11974 case token_type::literal_or_value:
11975 default:
11976 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11977 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11978 }
11979 }
11980
11982 // Utility functions //
11984
11994 char_int_type get()
11995 {
11996 ++chars_read;
11997 return current = ia.get_character();
11998 }
11999
12003 char_int_type get_ignore_noop()
12004 {
12005 do
12006 {
12007 get();
12008 }
12009 while (current == 'N');
12010
12011 return current;
12012 }
12013
12014 /*
12015 @brief read a number from the input
12016
12017 @tparam NumberType the type of the number
12018 @param[in] format the current format (for diagnostics)
12019 @param[out] result number of type @a NumberType
12020
12021 @return whether conversion completed
12022
12023 @note This function needs to respect the system's endianness, because
12024 bytes in CBOR, MessagePack, and UBJSON are stored in network order
12025 (big endian) and therefore need reordering on little endian systems.
12026 On the other hand, BSON and BJData use little endian and should reorder
12027 on big endian systems.
12028 */
12029 template<typename NumberType, bool InputIsLittleEndian = false>
12030 bool get_number(const input_format_t format, NumberType& result)
12031 {
12032 // step 1: read input into array with system's byte order
12033 std::array<std::uint8_t, sizeof(NumberType)> vec{};
12034 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
12035 {
12036 get();
12037 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
12038 {
12039 return false;
12040 }
12041
12042 // reverse byte order prior to conversion if necessary
12043 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
12044 {
12045 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
12046 }
12047 else
12048 {
12049 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
12050 }
12051 }
12052
12053 // step 2: convert array into number of type T and return
12054 std::memcpy(&result, vec.data(), sizeof(NumberType));
12055 return true;
12056 }
12057
12072 template<typename NumberType>
12073 bool get_string(const input_format_t format,
12074 const NumberType len,
12075 string_t& result)
12076 {
12077 bool success = true;
12078 for (NumberType i = 0; i < len; i++)
12079 {
12080 get();
12081 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
12082 {
12083 success = false;
12084 break;
12085 }
12086 result.push_back(static_cast<typename string_t::value_type>(current));
12087 }
12088 return success;
12089 }
12090
12105 template<typename NumberType>
12106 bool get_binary(const input_format_t format,
12107 const NumberType len,
12108 binary_t& result)
12109 {
12110 bool success = true;
12111 for (NumberType i = 0; i < len; i++)
12112 {
12113 get();
12114 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12115 {
12116 success = false;
12117 break;
12118 }
12119 result.push_back(static_cast<std::uint8_t>(current));
12120 }
12121 return success;
12122 }
12123
12130 bool unexpect_eof(const input_format_t format, const char* context) const
12131 {
12132 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12133 {
12134 return sax->parse_error(chars_read, "<end of file>",
12135 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12136 }
12137 return true;
12138 }
12139
12143 std::string get_token_string() const
12144 {
12145 std::array<char, 3> cr{{}};
12146 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12147 return std::string{cr.data()};
12148 }
12149
12156 std::string exception_message(const input_format_t format,
12157 const std::string& detail,
12158 const std::string& context) const
12159 {
12160 std::string error_msg = "syntax error while parsing ";
12161
12162 switch (format)
12163 {
12165 error_msg += "CBOR";
12166 break;
12167
12169 error_msg += "MessagePack";
12170 break;
12171
12173 error_msg += "UBJSON";
12174 break;
12175
12177 error_msg += "BSON";
12178 break;
12179
12181 error_msg += "BJData";
12182 break;
12183
12184 case input_format_t::json: // LCOV_EXCL_LINE
12185 default: // LCOV_EXCL_LINE
12186 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12187 }
12188
12189 return concat(error_msg, ' ', context, ": ", detail);
12190 }
12191
12192 private:
12193 static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
12194
12196 InputAdapterType ia;
12197
12199 char_int_type current = char_traits<char_type>::eof();
12200
12202 std::size_t chars_read = 0;
12203
12205 const bool is_little_endian = little_endianness();
12206
12208 const input_format_t input_format = input_format_t::json;
12209
12211 json_sax_t* sax = nullptr;
12212
12213 // excluded markers in bjdata optimized type
12214#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12215 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12216
12217#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12218 make_array<bjd_type>( \
12219 bjd_type{'C', "char"}, \
12220 bjd_type{'D', "double"}, \
12221 bjd_type{'I', "int16"}, \
12222 bjd_type{'L', "int64"}, \
12223 bjd_type{'M', "uint64"}, \
12224 bjd_type{'U', "uint8"}, \
12225 bjd_type{'d', "single"}, \
12226 bjd_type{'i', "int8"}, \
12227 bjd_type{'l', "int32"}, \
12228 bjd_type{'m', "uint32"}, \
12229 bjd_type{'u', "uint16"})
12230
12232 // lookup tables
12233 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12234 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12236
12237 using bjd_type = std::pair<char_int_type, string_t>;
12238 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12239 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12241
12242#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12243#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12244};
12245
12246#ifndef JSON_HAS_CPP_17
12247 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12248 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12249#endif
12250
12251} // namespace detail
12253
12254// #include <nlohmann/detail/input/input_adapters.hpp>
12255
12256// #include <nlohmann/detail/input/lexer.hpp>
12257
12258// #include <nlohmann/detail/input/parser.hpp>
12259// __ _____ _____ _____
12260// __| | __| | | | JSON for Modern C++
12261// | | |__ | | | | | | version 3.11.3
12262// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12263//
12264// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12265// SPDX-License-Identifier: MIT
12266
12267
12268
12269#include <cmath> // isfinite
12270#include <cstdint> // uint8_t
12271#include <functional> // function
12272#include <string> // string
12273#include <utility> // move
12274#include <vector> // vector
12275
12276// #include <nlohmann/detail/exceptions.hpp>
12277
12278// #include <nlohmann/detail/input/input_adapters.hpp>
12279
12280// #include <nlohmann/detail/input/json_sax.hpp>
12281
12282// #include <nlohmann/detail/input/lexer.hpp>
12283
12284// #include <nlohmann/detail/macro_scope.hpp>
12285
12286// #include <nlohmann/detail/meta/is_sax.hpp>
12287
12288// #include <nlohmann/detail/string_concat.hpp>
12289
12290// #include <nlohmann/detail/value_t.hpp>
12291
12292
12294namespace detail
12295{
12297// parser //
12299
12300enum class parse_event_t : std::uint8_t
12301{
12305 object_end,
12309 array_end,
12311 key,
12313 value
12314};
12315
12316template<typename BasicJsonType>
12318 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12319
12325template<typename BasicJsonType, typename InputAdapterType>
12327{
12328 using number_integer_t = typename BasicJsonType::number_integer_t;
12329 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12330 using number_float_t = typename BasicJsonType::number_float_t;
12331 using string_t = typename BasicJsonType::string_t;
12333 using token_type = typename lexer_t::token_type;
12334
12335 public:
12337 explicit parser(InputAdapterType&& adapter,
12339 const bool allow_exceptions_ = true,
12340 const bool skip_comments = false)
12341 : callback(std::move(cb))
12342 , m_lexer(std::move(adapter), skip_comments)
12343 , allow_exceptions(allow_exceptions_)
12344 {
12345 // read first token
12346 get_token();
12347 }
12348
12359 void parse(const bool strict, BasicJsonType& result)
12360 {
12361 if (callback)
12362 {
12363 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
12364 sax_parse_internal(&sdp);
12365
12366 // in strict mode, input must be completely read
12367 if (strict && (get_token() != token_type::end_of_input))
12368 {
12369 sdp.parse_error(m_lexer.get_position(),
12370 m_lexer.get_token_string(),
12371 parse_error::create(101, m_lexer.get_position(),
12372 exception_message(token_type::end_of_input, "value"), nullptr));
12373 }
12374
12375 // in case of an error, return discarded value
12376 if (sdp.is_errored())
12377 {
12378 result = value_t::discarded;
12379 return;
12380 }
12381
12382 // set top-level value to null if it was discarded by the callback
12383 // function
12384 if (result.is_discarded())
12385 {
12386 result = nullptr;
12387 }
12388 }
12389 else
12390 {
12391 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
12392 sax_parse_internal(&sdp);
12393
12394 // in strict mode, input must be completely read
12395 if (strict && (get_token() != token_type::end_of_input))
12396 {
12397 sdp.parse_error(m_lexer.get_position(),
12398 m_lexer.get_token_string(),
12399 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12400 }
12401
12402 // in case of an error, return discarded value
12403 if (sdp.is_errored())
12404 {
12405 result = value_t::discarded;
12406 return;
12407 }
12408 }
12409
12410 result.assert_invariant();
12411 }
12412
12419 bool accept(const bool strict = true)
12420 {
12422 return sax_parse(&sax_acceptor, strict);
12423 }
12424
12425 template<typename SAX>
12427 bool sax_parse(SAX* sax, const bool strict = true)
12428 {
12430 const bool result = sax_parse_internal(sax);
12431
12432 // strict mode: next byte must be EOF
12433 if (result && strict && (get_token() != token_type::end_of_input))
12434 {
12435 return sax->parse_error(m_lexer.get_position(),
12436 m_lexer.get_token_string(),
12437 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12438 }
12439
12440 return result;
12441 }
12442
12443 private:
12444 template<typename SAX>
12446 bool sax_parse_internal(SAX* sax)
12447 {
12448 // stack to remember the hierarchy of structured values we are parsing
12449 // true = array; false = object
12450 std::vector<bool> states;
12451 // value to avoid a goto (see comment where set to true)
12452 bool skip_to_state_evaluation = false;
12453
12454 while (true)
12455 {
12456 if (!skip_to_state_evaluation)
12457 {
12458 // invariant: get_token() was called before each iteration
12459 switch (last_token)
12460 {
12461 case token_type::begin_object:
12462 {
12463 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
12464 {
12465 return false;
12466 }
12467
12468 // closing } -> we are done
12469 if (get_token() == token_type::end_object)
12470 {
12471 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12472 {
12473 return false;
12474 }
12475 break;
12476 }
12477
12478 // parse key
12479 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
12480 {
12481 return sax->parse_error(m_lexer.get_position(),
12482 m_lexer.get_token_string(),
12483 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12484 }
12485 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12486 {
12487 return false;
12488 }
12489
12490 // parse separator (:)
12491 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12492 {
12493 return sax->parse_error(m_lexer.get_position(),
12494 m_lexer.get_token_string(),
12495 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12496 }
12497
12498 // remember we are now inside an object
12499 states.push_back(false);
12500
12501 // parse values
12502 get_token();
12503 continue;
12504 }
12505
12506 case token_type::begin_array:
12507 {
12508 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
12509 {
12510 return false;
12511 }
12512
12513 // closing ] -> we are done
12514 if (get_token() == token_type::end_array)
12515 {
12516 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12517 {
12518 return false;
12519 }
12520 break;
12521 }
12522
12523 // remember we are now inside an array
12524 states.push_back(true);
12525
12526 // parse values (no need to call get_token)
12527 continue;
12528 }
12529
12530 case token_type::value_float:
12531 {
12532 const auto res = m_lexer.get_number_float();
12533
12534 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
12535 {
12536 return sax->parse_error(m_lexer.get_position(),
12537 m_lexer.get_token_string(),
12538 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
12539 }
12540
12541 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
12542 {
12543 return false;
12544 }
12545
12546 break;
12547 }
12548
12549 case token_type::literal_false:
12550 {
12551 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
12552 {
12553 return false;
12554 }
12555 break;
12556 }
12557
12558 case token_type::literal_null:
12559 {
12560 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
12561 {
12562 return false;
12563 }
12564 break;
12565 }
12566
12567 case token_type::literal_true:
12568 {
12569 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
12570 {
12571 return false;
12572 }
12573 break;
12574 }
12575
12576 case token_type::value_integer:
12577 {
12578 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
12579 {
12580 return false;
12581 }
12582 break;
12583 }
12584
12585 case token_type::value_string:
12586 {
12587 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
12588 {
12589 return false;
12590 }
12591 break;
12592 }
12593
12594 case token_type::value_unsigned:
12595 {
12596 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
12597 {
12598 return false;
12599 }
12600 break;
12601 }
12602
12603 case token_type::parse_error:
12604 {
12605 // using "uninitialized" to avoid "expected" message
12606 return sax->parse_error(m_lexer.get_position(),
12607 m_lexer.get_token_string(),
12608 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
12609 }
12610 case token_type::end_of_input:
12611 {
12613 {
12614 return sax->parse_error(m_lexer.get_position(),
12615 m_lexer.get_token_string(),
12616 parse_error::create(101, m_lexer.get_position(),
12617 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
12618 }
12619
12620 return sax->parse_error(m_lexer.get_position(),
12621 m_lexer.get_token_string(),
12622 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12623 }
12624 case token_type::uninitialized:
12625 case token_type::end_array:
12626 case token_type::end_object:
12627 case token_type::name_separator:
12628 case token_type::value_separator:
12629 case token_type::literal_or_value:
12630 default: // the last token was unexpected
12631 {
12632 return sax->parse_error(m_lexer.get_position(),
12633 m_lexer.get_token_string(),
12634 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12635 }
12636 }
12637 }
12638 else
12639 {
12640 skip_to_state_evaluation = false;
12641 }
12642
12643 // we reached this line after we successfully parsed a value
12644 if (states.empty())
12645 {
12646 // empty stack: we reached the end of the hierarchy: done
12647 return true;
12648 }
12649
12650 if (states.back()) // array
12651 {
12652 // comma -> next value
12653 if (get_token() == token_type::value_separator)
12654 {
12655 // parse a new value
12656 get_token();
12657 continue;
12658 }
12659
12660 // closing ]
12661 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
12662 {
12663 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12664 {
12665 return false;
12666 }
12667
12668 // We are done with this array. Before we can parse a
12669 // new value, we need to evaluate the new state first.
12670 // By setting skip_to_state_evaluation to false, we
12671 // are effectively jumping to the beginning of this if.
12672 JSON_ASSERT(!states.empty());
12673 states.pop_back();
12674 skip_to_state_evaluation = true;
12675 continue;
12676 }
12677
12678 return sax->parse_error(m_lexer.get_position(),
12679 m_lexer.get_token_string(),
12680 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
12681 }
12682
12683 // states.back() is false -> object
12684
12685 // comma -> next value
12686 if (get_token() == token_type::value_separator)
12687 {
12688 // parse key
12689 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
12690 {
12691 return sax->parse_error(m_lexer.get_position(),
12692 m_lexer.get_token_string(),
12693 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12694 }
12695
12696 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12697 {
12698 return false;
12699 }
12700
12701 // parse separator (:)
12702 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12703 {
12704 return sax->parse_error(m_lexer.get_position(),
12705 m_lexer.get_token_string(),
12706 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12707 }
12708
12709 // parse values
12710 get_token();
12711 continue;
12712 }
12713
12714 // closing }
12715 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
12716 {
12717 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12718 {
12719 return false;
12720 }
12721
12722 // We are done with this object. Before we can parse a
12723 // new value, we need to evaluate the new state first.
12724 // By setting skip_to_state_evaluation to false, we
12725 // are effectively jumping to the beginning of this if.
12726 JSON_ASSERT(!states.empty());
12727 states.pop_back();
12728 skip_to_state_evaluation = true;
12729 continue;
12730 }
12731
12732 return sax->parse_error(m_lexer.get_position(),
12733 m_lexer.get_token_string(),
12734 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
12735 }
12736 }
12737
12739 token_type get_token()
12740 {
12741 return last_token = m_lexer.scan();
12742 }
12743
12744 std::string exception_message(const token_type expected, const std::string& context)
12745 {
12746 std::string error_msg = "syntax error ";
12747
12748 if (!context.empty())
12749 {
12750 error_msg += concat("while parsing ", context, ' ');
12751 }
12752
12753 error_msg += "- ";
12754
12755 if (last_token == token_type::parse_error)
12756 {
12757 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12758 m_lexer.get_token_string(), '\'');
12759 }
12760 else
12761 {
12762 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12763 }
12764
12765 if (expected != token_type::uninitialized)
12766 {
12767 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12768 }
12769
12770 return error_msg;
12771 }
12772
12773 private:
12775 const parser_callback_t<BasicJsonType> callback = nullptr;
12777 token_type last_token = token_type::uninitialized;
12779 lexer_t m_lexer;
12781 const bool allow_exceptions = true;
12782};
12783
12784} // namespace detail
12786
12787// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12788// __ _____ _____ _____
12789// __| | __| | | | JSON for Modern C++
12790// | | |__ | | | | | | version 3.11.3
12791// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12792//
12793// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12794// SPDX-License-Identifier: MIT
12795
12796
12797
12798// #include <nlohmann/detail/abi_macros.hpp>
12799
12800// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12801// __ _____ _____ _____
12802// __| | __| | | | JSON for Modern C++
12803// | | |__ | | | | | | version 3.11.3
12804// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12805//
12806// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12807// SPDX-License-Identifier: MIT
12808
12809
12810
12811#include <cstddef> // ptrdiff_t
12812#include <limits> // numeric_limits
12813
12814// #include <nlohmann/detail/macro_scope.hpp>
12815
12816
12818namespace detail
12819{
12820
12821/*
12822@brief an iterator for primitive JSON types
12823
12824This class models an iterator for primitive JSON types (boolean, number,
12825string). It's only purpose is to allow the iterator/const_iterator classes
12826to "iterate" over primitive values. Internally, the iterator is modeled by
12827a `difference_type` variable. Value begin_value (`0`) models the begin,
12828end_value (`1`) models past the end.
12829*/
12831{
12832 private:
12833 using difference_type = std::ptrdiff_t;
12834 static constexpr difference_type begin_value = 0;
12835 static constexpr difference_type end_value = begin_value + 1;
12836
12839 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12840
12841 public:
12842 constexpr difference_type get_value() const noexcept
12843 {
12844 return m_it;
12845 }
12846
12848 void set_begin() noexcept
12849 {
12850 m_it = begin_value;
12851 }
12852
12854 void set_end() noexcept
12855 {
12856 m_it = end_value;
12857 }
12858
12860 constexpr bool is_begin() const noexcept
12861 {
12862 return m_it == begin_value;
12863 }
12864
12866 constexpr bool is_end() const noexcept
12867 {
12868 return m_it == end_value;
12869 }
12870
12871 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12872 {
12873 return lhs.m_it == rhs.m_it;
12874 }
12875
12876 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12877 {
12878 return lhs.m_it < rhs.m_it;
12879 }
12880
12881 primitive_iterator_t operator+(difference_type n) noexcept
12882 {
12883 auto result = *this;
12884 result += n;
12885 return result;
12886 }
12887
12888 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12889 {
12890 return lhs.m_it - rhs.m_it;
12891 }
12892
12894 {
12895 ++m_it;
12896 return *this;
12897 }
12898
12899 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
12900 {
12901 auto result = *this;
12902 ++m_it;
12903 return result;
12904 }
12905
12907 {
12908 --m_it;
12909 return *this;
12910 }
12911
12912 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
12913 {
12914 auto result = *this;
12915 --m_it;
12916 return result;
12917 }
12918
12919 primitive_iterator_t& operator+=(difference_type n) noexcept
12920 {
12921 m_it += n;
12922 return *this;
12923 }
12924
12925 primitive_iterator_t& operator-=(difference_type n) noexcept
12926 {
12927 m_it -= n;
12928 return *this;
12929 }
12930};
12931
12932} // namespace detail
12934
12935
12937namespace detail
12938{
12939
12946template<typename BasicJsonType> struct internal_iterator
12947{
12949 typename BasicJsonType::object_t::iterator object_iterator {};
12951 typename BasicJsonType::array_t::iterator array_iterator {};
12954};
12955
12956} // namespace detail
12958
12959// #include <nlohmann/detail/iterators/iter_impl.hpp>
12960// __ _____ _____ _____
12961// __| | __| | | | JSON for Modern C++
12962// | | |__ | | | | | | version 3.11.3
12963// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12964//
12965// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12966// SPDX-License-Identifier: MIT
12967
12968
12969
12970#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
12971#include <type_traits> // conditional, is_const, remove_const
12972
12973// #include <nlohmann/detail/exceptions.hpp>
12974
12975// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12976
12977// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12978
12979// #include <nlohmann/detail/macro_scope.hpp>
12980
12981// #include <nlohmann/detail/meta/cpp_future.hpp>
12982
12983// #include <nlohmann/detail/meta/type_traits.hpp>
12984
12985// #include <nlohmann/detail/value_t.hpp>
12986
12987
12989namespace detail
12990{
12991
12992// forward declare, to be able to friend it later on
12993template<typename IteratorType> class iteration_proxy;
12994template<typename IteratorType> class iteration_proxy_value;
12995
13012template<typename BasicJsonType>
13013class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
13014{
13016 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
13018 friend other_iter_impl;
13019 friend BasicJsonType;
13022
13023 using object_t = typename BasicJsonType::object_t;
13024 using array_t = typename BasicJsonType::array_t;
13025 // make sure BasicJsonType is basic_json or const basic_json
13027 "iter_impl only accepts (const) basic_json");
13028 // superficial check for the LegacyBidirectionalIterator named requirement
13029 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
13030 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
13031 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
13032
13033 public:
13039 using iterator_category = std::bidirectional_iterator_tag;
13040
13042 using value_type = typename BasicJsonType::value_type;
13044 using difference_type = typename BasicJsonType::difference_type;
13046 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
13047 typename BasicJsonType::const_pointer,
13048 typename BasicJsonType::pointer>::type;
13051 typename std::conditional<std::is_const<BasicJsonType>::value,
13052 typename BasicJsonType::const_reference,
13053 typename BasicJsonType::reference>::type;
13054
13055 iter_impl() = default;
13056 ~iter_impl() = default;
13057 iter_impl(iter_impl&&) noexcept = default;
13058 iter_impl& operator=(iter_impl&&) noexcept = default;
13059
13066 explicit iter_impl(pointer object) noexcept : m_object(object)
13067 {
13068 JSON_ASSERT(m_object != nullptr);
13069
13070 switch (m_object->m_data.m_type)
13071 {
13072 case value_t::object:
13073 {
13074 m_it.object_iterator = typename object_t::iterator();
13075 break;
13076 }
13077
13078 case value_t::array:
13079 {
13080 m_it.array_iterator = typename array_t::iterator();
13081 break;
13082 }
13083
13084 case value_t::null:
13085 case value_t::string:
13086 case value_t::boolean:
13090 case value_t::binary:
13091 case value_t::discarded:
13092 default:
13093 {
13095 break;
13096 }
13097 }
13098 }
13099
13117 : m_object(other.m_object), m_it(other.m_it)
13118 {}
13119
13127 {
13128 if (&other != this)
13129 {
13130 m_object = other.m_object;
13131 m_it = other.m_it;
13132 }
13133 return *this;
13134 }
13135
13141 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13142 : m_object(other.m_object), m_it(other.m_it)
13143 {}
13144
13151 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13152 {
13153 m_object = other.m_object;
13154 m_it = other.m_it;
13155 return *this;
13156 }
13157
13163 void set_begin() noexcept
13164 {
13165 JSON_ASSERT(m_object != nullptr);
13166
13167 switch (m_object->m_data.m_type)
13168 {
13169 case value_t::object:
13170 {
13171 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13172 break;
13173 }
13174
13175 case value_t::array:
13176 {
13177 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13178 break;
13179 }
13180
13181 case value_t::null:
13182 {
13183 // set to end so begin()==end() is true: null is empty
13185 break;
13186 }
13187
13188 case value_t::string:
13189 case value_t::boolean:
13193 case value_t::binary:
13194 case value_t::discarded:
13195 default:
13196 {
13198 break;
13199 }
13200 }
13201 }
13202
13207 void set_end() noexcept
13208 {
13209 JSON_ASSERT(m_object != nullptr);
13210
13211 switch (m_object->m_data.m_type)
13212 {
13213 case value_t::object:
13214 {
13215 m_it.object_iterator = m_object->m_data.m_value.object->end();
13216 break;
13217 }
13218
13219 case value_t::array:
13220 {
13221 m_it.array_iterator = m_object->m_data.m_value.array->end();
13222 break;
13223 }
13224
13225 case value_t::null:
13226 case value_t::string:
13227 case value_t::boolean:
13231 case value_t::binary:
13232 case value_t::discarded:
13233 default:
13234 {
13236 break;
13237 }
13238 }
13239 }
13240
13241 public:
13247 {
13248 JSON_ASSERT(m_object != nullptr);
13249
13250 switch (m_object->m_data.m_type)
13251 {
13252 case value_t::object:
13253 {
13254 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13255 return m_it.object_iterator->second;
13256 }
13257
13258 case value_t::array:
13259 {
13260 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13261 return *m_it.array_iterator;
13262 }
13263
13264 case value_t::null:
13265 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13266
13267 case value_t::string:
13268 case value_t::boolean:
13272 case value_t::binary:
13273 case value_t::discarded:
13274 default:
13275 {
13277 {
13278 return *m_object;
13279 }
13280
13281 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13282 }
13283 }
13284 }
13285
13291 {
13292 JSON_ASSERT(m_object != nullptr);
13293
13294 switch (m_object->m_data.m_type)
13295 {
13296 case value_t::object:
13297 {
13298 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13299 return &(m_it.object_iterator->second);
13300 }
13301
13302 case value_t::array:
13303 {
13304 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13305 return &*m_it.array_iterator;
13306 }
13307
13308 case value_t::null:
13309 case value_t::string:
13310 case value_t::boolean:
13314 case value_t::binary:
13315 case value_t::discarded:
13316 default:
13317 {
13319 {
13320 return m_object;
13321 }
13322
13323 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13324 }
13325 }
13326 }
13327
13332 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13333 {
13334 auto result = *this;
13335 ++(*this);
13336 return result;
13337 }
13338
13344 {
13345 JSON_ASSERT(m_object != nullptr);
13346
13347 switch (m_object->m_data.m_type)
13348 {
13349 case value_t::object:
13350 {
13351 std::advance(m_it.object_iterator, 1);
13352 break;
13353 }
13354
13355 case value_t::array:
13356 {
13357 std::advance(m_it.array_iterator, 1);
13358 break;
13359 }
13360
13361 case value_t::null:
13362 case value_t::string:
13363 case value_t::boolean:
13367 case value_t::binary:
13368 case value_t::discarded:
13369 default:
13370 {
13372 break;
13373 }
13374 }
13375
13376 return *this;
13377 }
13378
13383 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13384 {
13385 auto result = *this;
13386 --(*this);
13387 return result;
13388 }
13389
13395 {
13396 JSON_ASSERT(m_object != nullptr);
13397
13398 switch (m_object->m_data.m_type)
13399 {
13400 case value_t::object:
13401 {
13402 std::advance(m_it.object_iterator, -1);
13403 break;
13404 }
13405
13406 case value_t::array:
13407 {
13408 std::advance(m_it.array_iterator, -1);
13409 break;
13410 }
13411
13412 case value_t::null:
13413 case value_t::string:
13414 case value_t::boolean:
13418 case value_t::binary:
13419 case value_t::discarded:
13420 default:
13421 {
13423 break;
13424 }
13425 }
13426
13427 return *this;
13428 }
13429
13434 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 >
13435 bool operator==(const IterImpl& other) const
13436 {
13437 // if objects are not the same, the comparison is undefined
13438 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13439 {
13440 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13441 }
13442
13443 JSON_ASSERT(m_object != nullptr);
13444
13445 switch (m_object->m_data.m_type)
13446 {
13447 case value_t::object:
13448 return (m_it.object_iterator == other.m_it.object_iterator);
13449
13450 case value_t::array:
13451 return (m_it.array_iterator == other.m_it.array_iterator);
13452
13453 case value_t::null:
13454 case value_t::string:
13455 case value_t::boolean:
13459 case value_t::binary:
13460 case value_t::discarded:
13461 default:
13462 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
13463 }
13464 }
13465
13470 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 >
13471 bool operator!=(const IterImpl& other) const
13472 {
13473 return !operator==(other);
13474 }
13475
13480 bool operator<(const iter_impl& other) const
13481 {
13482 // if objects are not the same, the comparison is undefined
13483 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13484 {
13485 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13486 }
13487
13488 JSON_ASSERT(m_object != nullptr);
13489
13490 switch (m_object->m_data.m_type)
13491 {
13492 case value_t::object:
13493 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
13494
13495 case value_t::array:
13496 return (m_it.array_iterator < other.m_it.array_iterator);
13497
13498 case value_t::null:
13499 case value_t::string:
13500 case value_t::boolean:
13504 case value_t::binary:
13505 case value_t::discarded:
13506 default:
13507 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
13508 }
13509 }
13510
13515 bool operator<=(const iter_impl& other) const
13516 {
13517 return !other.operator < (*this);
13518 }
13519
13524 bool operator>(const iter_impl& other) const
13525 {
13526 return !operator<=(other);
13527 }
13528
13533 bool operator>=(const iter_impl& other) const
13534 {
13535 return !operator<(other);
13536 }
13537
13543 {
13544 JSON_ASSERT(m_object != nullptr);
13545
13546 switch (m_object->m_data.m_type)
13547 {
13548 case value_t::object:
13549 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13550
13551 case value_t::array:
13552 {
13553 std::advance(m_it.array_iterator, i);
13554 break;
13555 }
13556
13557 case value_t::null:
13558 case value_t::string:
13559 case value_t::boolean:
13563 case value_t::binary:
13564 case value_t::discarded:
13565 default:
13566 {
13568 break;
13569 }
13570 }
13571
13572 return *this;
13573 }
13574
13580 {
13581 return operator+=(-i);
13582 }
13583
13589 {
13590 auto result = *this;
13591 result += i;
13592 return result;
13593 }
13594
13600 {
13601 auto result = it;
13602 result += i;
13603 return result;
13604 }
13605
13611 {
13612 auto result = *this;
13613 result -= i;
13614 return result;
13615 }
13616
13622 {
13623 JSON_ASSERT(m_object != nullptr);
13624
13625 switch (m_object->m_data.m_type)
13626 {
13627 case value_t::object:
13628 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13629
13630 case value_t::array:
13631 return m_it.array_iterator - other.m_it.array_iterator;
13632
13633 case value_t::null:
13634 case value_t::string:
13635 case value_t::boolean:
13639 case value_t::binary:
13640 case value_t::discarded:
13641 default:
13642 return m_it.primitive_iterator - other.m_it.primitive_iterator;
13643 }
13644 }
13645
13651 {
13652 JSON_ASSERT(m_object != nullptr);
13653
13654 switch (m_object->m_data.m_type)
13655 {
13656 case value_t::object:
13657 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
13658
13659 case value_t::array:
13660 return *std::next(m_it.array_iterator, n);
13661
13662 case value_t::null:
13663 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13664
13665 case value_t::string:
13666 case value_t::boolean:
13670 case value_t::binary:
13671 case value_t::discarded:
13672 default:
13673 {
13675 {
13676 return *m_object;
13677 }
13678
13679 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13680 }
13681 }
13682 }
13683
13688 const typename object_t::key_type& key() const
13689 {
13690 JSON_ASSERT(m_object != nullptr);
13691
13692 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
13693 {
13694 return m_it.object_iterator->first;
13695 }
13696
13697 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
13698 }
13699
13705 {
13706 return operator*();
13707 }
13708
13711 pointer m_object = nullptr;
13714};
13715
13716} // namespace detail
13718
13719// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
13720
13721// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
13722// __ _____ _____ _____
13723// __| | __| | | | JSON for Modern C++
13724// | | |__ | | | | | | version 3.11.3
13725// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13726//
13727// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13728// SPDX-License-Identifier: MIT
13729
13730
13731
13732#include <cstddef> // ptrdiff_t
13733#include <iterator> // reverse_iterator
13734#include <utility> // declval
13735
13736// #include <nlohmann/detail/abi_macros.hpp>
13737
13738
13740namespace detail
13741{
13742
13744// reverse_iterator //
13746
13765template<typename Base>
13766class json_reverse_iterator : public std::reverse_iterator<Base>
13767{
13768 public:
13769 using difference_type = std::ptrdiff_t;
13771 using base_iterator = std::reverse_iterator<Base>;
13773 using reference = typename Base::reference;
13774
13776 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13777 : base_iterator(it) {}
13778
13780 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13781
13783 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
13784 {
13785 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13786 }
13787
13790 {
13791 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13792 }
13793
13795 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
13796 {
13797 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13798 }
13799
13802 {
13803 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13804 }
13805
13808 {
13809 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13810 }
13811
13814 {
13815 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13816 }
13817
13820 {
13821 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13822 }
13823
13826 {
13827 return base_iterator(*this) - base_iterator(other);
13828 }
13829
13832 {
13833 return *(this->operator+(n));
13834 }
13835
13837 auto key() const -> decltype(std::declval<Base>().key())
13838 {
13839 auto it = --this->base();
13840 return it.key();
13841 }
13842
13845 {
13846 auto it = --this->base();
13847 return it.operator * ();
13848 }
13849};
13850
13851} // namespace detail
13853
13854// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13855
13856// #include <nlohmann/detail/json_custom_base_class.hpp>
13857// __ _____ _____ _____
13858// __| | __| | | | JSON for Modern C++
13859// | | |__ | | | | | | version 3.11.3
13860// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13861//
13862// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13863// SPDX-License-Identifier: MIT
13864
13865
13866
13867#include <type_traits> // conditional, is_same
13868
13869// #include <nlohmann/detail/abi_macros.hpp>
13870
13871
13873namespace detail
13874{
13875
13887
13888template<class T>
13889using json_base_class = typename std::conditional <
13890 std::is_same<T, void>::value,
13892 T
13893 >::type;
13894
13895} // namespace detail
13897
13898// #include <nlohmann/detail/json_pointer.hpp>
13899// __ _____ _____ _____
13900// __| | __| | | | JSON for Modern C++
13901// | | |__ | | | | | | version 3.11.3
13902// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13903//
13904// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13905// SPDX-License-Identifier: MIT
13906
13907
13908
13909#include <algorithm> // all_of
13910#include <cctype> // isdigit
13911#include <cerrno> // errno, ERANGE
13912#include <cstdlib> // strtoull
13913#ifndef JSON_NO_IO
13914 #include <iosfwd> // ostream
13915#endif // JSON_NO_IO
13916#include <limits> // max
13917#include <numeric> // accumulate
13918#include <string> // string
13919#include <utility> // move
13920#include <vector> // vector
13921
13922// #include <nlohmann/detail/exceptions.hpp>
13923
13924// #include <nlohmann/detail/macro_scope.hpp>
13925
13926// #include <nlohmann/detail/string_concat.hpp>
13927
13928// #include <nlohmann/detail/string_escape.hpp>
13929
13930// #include <nlohmann/detail/value_t.hpp>
13931
13932
13934
13937template<typename RefStringType>
13939{
13940 // allow basic_json to access private members
13942 friend class basic_json;
13943
13944 template<typename>
13945 friend class json_pointer;
13946
13947 template<typename T>
13948 struct string_t_helper
13949 {
13950 using type = T;
13951 };
13952
13954 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
13955 {
13956 using type = StringType;
13957 };
13958
13959 public:
13960 // for backwards compatibility accept BasicJsonType
13961 using string_t = typename string_t_helper<RefStringType>::type;
13962
13965 explicit json_pointer(const string_t& s = "")
13966 : reference_tokens(split(s))
13967 {}
13968
13972 {
13973 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
13974 string_t{},
13975 [](const string_t& a, const string_t& b)
13976 {
13977 return detail::concat(a, '/', detail::escape(b));
13978 });
13979 }
13980
13984 operator string_t() const
13985 {
13986 return to_string();
13987 }
13988
13989#ifndef JSON_NO_IO
13992 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
13993 {
13994 o << ptr.to_string();
13995 return o;
13996 }
13997#endif
13998
14002 {
14003 reference_tokens.insert(reference_tokens.end(),
14004 ptr.reference_tokens.begin(),
14005 ptr.reference_tokens.end());
14006 return *this;
14007 }
14008
14012 {
14013 push_back(std::move(token));
14014 return *this;
14015 }
14016
14019 json_pointer& operator/=(std::size_t array_idx)
14020 {
14021 return *this /= std::to_string(array_idx);
14022 }
14023
14027 const json_pointer& rhs)
14028 {
14029 return json_pointer(lhs) /= rhs;
14030 }
14031
14034 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
14035 {
14036 return json_pointer(lhs) /= std::move(token);
14037 }
14038
14041 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
14042 {
14043 return json_pointer(lhs) /= array_idx;
14044 }
14045
14049 {
14050 if (empty())
14051 {
14052 return *this;
14053 }
14054
14055 json_pointer res = *this;
14056 res.pop_back();
14057 return res;
14058 }
14059
14063 {
14065 {
14066 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14067 }
14068
14069 reference_tokens.pop_back();
14070 }
14071
14074 const string_t& back() const
14075 {
14077 {
14078 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14079 }
14080
14081 return reference_tokens.back();
14082 }
14083
14087 {
14088 reference_tokens.push_back(token);
14089 }
14090
14094 {
14095 reference_tokens.push_back(std::move(token));
14096 }
14097
14100 bool empty() const noexcept
14101 {
14102 return reference_tokens.empty();
14103 }
14104
14105 private:
14116 template<typename BasicJsonType>
14117 static typename BasicJsonType::size_type array_index(const string_t& s)
14118 {
14119 using size_type = typename BasicJsonType::size_type;
14120
14121 // error condition (cf. RFC 6901, Sect. 4)
14122 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14123 {
14124 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14125 }
14126
14127 // error condition (cf. RFC 6901, Sect. 4)
14128 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14129 {
14130 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14131 }
14132
14133 const char* p = s.c_str();
14134 char* p_end = nullptr;
14135 errno = 0; // strtoull doesn't reset errno
14136 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14137 if (p == p_end // invalid input or empty string
14138 || errno == ERANGE // out of range
14139 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14140 {
14141 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14142 }
14143
14144 // only triggered on special platforms (like 32bit), see also
14145 // https://github.com/nlohmann/json/pull/2203
14146 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14147 {
14148 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14149 }
14150
14151 return static_cast<size_type>(res);
14152 }
14153
14155 json_pointer top() const
14156 {
14158 {
14159 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14160 }
14161
14162 json_pointer result = *this;
14163 result.reference_tokens = {reference_tokens[0]};
14164 return result;
14165 }
14166
14167 private:
14176 template<typename BasicJsonType>
14177 BasicJsonType& get_and_create(BasicJsonType& j) const
14178 {
14179 auto* result = &j;
14180
14181 // in case no reference tokens exist, return a reference to the JSON value
14182 // j which will be overwritten by a primitive value
14183 for (const auto& reference_token : reference_tokens)
14184 {
14185 switch (result->type())
14186 {
14188 {
14189 if (reference_token == "0")
14190 {
14191 // start a new array if reference token is 0
14192 result = &result->operator[](0);
14193 }
14194 else
14195 {
14196 // start a new object otherwise
14197 result = &result->operator[](reference_token);
14198 }
14199 break;
14200 }
14201
14203 {
14204 // create an entry in the object
14205 result = &result->operator[](reference_token);
14206 break;
14207 }
14208
14210 {
14211 // create an entry in the array
14212 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14213 break;
14214 }
14215
14216 /*
14217 The following code is only reached if there exists a reference
14218 token _and_ the current value is primitive. In this case, we have
14219 an error situation, because primitive values may only occur as
14220 single value; that is, with an empty list of reference tokens.
14221 */
14229 default:
14230 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14231 }
14232 }
14233
14234 return *result;
14235 }
14236
14256 template<typename BasicJsonType>
14257 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14258 {
14259 for (const auto& reference_token : reference_tokens)
14260 {
14261 // convert null values to arrays or objects before continuing
14262 if (ptr->is_null())
14263 {
14264 // check if reference token is a number
14265 const bool nums =
14266 std::all_of(reference_token.begin(), reference_token.end(),
14267 [](const unsigned char x)
14268 {
14269 return std::isdigit(x);
14270 });
14271
14272 // change value to array for numbers or "-" or to object otherwise
14273 *ptr = (nums || reference_token == "-")
14276 }
14277
14278 switch (ptr->type())
14279 {
14281 {
14282 // use unchecked object access
14283 ptr = &ptr->operator[](reference_token);
14284 break;
14285 }
14286
14288 {
14289 if (reference_token == "-")
14290 {
14291 // explicitly treat "-" as index beyond the end
14292 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14293 }
14294 else
14295 {
14296 // convert array index to number; unchecked access
14297 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14298 }
14299 break;
14300 }
14301
14310 default:
14311 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14312 }
14313 }
14314
14315 return *ptr;
14316 }
14317
14324 template<typename BasicJsonType>
14325 BasicJsonType& get_checked(BasicJsonType* ptr) const
14326 {
14327 for (const auto& reference_token : reference_tokens)
14328 {
14329 switch (ptr->type())
14330 {
14332 {
14333 // note: at performs range check
14334 ptr = &ptr->at(reference_token);
14335 break;
14336 }
14337
14339 {
14340 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14341 {
14342 // "-" always fails the range check
14344 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14345 ") is out of range"), ptr));
14346 }
14347
14348 // note: at performs range check
14349 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14350 break;
14351 }
14352
14361 default:
14362 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14363 }
14364 }
14365
14366 return *ptr;
14367 }
14368
14382 template<typename BasicJsonType>
14383 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
14384 {
14385 for (const auto& reference_token : reference_tokens)
14386 {
14387 switch (ptr->type())
14388 {
14390 {
14391 // use unchecked object access
14392 ptr = &ptr->operator[](reference_token);
14393 break;
14394 }
14395
14397 {
14398 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14399 {
14400 // "-" cannot be used for const access
14401 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));
14402 }
14403
14404 // use unchecked array access
14405 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14406 break;
14407 }
14408
14417 default:
14418 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14419 }
14420 }
14421
14422 return *ptr;
14423 }
14424
14431 template<typename BasicJsonType>
14432 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
14433 {
14434 for (const auto& reference_token : reference_tokens)
14435 {
14436 switch (ptr->type())
14437 {
14439 {
14440 // note: at performs range check
14441 ptr = &ptr->at(reference_token);
14442 break;
14443 }
14444
14446 {
14447 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14448 {
14449 // "-" always fails the range check
14451 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14452 ") is out of range"), ptr));
14453 }
14454
14455 // note: at performs range check
14456 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14457 break;
14458 }
14459
14468 default:
14469 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14470 }
14471 }
14472
14473 return *ptr;
14474 }
14475
14480 template<typename BasicJsonType>
14481 bool contains(const BasicJsonType* ptr) const
14482 {
14483 for (const auto& reference_token : reference_tokens)
14484 {
14485 switch (ptr->type())
14486 {
14488 {
14489 if (!ptr->contains(reference_token))
14490 {
14491 // we did not find the key in the object
14492 return false;
14493 }
14494
14495 ptr = &ptr->operator[](reference_token);
14496 break;
14497 }
14498
14500 {
14501 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14502 {
14503 // "-" always fails the range check
14504 return false;
14505 }
14506 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
14507 {
14508 // invalid char
14509 return false;
14510 }
14511 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
14512 {
14513 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
14514 {
14515 // first char should be between '1' and '9'
14516 return false;
14517 }
14518 for (std::size_t i = 1; i < reference_token.size(); i++)
14519 {
14520 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
14521 {
14522 // other char should be between '0' and '9'
14523 return false;
14524 }
14525 }
14526 }
14527
14528 const auto idx = array_index<BasicJsonType>(reference_token);
14529 if (idx >= ptr->size())
14530 {
14531 // index out of range
14532 return false;
14533 }
14534
14535 ptr = &ptr->operator[](idx);
14536 break;
14537 }
14538
14547 default:
14548 {
14549 // we do not expect primitive values if there is still a
14550 // reference token to process
14551 return false;
14552 }
14553 }
14554 }
14555
14556 // no reference token left means we found a primitive value
14557 return true;
14558 }
14559
14569 static std::vector<string_t> split(const string_t& reference_string)
14570 {
14571 std::vector<string_t> result;
14572
14573 // special case: empty reference string -> no reference tokens
14574 if (reference_string.empty())
14575 {
14576 return result;
14577 }
14578
14579 // check if nonempty reference string begins with slash
14580 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
14581 {
14582 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
14583 }
14584
14585 // extract the reference tokens:
14586 // - slash: position of the last read slash (or end of string)
14587 // - start: position after the previous slash
14588 for (
14589 // search for the first slash after the first character
14590 std::size_t slash = reference_string.find_first_of('/', 1),
14591 // set the beginning of the first reference token
14592 start = 1;
14593 // we can stop if start == 0 (if slash == string_t::npos)
14594 start != 0;
14595 // set the beginning of the next reference token
14596 // (will eventually be 0 if slash == string_t::npos)
14597 start = (slash == string_t::npos) ? 0 : slash + 1,
14598 // find next slash
14599 slash = reference_string.find_first_of('/', start))
14600 {
14601 // use the text between the beginning of the reference token
14602 // (start) and the last slash (slash).
14603 auto reference_token = reference_string.substr(start, slash - start);
14604
14605 // check reference tokens are properly escaped
14606 for (std::size_t pos = reference_token.find_first_of('~');
14607 pos != string_t::npos;
14608 pos = reference_token.find_first_of('~', pos + 1))
14609 {
14610 JSON_ASSERT(reference_token[pos] == '~');
14611
14612 // ~ must be followed by 0 or 1
14613 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
14614 (reference_token[pos + 1] != '0' &&
14615 reference_token[pos + 1] != '1')))
14616 {
14617 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
14618 }
14619 }
14620
14621 // finally, store the reference token
14622 detail::unescape(reference_token);
14623 result.push_back(reference_token);
14624 }
14625
14626 return result;
14627 }
14628
14629 private:
14637 template<typename BasicJsonType>
14638 static void flatten(const string_t& reference_string,
14639 const BasicJsonType& value,
14640 BasicJsonType& result)
14641 {
14642 switch (value.type())
14643 {
14645 {
14646 if (value.m_data.m_value.array->empty())
14647 {
14648 // flatten empty array as null
14649 result[reference_string] = nullptr;
14650 }
14651 else
14652 {
14653 // iterate array and use index as reference string
14654 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
14655 {
14656 flatten(detail::concat(reference_string, '/', std::to_string(i)),
14657 value.m_data.m_value.array->operator[](i), result);
14658 }
14659 }
14660 break;
14661 }
14662
14664 {
14665 if (value.m_data.m_value.object->empty())
14666 {
14667 // flatten empty object as null
14668 result[reference_string] = nullptr;
14669 }
14670 else
14671 {
14672 // iterate object and use keys as reference string
14673 for (const auto& element : *value.m_data.m_value.object)
14674 {
14675 flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
14676 }
14677 }
14678 break;
14679 }
14680
14689 default:
14690 {
14691 // add primitive value with its reference string
14692 result[reference_string] = value;
14693 break;
14694 }
14695 }
14696 }
14697
14708 template<typename BasicJsonType>
14709 static BasicJsonType
14710 unflatten(const BasicJsonType& value)
14711 {
14712 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
14713 {
14714 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
14715 }
14716
14717 BasicJsonType result;
14718
14719 // iterate the JSON object values
14720 for (const auto& element : *value.m_data.m_value.object)
14721 {
14722 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
14723 {
14724 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
14725 }
14726
14727 // assign value to reference pointed to by JSON pointer; Note that if
14728 // the JSON pointer is "" (i.e., points to the whole value), function
14729 // get_and_create returns a reference to result itself. An assignment
14730 // will then create a primitive value.
14731 json_pointer(element.first).get_and_create(result) = element.second;
14732 }
14733
14734 return result;
14735 }
14736
14737 // can't use conversion operator because of ambiguity
14738 json_pointer<string_t> convert() const&
14739 {
14741 result.reference_tokens = reference_tokens;
14742 return result;
14743 }
14744
14745 json_pointer<string_t> convert()&&
14746 {
14748 result.reference_tokens = std::move(reference_tokens);
14749 return result;
14750 }
14751
14752 public:
14753#if JSON_HAS_THREE_WAY_COMPARISON
14756 template<typename RefStringTypeRhs>
14757 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
14758 {
14759 return reference_tokens == rhs.reference_tokens;
14760 }
14761
14764 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
14765 bool operator==(const string_t& rhs) const
14766 {
14767 return *this == json_pointer(rhs);
14768 }
14769
14771 template<typename RefStringTypeRhs>
14772 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
14773 {
14774 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
14775 }
14776#else
14779 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14780 // NOLINTNEXTLINE(readability-redundant-declaration)
14781 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14782 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14783
14786 template<typename RefStringTypeLhs, typename StringType>
14787 // NOLINTNEXTLINE(readability-redundant-declaration)
14788 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14789 const StringType& rhs);
14790
14793 template<typename RefStringTypeRhs, typename StringType>
14794 // NOLINTNEXTLINE(readability-redundant-declaration)
14795 friend bool operator==(const StringType& lhs,
14797
14800 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14801 // NOLINTNEXTLINE(readability-redundant-declaration)
14802 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14803 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14804
14807 template<typename RefStringTypeLhs, typename StringType>
14808 // NOLINTNEXTLINE(readability-redundant-declaration)
14809 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14810 const StringType& rhs);
14811
14814 template<typename RefStringTypeRhs, typename StringType>
14815 // NOLINTNEXTLINE(readability-redundant-declaration)
14816 friend bool operator!=(const StringType& lhs,
14818
14820 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14821 // NOLINTNEXTLINE(readability-redundant-declaration)
14822 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14823 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14824#endif
14825
14826 private:
14828 std::vector<string_t> reference_tokens;
14829};
14830
14831#if !JSON_HAS_THREE_WAY_COMPARISON
14832// functions cannot be defined inside class due to ODR violations
14833template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14835 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14836{
14837 return lhs.reference_tokens == rhs.reference_tokens;
14838}
14839
14840template<typename RefStringTypeLhs,
14841 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14843inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14844 const StringType& rhs)
14845{
14846 return lhs == json_pointer<RefStringTypeLhs>(rhs);
14847}
14848
14849template<typename RefStringTypeRhs,
14850 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14852inline bool operator==(const StringType& lhs,
14853 const json_pointer<RefStringTypeRhs>& rhs)
14854{
14855 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
14856}
14857
14858template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14860 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14861{
14862 return !(lhs == rhs);
14863}
14864
14865template<typename RefStringTypeLhs,
14866 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14868inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14869 const StringType& rhs)
14870{
14871 return !(lhs == rhs);
14872}
14873
14874template<typename RefStringTypeRhs,
14875 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14877inline bool operator!=(const StringType& lhs,
14878 const json_pointer<RefStringTypeRhs>& rhs)
14879{
14880 return !(lhs == rhs);
14881}
14882
14883template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14885 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14886{
14887 return lhs.reference_tokens < rhs.reference_tokens;
14888}
14889#endif
14890
14892
14893// #include <nlohmann/detail/json_ref.hpp>
14894// __ _____ _____ _____
14895// __| | __| | | | JSON for Modern C++
14896// | | |__ | | | | | | version 3.11.3
14897// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14898//
14899// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14900// SPDX-License-Identifier: MIT
14901
14902
14903
14904#include <initializer_list>
14905#include <utility>
14906
14907// #include <nlohmann/detail/abi_macros.hpp>
14908
14909// #include <nlohmann/detail/meta/type_traits.hpp>
14910
14911
14913namespace detail
14914{
14915
14916template<typename BasicJsonType>
14918{
14919 public:
14920 using value_type = BasicJsonType;
14921
14923 : owned_value(std::move(value))
14924 {}
14925
14927 : value_ref(&value)
14928 {}
14929
14930 json_ref(std::initializer_list<json_ref> init)
14931 : owned_value(init)
14932 {}
14933
14934 template <
14935 class... Args,
14936 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
14937 json_ref(Args && ... args)
14938 : owned_value(std::forward<Args>(args)...)
14939 {}
14940
14941 // class should be movable only
14942 json_ref(json_ref&&) noexcept = default;
14943 json_ref(const json_ref&) = delete;
14944 json_ref& operator=(const json_ref&) = delete;
14945 json_ref& operator=(json_ref&&) = delete;
14946 ~json_ref() = default;
14947
14949 {
14950 if (value_ref == nullptr)
14951 {
14952 return std::move(owned_value);
14953 }
14954 return *value_ref;
14955 }
14956
14957 value_type const& operator*() const
14958 {
14959 return value_ref ? *value_ref : owned_value;
14960 }
14961
14962 value_type const* operator->() const
14963 {
14964 return &** this;
14965 }
14966
14967 private:
14968 mutable value_type owned_value = nullptr;
14969 value_type const* value_ref = nullptr;
14970};
14971
14972} // namespace detail
14974
14975// #include <nlohmann/detail/macro_scope.hpp>
14976
14977// #include <nlohmann/detail/string_concat.hpp>
14978
14979// #include <nlohmann/detail/string_escape.hpp>
14980
14981// #include <nlohmann/detail/meta/cpp_future.hpp>
14982
14983// #include <nlohmann/detail/meta/type_traits.hpp>
14984
14985// #include <nlohmann/detail/output/binary_writer.hpp>
14986// __ _____ _____ _____
14987// __| | __| | | | JSON for Modern C++
14988// | | |__ | | | | | | version 3.11.3
14989// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14990//
14991// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14992// SPDX-License-Identifier: MIT
14993
14994
14995
14996#include <algorithm> // reverse
14997#include <array> // array
14998#include <map> // map
14999#include <cmath> // isnan, isinf
15000#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
15001#include <cstring> // memcpy
15002#include <limits> // numeric_limits
15003#include <string> // string
15004#include <utility> // move
15005#include <vector> // vector
15006
15007// #include <nlohmann/detail/input/binary_reader.hpp>
15008
15009// #include <nlohmann/detail/macro_scope.hpp>
15010
15011// #include <nlohmann/detail/output/output_adapters.hpp>
15012// __ _____ _____ _____
15013// __| | __| | | | JSON for Modern C++
15014// | | |__ | | | | | | version 3.11.3
15015// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15016//
15017// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
15018// SPDX-License-Identifier: MIT
15019
15020
15021
15022#include <algorithm> // copy
15023#include <cstddef> // size_t
15024#include <iterator> // back_inserter
15025#include <memory> // shared_ptr, make_shared
15026#include <string> // basic_string
15027#include <vector> // vector
15028
15029#ifndef JSON_NO_IO
15030 #include <ios> // streamsize
15031 #include <ostream> // basic_ostream
15032#endif // JSON_NO_IO
15033
15034// #include <nlohmann/detail/macro_scope.hpp>
15035
15036
15038namespace detail
15039{
15040
15042template<typename CharType> struct output_adapter_protocol
15043{
15044 virtual void write_character(CharType c) = 0;
15045 virtual void write_characters(const CharType* s, std::size_t length) = 0;
15046 virtual ~output_adapter_protocol() = default;
15047
15052 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
15053};
15054
15056template<typename CharType>
15057using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
15058
15060template<typename CharType, typename AllocatorType = std::allocator<CharType>>
15062{
15063 public:
15064 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
15065 : v(vec)
15066 {}
15067
15068 void write_character(CharType c) override
15069 {
15070 v.push_back(c);
15071 }
15072
15074 void write_characters(const CharType* s, std::size_t length) override
15075 {
15076 v.insert(v.end(), s, s + length);
15077 }
15078
15079 private:
15080 std::vector<CharType, AllocatorType>& v;
15081};
15082
15083#ifndef JSON_NO_IO
15085template<typename CharType>
15087{
15088 public:
15089 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15090 : stream(s)
15091 {}
15092
15093 void write_character(CharType c) override
15094 {
15095 stream.put(c);
15096 }
15097
15099 void write_characters(const CharType* s, std::size_t length) override
15100 {
15101 stream.write(s, static_cast<std::streamsize>(length));
15102 }
15103
15104 private:
15105 std::basic_ostream<CharType>& stream;
15106};
15107#endif // JSON_NO_IO
15108
15110template<typename CharType, typename StringType = std::basic_string<CharType>>
15112{
15113 public:
15114 explicit output_string_adapter(StringType& s) noexcept
15115 : str(s)
15116 {}
15117
15118 void write_character(CharType c) override
15119 {
15120 str.push_back(c);
15121 }
15122
15124 void write_characters(const CharType* s, std::size_t length) override
15125 {
15126 str.append(s, length);
15127 }
15128
15129 private:
15130 StringType& str;
15131};
15132
15133template<typename CharType, typename StringType = std::basic_string<CharType>>
15135{
15136 public:
15137 template<typename AllocatorType = std::allocator<CharType>>
15138 output_adapter(std::vector<CharType, AllocatorType>& vec)
15139 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15140
15141#ifndef JSON_NO_IO
15142 output_adapter(std::basic_ostream<CharType>& s)
15143 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15144#endif // JSON_NO_IO
15145
15146 output_adapter(StringType& s)
15147 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15148
15150 {
15151 return oa;
15152 }
15153
15154 private:
15155 output_adapter_t<CharType> oa = nullptr;
15156};
15157
15158} // namespace detail
15160
15161// #include <nlohmann/detail/string_concat.hpp>
15162
15163
15165namespace detail
15166{
15167
15169// binary writer //
15171
15175template<typename BasicJsonType, typename CharType>
15177{
15178 using string_t = typename BasicJsonType::string_t;
15179 using binary_t = typename BasicJsonType::binary_t;
15180 using number_float_t = typename BasicJsonType::number_float_t;
15181
15182 public:
15188 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15189 {
15190 JSON_ASSERT(oa);
15191 }
15192
15197 void write_bson(const BasicJsonType& j)
15198 {
15199 switch (j.type())
15200 {
15201 case value_t::object:
15202 {
15203 write_bson_object(*j.m_data.m_value.object);
15204 break;
15205 }
15206
15207 case value_t::null:
15208 case value_t::array:
15209 case value_t::string:
15210 case value_t::boolean:
15211 case value_t::number_integer:
15212 case value_t::number_unsigned:
15213 case value_t::number_float:
15214 case value_t::binary:
15215 case value_t::discarded:
15216 default:
15217 {
15218 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15219 }
15220 }
15221 }
15222
15226 void write_cbor(const BasicJsonType& j)
15227 {
15228 switch (j.type())
15229 {
15230 case value_t::null:
15231 {
15232 oa->write_character(to_char_type(0xF6));
15233 break;
15234 }
15235
15236 case value_t::boolean:
15237 {
15238 oa->write_character(j.m_data.m_value.boolean
15239 ? to_char_type(0xF5)
15240 : to_char_type(0xF4));
15241 break;
15242 }
15243
15244 case value_t::number_integer:
15245 {
15246 if (j.m_data.m_value.number_integer >= 0)
15247 {
15248 // CBOR does not differentiate between positive signed
15249 // integers and unsigned integers. Therefore, we used the
15250 // code from the value_t::number_unsigned case here.
15251 if (j.m_data.m_value.number_integer <= 0x17)
15252 {
15253 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15254 }
15255 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15256 {
15257 oa->write_character(to_char_type(0x18));
15258 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15259 }
15260 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15261 {
15262 oa->write_character(to_char_type(0x19));
15263 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15264 }
15265 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15266 {
15267 oa->write_character(to_char_type(0x1A));
15268 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15269 }
15270 else
15271 {
15272 oa->write_character(to_char_type(0x1B));
15273 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15274 }
15275 }
15276 else
15277 {
15278 // The conversions below encode the sign in the first
15279 // byte, and the value is converted to a positive number.
15280 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15281 if (j.m_data.m_value.number_integer >= -24)
15282 {
15283 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15284 }
15285 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15286 {
15287 oa->write_character(to_char_type(0x38));
15288 write_number(static_cast<std::uint8_t>(positive_number));
15289 }
15290 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15291 {
15292 oa->write_character(to_char_type(0x39));
15293 write_number(static_cast<std::uint16_t>(positive_number));
15294 }
15295 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15296 {
15297 oa->write_character(to_char_type(0x3A));
15298 write_number(static_cast<std::uint32_t>(positive_number));
15299 }
15300 else
15301 {
15302 oa->write_character(to_char_type(0x3B));
15303 write_number(static_cast<std::uint64_t>(positive_number));
15304 }
15305 }
15306 break;
15307 }
15308
15309 case value_t::number_unsigned:
15310 {
15311 if (j.m_data.m_value.number_unsigned <= 0x17)
15312 {
15313 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15314 }
15315 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15316 {
15317 oa->write_character(to_char_type(0x18));
15318 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15319 }
15320 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15321 {
15322 oa->write_character(to_char_type(0x19));
15323 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15324 }
15325 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15326 {
15327 oa->write_character(to_char_type(0x1A));
15328 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15329 }
15330 else
15331 {
15332 oa->write_character(to_char_type(0x1B));
15333 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15334 }
15335 break;
15336 }
15337
15338 case value_t::number_float:
15339 {
15340 if (std::isnan(j.m_data.m_value.number_float))
15341 {
15342 // NaN is 0xf97e00 in CBOR
15343 oa->write_character(to_char_type(0xF9));
15344 oa->write_character(to_char_type(0x7E));
15345 oa->write_character(to_char_type(0x00));
15346 }
15347 else if (std::isinf(j.m_data.m_value.number_float))
15348 {
15349 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
15350 oa->write_character(to_char_type(0xf9));
15351 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15352 oa->write_character(to_char_type(0x00));
15353 }
15354 else
15355 {
15356 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15357 }
15358 break;
15359 }
15360
15361 case value_t::string:
15362 {
15363 // step 1: write control byte and the string length
15364 const auto N = j.m_data.m_value.string->size();
15365 if (N <= 0x17)
15366 {
15367 write_number(static_cast<std::uint8_t>(0x60 + N));
15368 }
15369 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15370 {
15371 oa->write_character(to_char_type(0x78));
15372 write_number(static_cast<std::uint8_t>(N));
15373 }
15374 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15375 {
15376 oa->write_character(to_char_type(0x79));
15377 write_number(static_cast<std::uint16_t>(N));
15378 }
15379 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15380 {
15381 oa->write_character(to_char_type(0x7A));
15382 write_number(static_cast<std::uint32_t>(N));
15383 }
15384 // LCOV_EXCL_START
15385 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15386 {
15387 oa->write_character(to_char_type(0x7B));
15388 write_number(static_cast<std::uint64_t>(N));
15389 }
15390 // LCOV_EXCL_STOP
15391
15392 // step 2: write the string
15393 oa->write_characters(
15394 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15395 j.m_data.m_value.string->size());
15396 break;
15397 }
15398
15399 case value_t::array:
15400 {
15401 // step 1: write control byte and the array size
15402 const auto N = j.m_data.m_value.array->size();
15403 if (N <= 0x17)
15404 {
15405 write_number(static_cast<std::uint8_t>(0x80 + N));
15406 }
15407 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15408 {
15409 oa->write_character(to_char_type(0x98));
15410 write_number(static_cast<std::uint8_t>(N));
15411 }
15412 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15413 {
15414 oa->write_character(to_char_type(0x99));
15415 write_number(static_cast<std::uint16_t>(N));
15416 }
15417 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15418 {
15419 oa->write_character(to_char_type(0x9A));
15420 write_number(static_cast<std::uint32_t>(N));
15421 }
15422 // LCOV_EXCL_START
15423 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15424 {
15425 oa->write_character(to_char_type(0x9B));
15426 write_number(static_cast<std::uint64_t>(N));
15427 }
15428 // LCOV_EXCL_STOP
15429
15430 // step 2: write each element
15431 for (const auto& el : *j.m_data.m_value.array)
15432 {
15433 write_cbor(el);
15434 }
15435 break;
15436 }
15437
15438 case value_t::binary:
15439 {
15440 if (j.m_data.m_value.binary->has_subtype())
15441 {
15442 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
15443 {
15444 write_number(static_cast<std::uint8_t>(0xd8));
15445 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
15446 }
15447 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
15448 {
15449 write_number(static_cast<std::uint8_t>(0xd9));
15450 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
15451 }
15452 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
15453 {
15454 write_number(static_cast<std::uint8_t>(0xda));
15455 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
15456 }
15457 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
15458 {
15459 write_number(static_cast<std::uint8_t>(0xdb));
15460 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
15461 }
15462 }
15463
15464 // step 1: write control byte and the binary array size
15465 const auto N = j.m_data.m_value.binary->size();
15466 if (N <= 0x17)
15467 {
15468 write_number(static_cast<std::uint8_t>(0x40 + N));
15469 }
15470 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15471 {
15472 oa->write_character(to_char_type(0x58));
15473 write_number(static_cast<std::uint8_t>(N));
15474 }
15475 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15476 {
15477 oa->write_character(to_char_type(0x59));
15478 write_number(static_cast<std::uint16_t>(N));
15479 }
15480 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15481 {
15482 oa->write_character(to_char_type(0x5A));
15483 write_number(static_cast<std::uint32_t>(N));
15484 }
15485 // LCOV_EXCL_START
15486 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15487 {
15488 oa->write_character(to_char_type(0x5B));
15489 write_number(static_cast<std::uint64_t>(N));
15490 }
15491 // LCOV_EXCL_STOP
15492
15493 // step 2: write each element
15494 oa->write_characters(
15495 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15496 N);
15497
15498 break;
15499 }
15500
15501 case value_t::object:
15502 {
15503 // step 1: write control byte and the object size
15504 const auto N = j.m_data.m_value.object->size();
15505 if (N <= 0x17)
15506 {
15507 write_number(static_cast<std::uint8_t>(0xA0 + N));
15508 }
15509 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15510 {
15511 oa->write_character(to_char_type(0xB8));
15512 write_number(static_cast<std::uint8_t>(N));
15513 }
15514 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15515 {
15516 oa->write_character(to_char_type(0xB9));
15517 write_number(static_cast<std::uint16_t>(N));
15518 }
15519 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15520 {
15521 oa->write_character(to_char_type(0xBA));
15522 write_number(static_cast<std::uint32_t>(N));
15523 }
15524 // LCOV_EXCL_START
15525 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15526 {
15527 oa->write_character(to_char_type(0xBB));
15528 write_number(static_cast<std::uint64_t>(N));
15529 }
15530 // LCOV_EXCL_STOP
15531
15532 // step 2: write each element
15533 for (const auto& el : *j.m_data.m_value.object)
15534 {
15535 write_cbor(el.first);
15536 write_cbor(el.second);
15537 }
15538 break;
15539 }
15540
15541 case value_t::discarded:
15542 default:
15543 break;
15544 }
15545 }
15546
15550 void write_msgpack(const BasicJsonType& j)
15551 {
15552 switch (j.type())
15553 {
15554 case value_t::null: // nil
15555 {
15556 oa->write_character(to_char_type(0xC0));
15557 break;
15558 }
15559
15560 case value_t::boolean: // true and false
15561 {
15562 oa->write_character(j.m_data.m_value.boolean
15563 ? to_char_type(0xC3)
15564 : to_char_type(0xC2));
15565 break;
15566 }
15567
15568 case value_t::number_integer:
15569 {
15570 if (j.m_data.m_value.number_integer >= 0)
15571 {
15572 // MessagePack does not differentiate between positive
15573 // signed integers and unsigned integers. Therefore, we used
15574 // the code from the value_t::number_unsigned case here.
15575 if (j.m_data.m_value.number_unsigned < 128)
15576 {
15577 // positive fixnum
15578 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15579 }
15580 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15581 {
15582 // uint 8
15583 oa->write_character(to_char_type(0xCC));
15584 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15585 }
15586 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15587 {
15588 // uint 16
15589 oa->write_character(to_char_type(0xCD));
15590 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15591 }
15592 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15593 {
15594 // uint 32
15595 oa->write_character(to_char_type(0xCE));
15596 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15597 }
15598 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15599 {
15600 // uint 64
15601 oa->write_character(to_char_type(0xCF));
15602 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15603 }
15604 }
15605 else
15606 {
15607 if (j.m_data.m_value.number_integer >= -32)
15608 {
15609 // negative fixnum
15610 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15611 }
15612 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
15613 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
15614 {
15615 // int 8
15616 oa->write_character(to_char_type(0xD0));
15617 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15618 }
15619 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
15620 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
15621 {
15622 // int 16
15623 oa->write_character(to_char_type(0xD1));
15624 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
15625 }
15626 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
15627 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
15628 {
15629 // int 32
15630 oa->write_character(to_char_type(0xD2));
15631 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
15632 }
15633 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
15634 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
15635 {
15636 // int 64
15637 oa->write_character(to_char_type(0xD3));
15638 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
15639 }
15640 }
15641 break;
15642 }
15643
15644 case value_t::number_unsigned:
15645 {
15646 if (j.m_data.m_value.number_unsigned < 128)
15647 {
15648 // positive fixnum
15649 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15650 }
15651 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15652 {
15653 // uint 8
15654 oa->write_character(to_char_type(0xCC));
15655 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15656 }
15657 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15658 {
15659 // uint 16
15660 oa->write_character(to_char_type(0xCD));
15661 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15662 }
15663 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15664 {
15665 // uint 32
15666 oa->write_character(to_char_type(0xCE));
15667 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15668 }
15669 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15670 {
15671 // uint 64
15672 oa->write_character(to_char_type(0xCF));
15673 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15674 }
15675 break;
15676 }
15677
15678 case value_t::number_float:
15679 {
15680 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
15681 break;
15682 }
15683
15684 case value_t::string:
15685 {
15686 // step 1: write control byte and the string length
15687 const auto N = j.m_data.m_value.string->size();
15688 if (N <= 31)
15689 {
15690 // fixstr
15691 write_number(static_cast<std::uint8_t>(0xA0 | N));
15692 }
15693 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15694 {
15695 // str 8
15696 oa->write_character(to_char_type(0xD9));
15697 write_number(static_cast<std::uint8_t>(N));
15698 }
15699 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15700 {
15701 // str 16
15702 oa->write_character(to_char_type(0xDA));
15703 write_number(static_cast<std::uint16_t>(N));
15704 }
15705 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15706 {
15707 // str 32
15708 oa->write_character(to_char_type(0xDB));
15709 write_number(static_cast<std::uint32_t>(N));
15710 }
15711
15712 // step 2: write the string
15713 oa->write_characters(
15714 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15715 j.m_data.m_value.string->size());
15716 break;
15717 }
15718
15719 case value_t::array:
15720 {
15721 // step 1: write control byte and the array size
15722 const auto N = j.m_data.m_value.array->size();
15723 if (N <= 15)
15724 {
15725 // fixarray
15726 write_number(static_cast<std::uint8_t>(0x90 | N));
15727 }
15728 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15729 {
15730 // array 16
15731 oa->write_character(to_char_type(0xDC));
15732 write_number(static_cast<std::uint16_t>(N));
15733 }
15734 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15735 {
15736 // array 32
15737 oa->write_character(to_char_type(0xDD));
15738 write_number(static_cast<std::uint32_t>(N));
15739 }
15740
15741 // step 2: write each element
15742 for (const auto& el : *j.m_data.m_value.array)
15743 {
15744 write_msgpack(el);
15745 }
15746 break;
15747 }
15748
15749 case value_t::binary:
15750 {
15751 // step 0: determine if the binary type has a set subtype to
15752 // determine whether to use the ext or fixext types
15753 const bool use_ext = j.m_data.m_value.binary->has_subtype();
15754
15755 // step 1: write control byte and the byte string length
15756 const auto N = j.m_data.m_value.binary->size();
15757 if (N <= (std::numeric_limits<std::uint8_t>::max)())
15758 {
15759 std::uint8_t output_type{};
15760 bool fixed = true;
15761 if (use_ext)
15762 {
15763 switch (N)
15764 {
15765 case 1:
15766 output_type = 0xD4; // fixext 1
15767 break;
15768 case 2:
15769 output_type = 0xD5; // fixext 2
15770 break;
15771 case 4:
15772 output_type = 0xD6; // fixext 4
15773 break;
15774 case 8:
15775 output_type = 0xD7; // fixext 8
15776 break;
15777 case 16:
15778 output_type = 0xD8; // fixext 16
15779 break;
15780 default:
15781 output_type = 0xC7; // ext 8
15782 fixed = false;
15783 break;
15784 }
15785
15786 }
15787 else
15788 {
15789 output_type = 0xC4; // bin 8
15790 fixed = false;
15791 }
15792
15793 oa->write_character(to_char_type(output_type));
15794 if (!fixed)
15795 {
15796 write_number(static_cast<std::uint8_t>(N));
15797 }
15798 }
15799 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15800 {
15801 const std::uint8_t output_type = use_ext
15802 ? 0xC8 // ext 16
15803 : 0xC5; // bin 16
15804
15805 oa->write_character(to_char_type(output_type));
15806 write_number(static_cast<std::uint16_t>(N));
15807 }
15808 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15809 {
15810 const std::uint8_t output_type = use_ext
15811 ? 0xC9 // ext 32
15812 : 0xC6; // bin 32
15813
15814 oa->write_character(to_char_type(output_type));
15815 write_number(static_cast<std::uint32_t>(N));
15816 }
15817
15818 // step 1.5: if this is an ext type, write the subtype
15819 if (use_ext)
15820 {
15821 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
15822 }
15823
15824 // step 2: write the byte string
15825 oa->write_characters(
15826 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15827 N);
15828
15829 break;
15830 }
15831
15832 case value_t::object:
15833 {
15834 // step 1: write control byte and the object size
15835 const auto N = j.m_data.m_value.object->size();
15836 if (N <= 15)
15837 {
15838 // fixmap
15839 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
15840 }
15841 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15842 {
15843 // map 16
15844 oa->write_character(to_char_type(0xDE));
15845 write_number(static_cast<std::uint16_t>(N));
15846 }
15847 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15848 {
15849 // map 32
15850 oa->write_character(to_char_type(0xDF));
15851 write_number(static_cast<std::uint32_t>(N));
15852 }
15853
15854 // step 2: write each element
15855 for (const auto& el : *j.m_data.m_value.object)
15856 {
15857 write_msgpack(el.first);
15858 write_msgpack(el.second);
15859 }
15860 break;
15861 }
15862
15863 case value_t::discarded:
15864 default:
15865 break;
15866 }
15867 }
15868
15876 void write_ubjson(const BasicJsonType& j, const bool use_count,
15877 const bool use_type, const bool add_prefix = true,
15878 const bool use_bjdata = false)
15879 {
15880 switch (j.type())
15881 {
15882 case value_t::null:
15883 {
15884 if (add_prefix)
15885 {
15886 oa->write_character(to_char_type('Z'));
15887 }
15888 break;
15889 }
15890
15891 case value_t::boolean:
15892 {
15893 if (add_prefix)
15894 {
15895 oa->write_character(j.m_data.m_value.boolean
15896 ? to_char_type('T')
15897 : to_char_type('F'));
15898 }
15899 break;
15900 }
15901
15902 case value_t::number_integer:
15903 {
15904 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
15905 break;
15906 }
15907
15908 case value_t::number_unsigned:
15909 {
15910 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
15911 break;
15912 }
15913
15914 case value_t::number_float:
15915 {
15916 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
15917 break;
15918 }
15919
15920 case value_t::string:
15921 {
15922 if (add_prefix)
15923 {
15924 oa->write_character(to_char_type('S'));
15925 }
15926 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
15927 oa->write_characters(
15928 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15929 j.m_data.m_value.string->size());
15930 break;
15931 }
15932
15933 case value_t::array:
15934 {
15935 if (add_prefix)
15936 {
15937 oa->write_character(to_char_type('['));
15938 }
15939
15940 bool prefix_required = true;
15941 if (use_type && !j.m_data.m_value.array->empty())
15942 {
15943 JSON_ASSERT(use_count);
15944 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15945 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
15946 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15947 {
15948 return ubjson_prefix(v, use_bjdata) == first_prefix;
15949 });
15950
15951 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15952
15953 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15954 {
15955 prefix_required = false;
15956 oa->write_character(to_char_type('$'));
15957 oa->write_character(first_prefix);
15958 }
15959 }
15960
15961 if (use_count)
15962 {
15963 oa->write_character(to_char_type('#'));
15964 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
15965 }
15966
15967 for (const auto& el : *j.m_data.m_value.array)
15968 {
15969 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
15970 }
15971
15972 if (!use_count)
15973 {
15974 oa->write_character(to_char_type(']'));
15975 }
15976
15977 break;
15978 }
15979
15980 case value_t::binary:
15981 {
15982 if (add_prefix)
15983 {
15984 oa->write_character(to_char_type('['));
15985 }
15986
15987 if (use_type && !j.m_data.m_value.binary->empty())
15988 {
15989 JSON_ASSERT(use_count);
15990 oa->write_character(to_char_type('$'));
15991 oa->write_character('U');
15992 }
15993
15994 if (use_count)
15995 {
15996 oa->write_character(to_char_type('#'));
15997 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
15998 }
15999
16000 if (use_type)
16001 {
16002 oa->write_characters(
16003 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16004 j.m_data.m_value.binary->size());
16005 }
16006 else
16007 {
16008 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
16009 {
16010 oa->write_character(to_char_type('U'));
16011 oa->write_character(j.m_data.m_value.binary->data()[i]);
16012 }
16013 }
16014
16015 if (!use_count)
16016 {
16017 oa->write_character(to_char_type(']'));
16018 }
16019
16020 break;
16021 }
16022
16023 case value_t::object:
16024 {
16025 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())
16026 {
16027 if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
16028 {
16029 break;
16030 }
16031 }
16032
16033 if (add_prefix)
16034 {
16035 oa->write_character(to_char_type('{'));
16036 }
16037
16038 bool prefix_required = true;
16039 if (use_type && !j.m_data.m_value.object->empty())
16040 {
16041 JSON_ASSERT(use_count);
16042 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16043 const bool same_prefix = std::all_of(j.begin(), j.end(),
16044 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16045 {
16046 return ubjson_prefix(v, use_bjdata) == first_prefix;
16047 });
16048
16049 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16050
16051 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16052 {
16053 prefix_required = false;
16054 oa->write_character(to_char_type('$'));
16055 oa->write_character(first_prefix);
16056 }
16057 }
16058
16059 if (use_count)
16060 {
16061 oa->write_character(to_char_type('#'));
16062 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
16063 }
16064
16065 for (const auto& el : *j.m_data.m_value.object)
16066 {
16067 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
16068 oa->write_characters(
16069 reinterpret_cast<const CharType*>(el.first.c_str()),
16070 el.first.size());
16071 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
16072 }
16073
16074 if (!use_count)
16075 {
16076 oa->write_character(to_char_type('}'));
16077 }
16078
16079 break;
16080 }
16081
16082 case value_t::discarded:
16083 default:
16084 break;
16085 }
16086 }
16087
16088 private:
16090 // BSON //
16092
16097 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16098 {
16099 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16100 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16101 {
16102 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16103 static_cast<void>(j);
16104 }
16105
16106 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16107 }
16108
16112 void write_bson_entry_header(const string_t& name,
16113 const std::uint8_t element_type)
16114 {
16115 oa->write_character(to_char_type(element_type)); // boolean
16116 oa->write_characters(
16117 reinterpret_cast<const CharType*>(name.c_str()),
16118 name.size() + 1u);
16119 }
16120
16124 void write_bson_boolean(const string_t& name,
16125 const bool value)
16126 {
16127 write_bson_entry_header(name, 0x08);
16128 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16129 }
16130
16134 void write_bson_double(const string_t& name,
16135 const double value)
16136 {
16137 write_bson_entry_header(name, 0x01);
16138 write_number<double>(value, true);
16139 }
16140
16144 static std::size_t calc_bson_string_size(const string_t& value)
16145 {
16146 return sizeof(std::int32_t) + value.size() + 1ul;
16147 }
16148
16152 void write_bson_string(const string_t& name,
16153 const string_t& value)
16154 {
16155 write_bson_entry_header(name, 0x02);
16156
16157 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16158 oa->write_characters(
16159 reinterpret_cast<const CharType*>(value.c_str()),
16160 value.size() + 1);
16161 }
16162
16166 void write_bson_null(const string_t& name)
16167 {
16168 write_bson_entry_header(name, 0x0A);
16169 }
16170
16174 static std::size_t calc_bson_integer_size(const std::int64_t value)
16175 {
16176 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16177 ? sizeof(std::int32_t)
16178 : sizeof(std::int64_t);
16179 }
16180
16184 void write_bson_integer(const string_t& name,
16185 const std::int64_t value)
16186 {
16187 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16188 {
16189 write_bson_entry_header(name, 0x10); // int32
16190 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16191 }
16192 else
16193 {
16194 write_bson_entry_header(name, 0x12); // int64
16195 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16196 }
16197 }
16198
16202 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16203 {
16204 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16205 ? sizeof(std::int32_t)
16206 : sizeof(std::int64_t);
16207 }
16208
16212 void write_bson_unsigned(const string_t& name,
16213 const BasicJsonType& j)
16214 {
16215 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16216 {
16217 write_bson_entry_header(name, 0x10 /* int32 */);
16218 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16219 }
16220 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16221 {
16222 write_bson_entry_header(name, 0x12 /* int64 */);
16223 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16224 }
16225 else
16226 {
16227 JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
16228 }
16229 }
16230
16234 void write_bson_object_entry(const string_t& name,
16235 const typename BasicJsonType::object_t& value)
16236 {
16237 write_bson_entry_header(name, 0x03); // object
16238 write_bson_object(value);
16239 }
16240
16244 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16245 {
16246 std::size_t array_index = 0ul;
16247
16248 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)
16249 {
16250 return result + calc_bson_element_size(std::to_string(array_index++), el);
16251 });
16252
16253 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16254 }
16255
16259 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16260 {
16261 return sizeof(std::int32_t) + value.size() + 1ul;
16262 }
16263
16267 void write_bson_array(const string_t& name,
16268 const typename BasicJsonType::array_t& value)
16269 {
16270 write_bson_entry_header(name, 0x04); // array
16271 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16272
16273 std::size_t array_index = 0ul;
16274
16275 for (const auto& el : value)
16276 {
16277 write_bson_element(std::to_string(array_index++), el);
16278 }
16279
16280 oa->write_character(to_char_type(0x00));
16281 }
16282
16286 void write_bson_binary(const string_t& name,
16287 const binary_t& value)
16288 {
16289 write_bson_entry_header(name, 0x05);
16290
16291 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16292 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16293
16294 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16295 }
16296
16301 static std::size_t calc_bson_element_size(const string_t& name,
16302 const BasicJsonType& j)
16303 {
16304 const auto header_size = calc_bson_entry_header_size(name, j);
16305 switch (j.type())
16306 {
16307 case value_t::object:
16308 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16309
16310 case value_t::array:
16311 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16312
16313 case value_t::binary:
16314 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16315
16316 case value_t::boolean:
16317 return header_size + 1ul;
16318
16319 case value_t::number_float:
16320 return header_size + 8ul;
16321
16322 case value_t::number_integer:
16323 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16324
16325 case value_t::number_unsigned:
16326 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16327
16328 case value_t::string:
16329 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16330
16331 case value_t::null:
16332 return header_size + 0ul;
16333
16334 // LCOV_EXCL_START
16335 case value_t::discarded:
16336 default:
16337 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16338 return 0ul;
16339 // LCOV_EXCL_STOP
16340 }
16341 }
16342
16349 void write_bson_element(const string_t& name,
16350 const BasicJsonType& j)
16351 {
16352 switch (j.type())
16353 {
16354 case value_t::object:
16355 return write_bson_object_entry(name, *j.m_data.m_value.object);
16356
16357 case value_t::array:
16358 return write_bson_array(name, *j.m_data.m_value.array);
16359
16360 case value_t::binary:
16361 return write_bson_binary(name, *j.m_data.m_value.binary);
16362
16363 case value_t::boolean:
16364 return write_bson_boolean(name, j.m_data.m_value.boolean);
16365
16366 case value_t::number_float:
16367 return write_bson_double(name, j.m_data.m_value.number_float);
16368
16369 case value_t::number_integer:
16370 return write_bson_integer(name, j.m_data.m_value.number_integer);
16371
16372 case value_t::number_unsigned:
16373 return write_bson_unsigned(name, j);
16374
16375 case value_t::string:
16376 return write_bson_string(name, *j.m_data.m_value.string);
16377
16378 case value_t::null:
16379 return write_bson_null(name);
16380
16381 // LCOV_EXCL_START
16382 case value_t::discarded:
16383 default:
16384 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16385 return;
16386 // LCOV_EXCL_STOP
16387 }
16388 }
16389
16396 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
16397 {
16398 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
16399 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
16400 {
16401 return result += calc_bson_element_size(el.first, el.second);
16402 });
16403
16404 return sizeof(std::int32_t) + document_size + 1ul;
16405 }
16406
16411 void write_bson_object(const typename BasicJsonType::object_t& value)
16412 {
16413 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
16414
16415 for (const auto& el : value)
16416 {
16417 write_bson_element(el.first, el.second);
16418 }
16419
16420 oa->write_character(to_char_type(0x00));
16421 }
16422
16424 // CBOR //
16426
16427 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
16428 {
16429 return to_char_type(0xFA); // Single-Precision Float
16430 }
16431
16432 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
16433 {
16434 return to_char_type(0xFB); // Double-Precision Float
16435 }
16436
16438 // MsgPack //
16440
16441 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
16442 {
16443 return to_char_type(0xCA); // float 32
16444 }
16445
16446 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
16447 {
16448 return to_char_type(0xCB); // float 64
16449 }
16450
16452 // UBJSON //
16454
16455 // UBJSON: write number (floating point)
16456 template<typename NumberType, typename std::enable_if<
16457 std::is_floating_point<NumberType>::value, int>::type = 0>
16458 void write_number_with_ubjson_prefix(const NumberType n,
16459 const bool add_prefix,
16460 const bool use_bjdata)
16461 {
16462 if (add_prefix)
16463 {
16464 oa->write_character(get_ubjson_float_prefix(n));
16465 }
16466 write_number(n, use_bjdata);
16467 }
16468
16469 // UBJSON: write number (unsigned integer)
16470 template<typename NumberType, typename std::enable_if<
16471 std::is_unsigned<NumberType>::value, int>::type = 0>
16472 void write_number_with_ubjson_prefix(const NumberType n,
16473 const bool add_prefix,
16474 const bool use_bjdata)
16475 {
16476 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16477 {
16478 if (add_prefix)
16479 {
16480 oa->write_character(to_char_type('i')); // int8
16481 }
16482 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16483 }
16484 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
16485 {
16486 if (add_prefix)
16487 {
16488 oa->write_character(to_char_type('U')); // uint8
16489 }
16490 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16491 }
16492 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16493 {
16494 if (add_prefix)
16495 {
16496 oa->write_character(to_char_type('I')); // int16
16497 }
16498 write_number(static_cast<std::int16_t>(n), use_bjdata);
16499 }
16500 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
16501 {
16502 if (add_prefix)
16503 {
16504 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16505 }
16506 write_number(static_cast<std::uint16_t>(n), use_bjdata);
16507 }
16508 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16509 {
16510 if (add_prefix)
16511 {
16512 oa->write_character(to_char_type('l')); // int32
16513 }
16514 write_number(static_cast<std::int32_t>(n), use_bjdata);
16515 }
16516 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
16517 {
16518 if (add_prefix)
16519 {
16520 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16521 }
16522 write_number(static_cast<std::uint32_t>(n), use_bjdata);
16523 }
16524 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16525 {
16526 if (add_prefix)
16527 {
16528 oa->write_character(to_char_type('L')); // int64
16529 }
16530 write_number(static_cast<std::int64_t>(n), use_bjdata);
16531 }
16532 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
16533 {
16534 if (add_prefix)
16535 {
16536 oa->write_character(to_char_type('M')); // uint64 - bjdata only
16537 }
16538 write_number(static_cast<std::uint64_t>(n), use_bjdata);
16539 }
16540 else
16541 {
16542 if (add_prefix)
16543 {
16544 oa->write_character(to_char_type('H')); // high-precision number
16545 }
16546
16547 const auto number = BasicJsonType(n).dump();
16548 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16549 for (std::size_t i = 0; i < number.size(); ++i)
16550 {
16551 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16552 }
16553 }
16554 }
16555
16556 // UBJSON: write number (signed integer)
16557 template < typename NumberType, typename std::enable_if <
16558 std::is_signed<NumberType>::value&&
16559 !std::is_floating_point<NumberType>::value, int >::type = 0 >
16560 void write_number_with_ubjson_prefix(const NumberType n,
16561 const bool add_prefix,
16562 const bool use_bjdata)
16563 {
16564 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
16565 {
16566 if (add_prefix)
16567 {
16568 oa->write_character(to_char_type('i')); // int8
16569 }
16570 write_number(static_cast<std::int8_t>(n), use_bjdata);
16571 }
16572 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)()))
16573 {
16574 if (add_prefix)
16575 {
16576 oa->write_character(to_char_type('U')); // uint8
16577 }
16578 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16579 }
16580 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
16581 {
16582 if (add_prefix)
16583 {
16584 oa->write_character(to_char_type('I')); // int16
16585 }
16586 write_number(static_cast<std::int16_t>(n), use_bjdata);
16587 }
16588 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)())))
16589 {
16590 if (add_prefix)
16591 {
16592 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16593 }
16594 write_number(static_cast<uint16_t>(n), use_bjdata);
16595 }
16596 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
16597 {
16598 if (add_prefix)
16599 {
16600 oa->write_character(to_char_type('l')); // int32
16601 }
16602 write_number(static_cast<std::int32_t>(n), use_bjdata);
16603 }
16604 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)())))
16605 {
16606 if (add_prefix)
16607 {
16608 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16609 }
16610 write_number(static_cast<uint32_t>(n), use_bjdata);
16611 }
16612 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
16613 {
16614 if (add_prefix)
16615 {
16616 oa->write_character(to_char_type('L')); // int64
16617 }
16618 write_number(static_cast<std::int64_t>(n), use_bjdata);
16619 }
16620 // LCOV_EXCL_START
16621 else
16622 {
16623 if (add_prefix)
16624 {
16625 oa->write_character(to_char_type('H')); // high-precision number
16626 }
16627
16628 const auto number = BasicJsonType(n).dump();
16629 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16630 for (std::size_t i = 0; i < number.size(); ++i)
16631 {
16632 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16633 }
16634 }
16635 // LCOV_EXCL_STOP
16636 }
16637
16641 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
16642 {
16643 switch (j.type())
16644 {
16645 case value_t::null:
16646 return 'Z';
16647
16648 case value_t::boolean:
16649 return j.m_data.m_value.boolean ? 'T' : 'F';
16650
16651 case value_t::number_integer:
16652 {
16653 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)())
16654 {
16655 return 'i';
16656 }
16657 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)())
16658 {
16659 return 'U';
16660 }
16661 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)())
16662 {
16663 return 'I';
16664 }
16665 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)()))
16666 {
16667 return 'u';
16668 }
16669 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)())
16670 {
16671 return 'l';
16672 }
16673 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)()))
16674 {
16675 return 'm';
16676 }
16677 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)())
16678 {
16679 return 'L';
16680 }
16681 // anything else is treated as high-precision number
16682 return 'H'; // LCOV_EXCL_LINE
16683 }
16684
16685 case value_t::number_unsigned:
16686 {
16687 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16688 {
16689 return 'i';
16690 }
16691 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
16692 {
16693 return 'U';
16694 }
16695 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16696 {
16697 return 'I';
16698 }
16699 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
16700 {
16701 return 'u';
16702 }
16703 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16704 {
16705 return 'l';
16706 }
16707 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
16708 {
16709 return 'm';
16710 }
16711 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16712 {
16713 return 'L';
16714 }
16715 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16716 {
16717 return 'M';
16718 }
16719 // anything else is treated as high-precision number
16720 return 'H'; // LCOV_EXCL_LINE
16721 }
16722
16723 case value_t::number_float:
16724 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
16725
16726 case value_t::string:
16727 return 'S';
16728
16729 case value_t::array: // fallthrough
16730 case value_t::binary:
16731 return '[';
16732
16733 case value_t::object:
16734 return '{';
16735
16736 case value_t::discarded:
16737 default: // discarded values
16738 return 'N';
16739 }
16740 }
16741
16742 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
16743 {
16744 return 'd'; // float 32
16745 }
16746
16747 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
16748 {
16749 return 'D'; // float 64
16750 }
16751
16755 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
16756 {
16757 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
16758 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
16759 };
16760
16761 string_t key = "_ArrayType_";
16762 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
16763 if (it == bjdtype.end())
16764 {
16765 return true;
16766 }
16767 CharType dtype = it->second;
16768
16769 key = "_ArraySize_";
16770 std::size_t len = (value.at(key).empty() ? 0 : 1);
16771 for (const auto& el : value.at(key))
16772 {
16773 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
16774 }
16775
16776 key = "_ArrayData_";
16777 if (value.at(key).size() != len)
16778 {
16779 return true;
16780 }
16781
16782 oa->write_character('[');
16783 oa->write_character('$');
16784 oa->write_character(dtype);
16785 oa->write_character('#');
16786
16787 key = "_ArraySize_";
16788 write_ubjson(value.at(key), use_count, use_type, true, true);
16789
16790 key = "_ArrayData_";
16791 if (dtype == 'U' || dtype == 'C')
16792 {
16793 for (const auto& el : value.at(key))
16794 {
16795 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
16796 }
16797 }
16798 else if (dtype == 'i')
16799 {
16800 for (const auto& el : value.at(key))
16801 {
16802 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
16803 }
16804 }
16805 else if (dtype == 'u')
16806 {
16807 for (const auto& el : value.at(key))
16808 {
16809 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
16810 }
16811 }
16812 else if (dtype == 'I')
16813 {
16814 for (const auto& el : value.at(key))
16815 {
16816 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
16817 }
16818 }
16819 else if (dtype == 'm')
16820 {
16821 for (const auto& el : value.at(key))
16822 {
16823 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
16824 }
16825 }
16826 else if (dtype == 'l')
16827 {
16828 for (const auto& el : value.at(key))
16829 {
16830 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
16831 }
16832 }
16833 else if (dtype == 'M')
16834 {
16835 for (const auto& el : value.at(key))
16836 {
16837 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
16838 }
16839 }
16840 else if (dtype == 'L')
16841 {
16842 for (const auto& el : value.at(key))
16843 {
16844 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
16845 }
16846 }
16847 else if (dtype == 'd')
16848 {
16849 for (const auto& el : value.at(key))
16850 {
16851 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
16852 }
16853 }
16854 else if (dtype == 'D')
16855 {
16856 for (const auto& el : value.at(key))
16857 {
16858 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
16859 }
16860 }
16861 return false;
16862 }
16863
16865 // Utility functions //
16867
16868 /*
16869 @brief write a number to output input
16870 @param[in] n number of type @a NumberType
16871 @param[in] OutputIsLittleEndian Set to true if output data is
16872 required to be little endian
16873 @tparam NumberType the type of the number
16874
16875 @note This function needs to respect the system's endianness, because bytes
16876 in CBOR, MessagePack, and UBJSON are stored in network order (big
16877 endian) and therefore need reordering on little endian systems.
16878 On the other hand, BSON and BJData use little endian and should reorder
16879 on big endian systems.
16880 */
16881 template<typename NumberType>
16882 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
16883 {
16884 // step 1: write number to array of length NumberType
16885 std::array<CharType, sizeof(NumberType)> vec{};
16886 std::memcpy(vec.data(), &n, sizeof(NumberType));
16887
16888 // step 2: write array to output (with possible reordering)
16889 if (is_little_endian != OutputIsLittleEndian)
16890 {
16891 // reverse byte order prior to conversion if necessary
16892 std::reverse(vec.begin(), vec.end());
16893 }
16894
16895 oa->write_characters(vec.data(), sizeof(NumberType));
16896 }
16897
16898 void write_compact_float(const number_float_t n, detail::input_format_t format)
16899 {
16900#ifdef __GNUC__
16901#pragma GCC diagnostic push
16902#pragma GCC diagnostic ignored "-Wfloat-equal"
16903#endif
16904 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
16905 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
16906 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
16907 {
16908 oa->write_character(format == detail::input_format_t::cbor
16909 ? get_cbor_float_prefix(static_cast<float>(n))
16910 : get_msgpack_float_prefix(static_cast<float>(n)));
16911 write_number(static_cast<float>(n));
16912 }
16913 else
16914 {
16915 oa->write_character(format == detail::input_format_t::cbor
16916 ? get_cbor_float_prefix(n)
16917 : get_msgpack_float_prefix(n));
16918 write_number(n);
16919 }
16920#ifdef __GNUC__
16921#pragma GCC diagnostic pop
16922#endif
16923 }
16924
16925 public:
16926 // The following to_char_type functions are implement the conversion
16927 // between uint8_t and CharType. In case CharType is not unsigned,
16928 // such a conversion is required to allow values greater than 128.
16929 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
16930 template < typename C = CharType,
16931 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
16932 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16933 {
16934 return *reinterpret_cast<char*>(&x);
16935 }
16936
16937 template < typename C = CharType,
16938 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
16939 static CharType to_char_type(std::uint8_t x) noexcept
16940 {
16941 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
16942 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
16943 CharType result;
16944 std::memcpy(&result, &x, sizeof(x));
16945 return result;
16946 }
16947
16948 template<typename C = CharType,
16950 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16951 {
16952 return x;
16953 }
16954
16955 template < typename InputCharType, typename C = CharType,
16956 enable_if_t <
16957 std::is_signed<C>::value &&
16958 std::is_signed<char>::value &&
16959 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
16960 > * = nullptr >
16961 static constexpr CharType to_char_type(InputCharType x) noexcept
16962 {
16963 return x;
16964 }
16965
16966 private:
16968 const bool is_little_endian = little_endianness();
16969
16971 output_adapter_t<CharType> oa = nullptr;
16972};
16973
16974} // namespace detail
16976
16977// #include <nlohmann/detail/output/output_adapters.hpp>
16978
16979// #include <nlohmann/detail/output/serializer.hpp>
16980// __ _____ _____ _____
16981// __| | __| | | | JSON for Modern C++
16982// | | |__ | | | | | | version 3.11.3
16983// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16984//
16985// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de>
16986// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
16987// SPDX-License-Identifier: MIT
16988
16989
16990
16991#include <algorithm> // reverse, remove, fill, find, none_of
16992#include <array> // array
16993#include <clocale> // localeconv, lconv
16994#include <cmath> // labs, isfinite, isnan, signbit
16995#include <cstddef> // size_t, ptrdiff_t
16996#include <cstdint> // uint8_t
16997#include <cstdio> // snprintf
16998#include <limits> // numeric_limits
16999#include <string> // string, char_traits
17000#include <iomanip> // setfill, setw
17001#include <type_traits> // is_same
17002#include <utility> // move
17003
17004// #include <nlohmann/detail/conversions/to_chars.hpp>
17005// __ _____ _____ _____
17006// __| | __| | | | JSON for Modern C++
17007// | | |__ | | | | | | version 3.11.3
17008// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17009//
17010// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
17011// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
17012// SPDX-License-Identifier: MIT
17013
17014
17015
17016#include <array> // array
17017#include <cmath> // signbit, isfinite
17018#include <cstdint> // intN_t, uintN_t
17019#include <cstring> // memcpy, memmove
17020#include <limits> // numeric_limits
17021#include <type_traits> // conditional
17022
17023// #include <nlohmann/detail/macro_scope.hpp>
17024
17025
17027namespace detail
17028{
17029
17049namespace dtoa_impl
17050{
17051
17052template<typename Target, typename Source>
17053Target reinterpret_bits(const Source source)
17054{
17055 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
17056
17057 Target target;
17058 std::memcpy(&target, &source, sizeof(Source));
17059 return target;
17060}
17061
17062struct diyfp // f * 2^e
17063{
17064 static constexpr int kPrecision = 64; // = q
17065
17066 std::uint64_t f = 0;
17067 int e = 0;
17068
17069 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
17070
17075 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
17076 {
17077 JSON_ASSERT(x.e == y.e);
17078 JSON_ASSERT(x.f >= y.f);
17079
17080 return {x.f - y.f, x.e};
17081 }
17082
17087 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17088 {
17089 static_assert(kPrecision == 64, "internal error");
17090
17091 // Computes:
17092 // f = round((x.f * y.f) / 2^q)
17093 // e = x.e + y.e + q
17094
17095 // Emulate the 64-bit * 64-bit multiplication:
17096 //
17097 // p = u * v
17098 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17099 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17100 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17101 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17102 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17103 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17104 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17105 //
17106 // (Since Q might be larger than 2^32 - 1)
17107 //
17108 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17109 //
17110 // (Q_hi + H does not overflow a 64-bit int)
17111 //
17112 // = p_lo + 2^64 p_hi
17113
17114 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17115 const std::uint64_t u_hi = x.f >> 32u;
17116 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17117 const std::uint64_t v_hi = y.f >> 32u;
17118
17119 const std::uint64_t p0 = u_lo * v_lo;
17120 const std::uint64_t p1 = u_lo * v_hi;
17121 const std::uint64_t p2 = u_hi * v_lo;
17122 const std::uint64_t p3 = u_hi * v_hi;
17123
17124 const std::uint64_t p0_hi = p0 >> 32u;
17125 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17126 const std::uint64_t p1_hi = p1 >> 32u;
17127 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17128 const std::uint64_t p2_hi = p2 >> 32u;
17129
17130 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17131
17132 // The full product might now be computed as
17133 //
17134 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17135 // p_lo = p0_lo + (Q << 32)
17136 //
17137 // But in this particular case here, the full p_lo is not required.
17138 // Effectively we only need to add the highest bit in p_lo to p_hi (and
17139 // Q_hi + 1 does not overflow).
17140
17141 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17142
17143 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17144
17145 return {h, x.e + y.e + 64};
17146 }
17147
17152 static diyfp normalize(diyfp x) noexcept
17153 {
17154 JSON_ASSERT(x.f != 0);
17155
17156 while ((x.f >> 63u) == 0)
17157 {
17158 x.f <<= 1u;
17159 x.e--;
17160 }
17161
17162 return x;
17163 }
17164
17169 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17170 {
17171 const int delta = x.e - target_exponent;
17172
17173 JSON_ASSERT(delta >= 0);
17174 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17175
17176 return {x.f << delta, target_exponent};
17177 }
17178};
17179
17181{
17185};
17186
17193template<typename FloatType>
17195{
17196 JSON_ASSERT(std::isfinite(value));
17197 JSON_ASSERT(value > 0);
17198
17199 // Convert the IEEE representation into a diyfp.
17200 //
17201 // If v is denormal:
17202 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17203 // If v is normalized:
17204 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17205
17206 static_assert(std::numeric_limits<FloatType>::is_iec559,
17207 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17208
17209 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17210 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17211 constexpr int kMinExp = 1 - kBias;
17212 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17213
17214 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17215
17216 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17217 const std::uint64_t E = bits >> (kPrecision - 1);
17218 const std::uint64_t F = bits & (kHiddenBit - 1);
17219
17220 const bool is_denormal = E == 0;
17221 const diyfp v = is_denormal
17222 ? diyfp(F, kMinExp)
17223 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17224
17225 // Compute the boundaries m- and m+ of the floating-point value
17226 // v = f * 2^e.
17227 //
17228 // Determine v- and v+, the floating-point predecessor and successor if v,
17229 // respectively.
17230 //
17231 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17232 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17233 //
17234 // v+ = v + 2^e
17235 //
17236 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17237 // between m- and m+ round to v, regardless of how the input rounding
17238 // algorithm breaks ties.
17239 //
17240 // ---+-------------+-------------+-------------+-------------+--- (A)
17241 // v- m- v m+ v+
17242 //
17243 // -----------------+------+------+-------------+-------------+--- (B)
17244 // v- m- v m+ v+
17245
17246 const bool lower_boundary_is_closer = F == 0 && E > 1;
17247 const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
17248 const diyfp m_minus = lower_boundary_is_closer
17249 ? diyfp((4 * v.f) - 1, v.e - 2) // (B)
17250 : diyfp((2 * v.f) - 1, v.e - 1); // (A)
17251
17252 // Determine the normalized w+ = m+.
17253 const diyfp w_plus = diyfp::normalize(m_plus);
17254
17255 // Determine w- = m- such that e_(w-) = e_(w+).
17256 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17257
17258 return {diyfp::normalize(v), w_minus, w_plus};
17259}
17260
17261// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17262// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17263// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17264//
17265// alpha <= e = e_c + e_w + q <= gamma
17266//
17267// or
17268//
17269// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17270// <= f_c * f_w * 2^gamma
17271//
17272// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17273//
17274// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17275//
17276// or
17277//
17278// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17279//
17280// The choice of (alpha,gamma) determines the size of the table and the form of
17281// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17282// in practice:
17283//
17284// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17285// processed independently: An integral part p1, and a fractional part p2:
17286//
17287// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17288// = (f div 2^-e) + (f mod 2^-e) * 2^e
17289// = p1 + p2 * 2^e
17290//
17291// The conversion of p1 into decimal form requires a series of divisions and
17292// modulos by (a power of) 10. These operations are faster for 32-bit than for
17293// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17294// achieved by choosing
17295//
17296// -e >= 32 or e <= -32 := gamma
17297//
17298// In order to convert the fractional part
17299//
17300// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17301//
17302// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17303// d[-i] are extracted in order:
17304//
17305// (10 * p2) div 2^-e = d[-1]
17306// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17307//
17308// The multiplication by 10 must not overflow. It is sufficient to choose
17309//
17310// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17311//
17312// Since p2 = f mod 2^-e < 2^-e,
17313//
17314// -e <= 60 or e >= -60 := alpha
17315
17316constexpr int kAlpha = -60;
17317constexpr int kGamma = -32;
17318
17319struct cached_power // c = f * 2^e ~= 10^k
17320{
17321 std::uint64_t f;
17322 int e;
17323 int k;
17324};
17325
17334{
17335 // Now
17336 //
17337 // alpha <= e_c + e + q <= gamma (1)
17338 // ==> f_c * 2^alpha <= c * 2^e * 2^q
17339 //
17340 // and since the c's are normalized, 2^(q-1) <= f_c,
17341 //
17342 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
17343 // ==> 2^(alpha - e - 1) <= c
17344 //
17345 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
17346 //
17347 // k = ceil( log_10( 2^(alpha - e - 1) ) )
17348 // = ceil( (alpha - e - 1) * log_10(2) )
17349 //
17350 // From the paper:
17351 // "In theory the result of the procedure could be wrong since c is rounded,
17352 // and the computation itself is approximated [...]. In practice, however,
17353 // this simple function is sufficient."
17354 //
17355 // For IEEE double precision floating-point numbers converted into
17356 // normalized diyfp's w = f * 2^e, with q = 64,
17357 //
17358 // e >= -1022 (min IEEE exponent)
17359 // -52 (p - 1)
17360 // -52 (p - 1, possibly normalize denormal IEEE numbers)
17361 // -11 (normalize the diyfp)
17362 // = -1137
17363 //
17364 // and
17365 //
17366 // e <= +1023 (max IEEE exponent)
17367 // -52 (p - 1)
17368 // -11 (normalize the diyfp)
17369 // = 960
17370 //
17371 // This binary exponent range [-1137,960] results in a decimal exponent
17372 // range [-307,324]. One does not need to store a cached power for each
17373 // k in this range. For each such k it suffices to find a cached power
17374 // such that the exponent of the product lies in [alpha,gamma].
17375 // This implies that the difference of the decimal exponents of adjacent
17376 // table entries must be less than or equal to
17377 //
17378 // floor( (gamma - alpha) * log_10(2) ) = 8.
17379 //
17380 // (A smaller distance gamma-alpha would require a larger table.)
17381
17382 // NB:
17383 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
17384
17385 constexpr int kCachedPowersMinDecExp = -300;
17386 constexpr int kCachedPowersDecStep = 8;
17387
17388 static constexpr std::array<cached_power, 79> kCachedPowers =
17389 {
17390 {
17391 { 0xAB70FE17C79AC6CA, -1060, -300 },
17392 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
17393 { 0xBE5691EF416BD60C, -1007, -284 },
17394 { 0x8DD01FAD907FFC3C, -980, -276 },
17395 { 0xD3515C2831559A83, -954, -268 },
17396 { 0x9D71AC8FADA6C9B5, -927, -260 },
17397 { 0xEA9C227723EE8BCB, -901, -252 },
17398 { 0xAECC49914078536D, -874, -244 },
17399 { 0x823C12795DB6CE57, -847, -236 },
17400 { 0xC21094364DFB5637, -821, -228 },
17401 { 0x9096EA6F3848984F, -794, -220 },
17402 { 0xD77485CB25823AC7, -768, -212 },
17403 { 0xA086CFCD97BF97F4, -741, -204 },
17404 { 0xEF340A98172AACE5, -715, -196 },
17405 { 0xB23867FB2A35B28E, -688, -188 },
17406 { 0x84C8D4DFD2C63F3B, -661, -180 },
17407 { 0xC5DD44271AD3CDBA, -635, -172 },
17408 { 0x936B9FCEBB25C996, -608, -164 },
17409 { 0xDBAC6C247D62A584, -582, -156 },
17410 { 0xA3AB66580D5FDAF6, -555, -148 },
17411 { 0xF3E2F893DEC3F126, -529, -140 },
17412 { 0xB5B5ADA8AAFF80B8, -502, -132 },
17413 { 0x87625F056C7C4A8B, -475, -124 },
17414 { 0xC9BCFF6034C13053, -449, -116 },
17415 { 0x964E858C91BA2655, -422, -108 },
17416 { 0xDFF9772470297EBD, -396, -100 },
17417 { 0xA6DFBD9FB8E5B88F, -369, -92 },
17418 { 0xF8A95FCF88747D94, -343, -84 },
17419 { 0xB94470938FA89BCF, -316, -76 },
17420 { 0x8A08F0F8BF0F156B, -289, -68 },
17421 { 0xCDB02555653131B6, -263, -60 },
17422 { 0x993FE2C6D07B7FAC, -236, -52 },
17423 { 0xE45C10C42A2B3B06, -210, -44 },
17424 { 0xAA242499697392D3, -183, -36 },
17425 { 0xFD87B5F28300CA0E, -157, -28 },
17426 { 0xBCE5086492111AEB, -130, -20 },
17427 { 0x8CBCCC096F5088CC, -103, -12 },
17428 { 0xD1B71758E219652C, -77, -4 },
17429 { 0x9C40000000000000, -50, 4 },
17430 { 0xE8D4A51000000000, -24, 12 },
17431 { 0xAD78EBC5AC620000, 3, 20 },
17432 { 0x813F3978F8940984, 30, 28 },
17433 { 0xC097CE7BC90715B3, 56, 36 },
17434 { 0x8F7E32CE7BEA5C70, 83, 44 },
17435 { 0xD5D238A4ABE98068, 109, 52 },
17436 { 0x9F4F2726179A2245, 136, 60 },
17437 { 0xED63A231D4C4FB27, 162, 68 },
17438 { 0xB0DE65388CC8ADA8, 189, 76 },
17439 { 0x83C7088E1AAB65DB, 216, 84 },
17440 { 0xC45D1DF942711D9A, 242, 92 },
17441 { 0x924D692CA61BE758, 269, 100 },
17442 { 0xDA01EE641A708DEA, 295, 108 },
17443 { 0xA26DA3999AEF774A, 322, 116 },
17444 { 0xF209787BB47D6B85, 348, 124 },
17445 { 0xB454E4A179DD1877, 375, 132 },
17446 { 0x865B86925B9BC5C2, 402, 140 },
17447 { 0xC83553C5C8965D3D, 428, 148 },
17448 { 0x952AB45CFA97A0B3, 455, 156 },
17449 { 0xDE469FBD99A05FE3, 481, 164 },
17450 { 0xA59BC234DB398C25, 508, 172 },
17451 { 0xF6C69A72A3989F5C, 534, 180 },
17452 { 0xB7DCBF5354E9BECE, 561, 188 },
17453 { 0x88FCF317F22241E2, 588, 196 },
17454 { 0xCC20CE9BD35C78A5, 614, 204 },
17455 { 0x98165AF37B2153DF, 641, 212 },
17456 { 0xE2A0B5DC971F303A, 667, 220 },
17457 { 0xA8D9D1535CE3B396, 694, 228 },
17458 { 0xFB9B7CD9A4A7443C, 720, 236 },
17459 { 0xBB764C4CA7A44410, 747, 244 },
17460 { 0x8BAB8EEFB6409C1A, 774, 252 },
17461 { 0xD01FEF10A657842C, 800, 260 },
17462 { 0x9B10A4E5E9913129, 827, 268 },
17463 { 0xE7109BFBA19C0C9D, 853, 276 },
17464 { 0xAC2820D9623BF429, 880, 284 },
17465 { 0x80444B5E7AA7CF85, 907, 292 },
17466 { 0xBF21E44003ACDD2D, 933, 300 },
17467 { 0x8E679C2F5E44FF8F, 960, 308 },
17468 { 0xD433179D9C8CB841, 986, 316 },
17469 { 0x9E19DB92B4E31BA9, 1013, 324 },
17470 }
17471 };
17472
17473 // This computation gives exactly the same results for k as
17474 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
17475 // for |e| <= 1500, but doesn't require floating-point operations.
17476 // NB: log_10(2) ~= 78913 / 2^18
17477 JSON_ASSERT(e >= -1500);
17478 JSON_ASSERT(e <= 1500);
17479 const int f = kAlpha - e - 1;
17480 const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
17481
17482 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
17483 JSON_ASSERT(index >= 0);
17484 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
17485
17486 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
17487 JSON_ASSERT(kAlpha <= cached.e + e + 64);
17488 JSON_ASSERT(kGamma >= cached.e + e + 64);
17489
17490 return cached;
17491}
17492
17497inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
17498{
17499 // LCOV_EXCL_START
17500 if (n >= 1000000000)
17501 {
17502 pow10 = 1000000000;
17503 return 10;
17504 }
17505 // LCOV_EXCL_STOP
17506 if (n >= 100000000)
17507 {
17508 pow10 = 100000000;
17509 return 9;
17510 }
17511 if (n >= 10000000)
17512 {
17513 pow10 = 10000000;
17514 return 8;
17515 }
17516 if (n >= 1000000)
17517 {
17518 pow10 = 1000000;
17519 return 7;
17520 }
17521 if (n >= 100000)
17522 {
17523 pow10 = 100000;
17524 return 6;
17525 }
17526 if (n >= 10000)
17527 {
17528 pow10 = 10000;
17529 return 5;
17530 }
17531 if (n >= 1000)
17532 {
17533 pow10 = 1000;
17534 return 4;
17535 }
17536 if (n >= 100)
17537 {
17538 pow10 = 100;
17539 return 3;
17540 }
17541 if (n >= 10)
17542 {
17543 pow10 = 10;
17544 return 2;
17545 }
17546
17547 pow10 = 1;
17548 return 1;
17549}
17550
17551inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
17552 std::uint64_t rest, std::uint64_t ten_k)
17553{
17554 JSON_ASSERT(len >= 1);
17555 JSON_ASSERT(dist <= delta);
17556 JSON_ASSERT(rest <= delta);
17557 JSON_ASSERT(ten_k > 0);
17558
17559 // <--------------------------- delta ---->
17560 // <---- dist --------->
17561 // --------------[------------------+-------------------]--------------
17562 // M- w M+
17563 //
17564 // ten_k
17565 // <------>
17566 // <---- rest ---->
17567 // --------------[------------------+----+--------------]--------------
17568 // w V
17569 // = buf * 10^k
17570 //
17571 // ten_k represents a unit-in-the-last-place in the decimal representation
17572 // stored in buf.
17573 // Decrement buf by ten_k while this takes buf closer to w.
17574
17575 // The tests are written in this order to avoid overflow in unsigned
17576 // integer arithmetic.
17577
17578 while (rest < dist
17579 && delta - rest >= ten_k
17580 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
17581 {
17582 JSON_ASSERT(buf[len - 1] != '0');
17583 buf[len - 1]--;
17584 rest += ten_k;
17585 }
17586}
17587
17592inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
17593 diyfp M_minus, diyfp w, diyfp M_plus)
17594{
17595 static_assert(kAlpha >= -60, "internal error");
17596 static_assert(kGamma <= -32, "internal error");
17597
17598 // Generates the digits (and the exponent) of a decimal floating-point
17599 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
17600 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
17601 //
17602 // <--------------------------- delta ---->
17603 // <---- dist --------->
17604 // --------------[------------------+-------------------]--------------
17605 // M- w M+
17606 //
17607 // Grisu2 generates the digits of M+ from left to right and stops as soon as
17608 // V is in [M-,M+].
17609
17610 JSON_ASSERT(M_plus.e >= kAlpha);
17611 JSON_ASSERT(M_plus.e <= kGamma);
17612
17613 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
17614 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
17615
17616 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
17617 //
17618 // M+ = f * 2^e
17619 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
17620 // = ((p1 ) * 2^-e + (p2 )) * 2^e
17621 // = p1 + p2 * 2^e
17622
17623 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
17624
17625 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.)
17626 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
17627
17628 // 1)
17629 //
17630 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
17631
17632 JSON_ASSERT(p1 > 0);
17633
17634 std::uint32_t pow10{};
17635 const int k = find_largest_pow10(p1, pow10);
17636
17637 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
17638 //
17639 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
17640 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
17641 //
17642 // M+ = p1 + p2 * 2^e
17643 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
17644 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
17645 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
17646 //
17647 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
17648 //
17649 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
17650 //
17651 // but stop as soon as
17652 //
17653 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
17654
17655 int n = k;
17656 while (n > 0)
17657 {
17658 // Invariants:
17659 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
17660 // pow10 = 10^(n-1) <= p1 < 10^n
17661 //
17662 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
17663 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
17664 //
17665 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
17666 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
17667 //
17668 JSON_ASSERT(d <= 9);
17669 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17670 //
17671 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
17672 //
17673 p1 = r;
17674 n--;
17675 //
17676 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
17677 // pow10 = 10^n
17678 //
17679
17680 // Now check if enough digits have been generated.
17681 // Compute
17682 //
17683 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
17684 //
17685 // Note:
17686 // Since rest and delta share the same exponent e, it suffices to
17687 // compare the significands.
17688 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
17689 if (rest <= delta)
17690 {
17691 // V = buffer * 10^n, with M- <= V <= M+.
17692
17693 decimal_exponent += n;
17694
17695 // We may now just stop. But instead look if the buffer could be
17696 // decremented to bring V closer to w.
17697 //
17698 // pow10 = 10^n is now 1 ulp in the decimal representation V.
17699 // The rounding procedure works with diyfp's with an implicit
17700 // exponent of e.
17701 //
17702 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
17703 //
17704 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
17705 grisu2_round(buffer, length, dist, delta, rest, ten_n);
17706
17707 return;
17708 }
17709
17710 pow10 /= 10;
17711 //
17712 // pow10 = 10^(n-1) <= p1 < 10^n
17713 // Invariants restored.
17714 }
17715
17716 // 2)
17717 //
17718 // The digits of the integral part have been generated:
17719 //
17720 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
17721 // = buffer + p2 * 2^e
17722 //
17723 // Now generate the digits of the fractional part p2 * 2^e.
17724 //
17725 // Note:
17726 // No decimal point is generated: the exponent is adjusted instead.
17727 //
17728 // p2 actually represents the fraction
17729 //
17730 // p2 * 2^e
17731 // = p2 / 2^-e
17732 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
17733 //
17734 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
17735 //
17736 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
17737 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
17738 //
17739 // using
17740 //
17741 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
17742 // = ( d) * 2^-e + ( r)
17743 //
17744 // or
17745 // 10^m * p2 * 2^e = d + r * 2^e
17746 //
17747 // i.e.
17748 //
17749 // M+ = buffer + p2 * 2^e
17750 // = buffer + 10^-m * (d + r * 2^e)
17751 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
17752 //
17753 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
17754
17755 JSON_ASSERT(p2 > delta);
17756
17757 int m = 0;
17758 for (;;)
17759 {
17760 // Invariant:
17761 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
17762 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
17763 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
17764 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
17765 //
17766 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
17767 p2 *= 10;
17768 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
17769 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
17770 //
17771 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
17772 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
17773 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
17774 //
17775 JSON_ASSERT(d <= 9);
17776 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17777 //
17778 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
17779 //
17780 p2 = r;
17781 m++;
17782 //
17783 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
17784 // Invariant restored.
17785
17786 // Check if enough digits have been generated.
17787 //
17788 // 10^-m * p2 * 2^e <= delta * 2^e
17789 // p2 * 2^e <= 10^m * delta * 2^e
17790 // p2 <= 10^m * delta
17791 delta *= 10;
17792 dist *= 10;
17793 if (p2 <= delta)
17794 {
17795 break;
17796 }
17797 }
17798
17799 // V = buffer * 10^-m, with M- <= V <= M+.
17800
17801 decimal_exponent -= m;
17802
17803 // 1 ulp in the decimal representation is now 10^-m.
17804 // Since delta and dist are now scaled by 10^m, we need to do the
17805 // same with ulp in order to keep the units in sync.
17806 //
17807 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
17808 //
17809 const std::uint64_t ten_m = one.f;
17810 grisu2_round(buffer, length, dist, delta, p2, ten_m);
17811
17812 // By construction this algorithm generates the shortest possible decimal
17813 // number (Loitsch, Theorem 6.2) which rounds back to w.
17814 // For an input number of precision p, at least
17815 //
17816 // N = 1 + ceil(p * log_10(2))
17817 //
17818 // decimal digits are sufficient to identify all binary floating-point
17819 // numbers (Matula, "In-and-Out conversions").
17820 // This implies that the algorithm does not produce more than N decimal
17821 // digits.
17822 //
17823 // N = 17 for p = 53 (IEEE double precision)
17824 // N = 9 for p = 24 (IEEE single precision)
17825}
17826
17833inline void grisu2(char* buf, int& len, int& decimal_exponent,
17834 diyfp m_minus, diyfp v, diyfp m_plus)
17835{
17836 JSON_ASSERT(m_plus.e == m_minus.e);
17837 JSON_ASSERT(m_plus.e == v.e);
17838
17839 // --------(-----------------------+-----------------------)-------- (A)
17840 // m- v m+
17841 //
17842 // --------------------(-----------+-----------------------)-------- (B)
17843 // m- v m+
17844 //
17845 // First scale v (and m- and m+) such that the exponent is in the range
17846 // [alpha, gamma].
17847
17848 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
17849
17850 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
17851
17852 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
17853 const diyfp w = diyfp::mul(v, c_minus_k);
17854 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17855 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
17856
17857 // ----(---+---)---------------(---+---)---------------(---+---)----
17858 // w- w w+
17859 // = c*m- = c*v = c*m+
17860 //
17861 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
17862 // w+ are now off by a small amount.
17863 // In fact:
17864 //
17865 // w - v * 10^k < 1 ulp
17866 //
17867 // To account for this inaccuracy, add resp. subtract 1 ulp.
17868 //
17869 // --------+---[---------------(---+---)---------------]---+--------
17870 // w- M- w M+ w+
17871 //
17872 // Now any number in [M-, M+] (bounds included) will round to w when input,
17873 // regardless of how the input rounding algorithm breaks ties.
17874 //
17875 // And digit_gen generates the shortest possible such number in [M-, M+].
17876 // Note that this does not mean that Grisu2 always generates the shortest
17877 // possible number in the interval (m-, m+).
17878 const diyfp M_minus(w_minus.f + 1, w_minus.e);
17879 const diyfp M_plus (w_plus.f - 1, w_plus.e );
17880
17881 decimal_exponent = -cached.k; // = -(-k) = k
17882
17883 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
17884}
17885
17891template<typename FloatType>
17893void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
17894{
17895 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17896 "internal error: not enough precision");
17897
17898 JSON_ASSERT(std::isfinite(value));
17899 JSON_ASSERT(value > 0);
17900
17901 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
17902 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
17903 // decimal representations are not exactly "short".
17904 //
17905 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
17906 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
17907 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
17908 // does.
17909 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
17910 // representation using the corresponding std::from_chars function recovers value exactly". That
17911 // indicates that single precision floating-point numbers should be recovered using
17912 // 'std::strtof'.
17913 //
17914 // NB: If the neighbors are computed for single-precision numbers, there is a single float
17915 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
17916 // value is off by 1 ulp.
17917#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
17918 const boundaries w = compute_boundaries(static_cast<double>(value));
17919#else
17921#endif
17922
17923 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
17924}
17925
17933inline char* append_exponent(char* buf, int e)
17934{
17935 JSON_ASSERT(e > -1000);
17936 JSON_ASSERT(e < 1000);
17937
17938 if (e < 0)
17939 {
17940 e = -e;
17941 *buf++ = '-';
17942 }
17943 else
17944 {
17945 *buf++ = '+';
17946 }
17947
17948 auto k = static_cast<std::uint32_t>(e);
17949 if (k < 10)
17950 {
17951 // Always print at least two digits in the exponent.
17952 // This is for compatibility with printf("%g").
17953 *buf++ = '0';
17954 *buf++ = static_cast<char>('0' + k);
17955 }
17956 else if (k < 100)
17957 {
17958 *buf++ = static_cast<char>('0' + (k / 10));
17959 k %= 10;
17960 *buf++ = static_cast<char>('0' + k);
17961 }
17962 else
17963 {
17964 *buf++ = static_cast<char>('0' + (k / 100));
17965 k %= 100;
17966 *buf++ = static_cast<char>('0' + (k / 10));
17967 k %= 10;
17968 *buf++ = static_cast<char>('0' + k);
17969 }
17970
17971 return buf;
17972}
17973
17985inline char* format_buffer(char* buf, int len, int decimal_exponent,
17986 int min_exp, int max_exp)
17987{
17988 JSON_ASSERT(min_exp < 0);
17989 JSON_ASSERT(max_exp > 0);
17990
17991 const int k = len;
17992 const int n = len + decimal_exponent;
17993
17994 // v = buf * 10^(n-k)
17995 // k is the length of the buffer (number of decimal digits)
17996 // n is the position of the decimal point relative to the start of the buffer.
17997
17998 if (k <= n && n <= max_exp)
17999 {
18000 // digits[000]
18001 // len <= max_exp + 2
18002
18003 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
18004 // Make it look like a floating-point number (#362, #378)
18005 buf[n + 0] = '.';
18006 buf[n + 1] = '0';
18007 return buf + (static_cast<size_t>(n) + 2);
18008 }
18009
18010 if (0 < n && n <= max_exp)
18011 {
18012 // dig.its
18013 // len <= max_digits10 + 1
18014
18015 JSON_ASSERT(k > n);
18016
18017 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
18018 buf[n] = '.';
18019 return buf + (static_cast<size_t>(k) + 1U);
18020 }
18021
18022 if (min_exp < n && n <= 0)
18023 {
18024 // 0.[000]digits
18025 // len <= 2 + (-min_exp - 1) + max_digits10
18026
18027 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
18028 buf[0] = '0';
18029 buf[1] = '.';
18030 std::memset(buf + 2, '0', static_cast<size_t>(-n));
18031 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
18032 }
18033
18034 if (k == 1)
18035 {
18036 // dE+123
18037 // len <= 1 + 5
18038
18039 buf += 1;
18040 }
18041 else
18042 {
18043 // d.igitsE+123
18044 // len <= max_digits10 + 1 + 5
18045
18046 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
18047 buf[1] = '.';
18048 buf += 1 + static_cast<size_t>(k);
18049 }
18050
18051 *buf++ = 'e';
18052 return append_exponent(buf, n - 1);
18053}
18054
18055} // namespace dtoa_impl
18056
18067template<typename FloatType>
18070char* to_chars(char* first, const char* last, FloatType value)
18071{
18072 static_cast<void>(last); // maybe unused - fix warning
18073 JSON_ASSERT(std::isfinite(value));
18074
18075 // Use signbit(value) instead of (value < 0) since signbit works for -0.
18076 if (std::signbit(value))
18077 {
18078 value = -value;
18079 *first++ = '-';
18080 }
18081
18082#ifdef __GNUC__
18083#pragma GCC diagnostic push
18084#pragma GCC diagnostic ignored "-Wfloat-equal"
18085#endif
18086 if (value == 0) // +-0
18087 {
18088 *first++ = '0';
18089 // Make it look like a floating-point number (#362, #378)
18090 *first++ = '.';
18091 *first++ = '0';
18092 return first;
18093 }
18094#ifdef __GNUC__
18095#pragma GCC diagnostic pop
18096#endif
18097
18098 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18099
18100 // Compute v = buffer * 10^decimal_exponent.
18101 // The decimal digits are stored in the buffer, which needs to be interpreted
18102 // as an unsigned decimal integer.
18103 // len is the length of the buffer, i.e. the number of decimal digits.
18104 int len = 0;
18105 int decimal_exponent = 0;
18106 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18107
18108 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18109
18110 // Format the buffer like printf("%.*g", prec, value)
18111 constexpr int kMinExp = -4;
18112 // Use digits10 here to increase compatibility with version 2.
18113 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18114
18115 JSON_ASSERT(last - first >= kMaxExp + 2);
18116 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18117 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18118
18119 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18120}
18121
18122} // namespace detail
18124
18125// #include <nlohmann/detail/exceptions.hpp>
18126
18127// #include <nlohmann/detail/macro_scope.hpp>
18128
18129// #include <nlohmann/detail/meta/cpp_future.hpp>
18130
18131// #include <nlohmann/detail/output/binary_writer.hpp>
18132
18133// #include <nlohmann/detail/output/output_adapters.hpp>
18134
18135// #include <nlohmann/detail/string_concat.hpp>
18136
18137// #include <nlohmann/detail/value_t.hpp>
18138
18139
18141namespace detail
18142{
18143
18145// serialization //
18147
18150{
18151 strict,
18152 replace,
18153 ignore
18154};
18155
18156template<typename BasicJsonType>
18158{
18159 using string_t = typename BasicJsonType::string_t;
18160 using number_float_t = typename BasicJsonType::number_float_t;
18161 using number_integer_t = typename BasicJsonType::number_integer_t;
18162 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18163 using binary_char_t = typename BasicJsonType::binary_t::value_type;
18164 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18165 static constexpr std::uint8_t UTF8_REJECT = 1;
18166
18167 public:
18175 : o(std::move(s))
18176 , loc(std::localeconv())
18177 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18178 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18179 , indent_char(ichar)
18181 , error_handler(error_handler_)
18182 {}
18183
18184 // delete because of pointer members
18185 serializer(const serializer&) = delete;
18189 ~serializer() = default;
18190
18213 void dump(const BasicJsonType& val,
18214 const bool pretty_print,
18215 const bool ensure_ascii,
18216 const unsigned int indent_step,
18217 const unsigned int current_indent = 0)
18218 {
18219 switch (val.m_data.m_type)
18220 {
18221 case value_t::object:
18222 {
18223 if (val.m_data.m_value.object->empty())
18224 {
18225 o->write_characters("{}", 2);
18226 return;
18227 }
18228
18229 if (pretty_print)
18230 {
18231 o->write_characters("{\n", 2);
18232
18233 // variable to hold indentation for recursive calls
18234 const auto new_indent = current_indent + indent_step;
18235 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18236 {
18237 indent_string.resize(indent_string.size() * 2, ' ');
18238 }
18239
18240 // first n-1 elements
18241 auto i = val.m_data.m_value.object->cbegin();
18242 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18243 {
18244 o->write_characters(indent_string.c_str(), new_indent);
18245 o->write_character('\"');
18246 dump_escaped(i->first, ensure_ascii);
18247 o->write_characters("\": ", 3);
18248 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18249 o->write_characters(",\n", 2);
18250 }
18251
18252 // last element
18253 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18254 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18255 o->write_characters(indent_string.c_str(), new_indent);
18256 o->write_character('\"');
18257 dump_escaped(i->first, ensure_ascii);
18258 o->write_characters("\": ", 3);
18259 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18260
18261 o->write_character('\n');
18262 o->write_characters(indent_string.c_str(), current_indent);
18263 o->write_character('}');
18264 }
18265 else
18266 {
18267 o->write_character('{');
18268
18269 // first n-1 elements
18270 auto i = val.m_data.m_value.object->cbegin();
18271 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18272 {
18273 o->write_character('\"');
18274 dump_escaped(i->first, ensure_ascii);
18275 o->write_characters("\":", 2);
18276 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18277 o->write_character(',');
18278 }
18279
18280 // last element
18281 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18282 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18283 o->write_character('\"');
18284 dump_escaped(i->first, ensure_ascii);
18285 o->write_characters("\":", 2);
18286 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18287
18288 o->write_character('}');
18289 }
18290
18291 return;
18292 }
18293
18294 case value_t::array:
18295 {
18296 if (val.m_data.m_value.array->empty())
18297 {
18298 o->write_characters("[]", 2);
18299 return;
18300 }
18301
18302 if (pretty_print)
18303 {
18304 o->write_characters("[\n", 2);
18305
18306 // variable to hold indentation for recursive calls
18307 const auto new_indent = current_indent + indent_step;
18308 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18309 {
18310 indent_string.resize(indent_string.size() * 2, ' ');
18311 }
18312
18313 // first n-1 elements
18314 for (auto i = val.m_data.m_value.array->cbegin();
18315 i != val.m_data.m_value.array->cend() - 1; ++i)
18316 {
18317 o->write_characters(indent_string.c_str(), new_indent);
18318 dump(*i, true, ensure_ascii, indent_step, new_indent);
18319 o->write_characters(",\n", 2);
18320 }
18321
18322 // last element
18323 JSON_ASSERT(!val.m_data.m_value.array->empty());
18324 o->write_characters(indent_string.c_str(), new_indent);
18325 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18326
18327 o->write_character('\n');
18328 o->write_characters(indent_string.c_str(), current_indent);
18329 o->write_character(']');
18330 }
18331 else
18332 {
18333 o->write_character('[');
18334
18335 // first n-1 elements
18336 for (auto i = val.m_data.m_value.array->cbegin();
18337 i != val.m_data.m_value.array->cend() - 1; ++i)
18338 {
18339 dump(*i, false, ensure_ascii, indent_step, current_indent);
18340 o->write_character(',');
18341 }
18342
18343 // last element
18344 JSON_ASSERT(!val.m_data.m_value.array->empty());
18345 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
18346
18347 o->write_character(']');
18348 }
18349
18350 return;
18351 }
18352
18353 case value_t::string:
18354 {
18355 o->write_character('\"');
18356 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
18357 o->write_character('\"');
18358 return;
18359 }
18360
18361 case value_t::binary:
18362 {
18363 if (pretty_print)
18364 {
18365 o->write_characters("{\n", 2);
18366
18367 // variable to hold indentation for recursive calls
18368 const auto new_indent = current_indent + indent_step;
18369 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18370 {
18371 indent_string.resize(indent_string.size() * 2, ' ');
18372 }
18373
18374 o->write_characters(indent_string.c_str(), new_indent);
18375
18376 o->write_characters("\"bytes\": [", 10);
18377
18378 if (!val.m_data.m_value.binary->empty())
18379 {
18380 for (auto i = val.m_data.m_value.binary->cbegin();
18381 i != val.m_data.m_value.binary->cend() - 1; ++i)
18382 {
18383 dump_integer(*i);
18384 o->write_characters(", ", 2);
18385 }
18386 dump_integer(val.m_data.m_value.binary->back());
18387 }
18388
18389 o->write_characters("],\n", 3);
18390 o->write_characters(indent_string.c_str(), new_indent);
18391
18392 o->write_characters("\"subtype\": ", 11);
18393 if (val.m_data.m_value.binary->has_subtype())
18394 {
18395 dump_integer(val.m_data.m_value.binary->subtype());
18396 }
18397 else
18398 {
18399 o->write_characters("null", 4);
18400 }
18401 o->write_character('\n');
18402 o->write_characters(indent_string.c_str(), current_indent);
18403 o->write_character('}');
18404 }
18405 else
18406 {
18407 o->write_characters("{\"bytes\":[", 10);
18408
18409 if (!val.m_data.m_value.binary->empty())
18410 {
18411 for (auto i = val.m_data.m_value.binary->cbegin();
18412 i != val.m_data.m_value.binary->cend() - 1; ++i)
18413 {
18414 dump_integer(*i);
18415 o->write_character(',');
18416 }
18417 dump_integer(val.m_data.m_value.binary->back());
18418 }
18419
18420 o->write_characters("],\"subtype\":", 12);
18421 if (val.m_data.m_value.binary->has_subtype())
18422 {
18423 dump_integer(val.m_data.m_value.binary->subtype());
18424 o->write_character('}');
18425 }
18426 else
18427 {
18428 o->write_characters("null}", 5);
18429 }
18430 }
18431 return;
18432 }
18433
18434 case value_t::boolean:
18435 {
18436 if (val.m_data.m_value.boolean)
18437 {
18438 o->write_characters("true", 4);
18439 }
18440 else
18441 {
18442 o->write_characters("false", 5);
18443 }
18444 return;
18445 }
18446
18448 {
18449 dump_integer(val.m_data.m_value.number_integer);
18450 return;
18451 }
18452
18454 {
18455 dump_integer(val.m_data.m_value.number_unsigned);
18456 return;
18457 }
18458
18460 {
18461 dump_float(val.m_data.m_value.number_float);
18462 return;
18463 }
18464
18465 case value_t::discarded:
18466 {
18467 o->write_characters("<discarded>", 11);
18468 return;
18469 }
18470
18471 case value_t::null:
18472 {
18473 o->write_characters("null", 4);
18474 return;
18475 }
18476
18477 default: // LCOV_EXCL_LINE
18478 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18479 }
18480 }
18481
18497 void dump_escaped(const string_t& s, const bool ensure_ascii)
18498 {
18499 std::uint32_t codepoint{};
18500 std::uint8_t state = UTF8_ACCEPT;
18501 std::size_t bytes = 0; // number of bytes written to string_buffer
18502
18503 // number of bytes written at the point of the last valid byte
18505 std::size_t undumped_chars = 0;
18506
18507 for (std::size_t i = 0; i < s.size(); ++i)
18508 {
18509 const auto byte = static_cast<std::uint8_t>(s[i]);
18510
18511 switch (decode(state, codepoint, byte))
18512 {
18513 case UTF8_ACCEPT: // decode found a new code point
18514 {
18515 switch (codepoint)
18516 {
18517 case 0x08: // backspace
18518 {
18519 string_buffer[bytes++] = '\\';
18520 string_buffer[bytes++] = 'b';
18521 break;
18522 }
18523
18524 case 0x09: // horizontal tab
18525 {
18526 string_buffer[bytes++] = '\\';
18527 string_buffer[bytes++] = 't';
18528 break;
18529 }
18530
18531 case 0x0A: // newline
18532 {
18533 string_buffer[bytes++] = '\\';
18534 string_buffer[bytes++] = 'n';
18535 break;
18536 }
18537
18538 case 0x0C: // formfeed
18539 {
18540 string_buffer[bytes++] = '\\';
18541 string_buffer[bytes++] = 'f';
18542 break;
18543 }
18544
18545 case 0x0D: // carriage return
18546 {
18547 string_buffer[bytes++] = '\\';
18548 string_buffer[bytes++] = 'r';
18549 break;
18550 }
18551
18552 case 0x22: // quotation mark
18553 {
18554 string_buffer[bytes++] = '\\';
18555 string_buffer[bytes++] = '\"';
18556 break;
18557 }
18558
18559 case 0x5C: // reverse solidus
18560 {
18561 string_buffer[bytes++] = '\\';
18562 string_buffer[bytes++] = '\\';
18563 break;
18564 }
18565
18566 default:
18567 {
18568 // escape control characters (0x00..0x1F) or, if
18569 // ensure_ascii parameter is used, non-ASCII characters
18570 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
18571 {
18572 if (codepoint <= 0xFFFF)
18573 {
18574 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18575 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
18576 static_cast<std::uint16_t>(codepoint)));
18577 bytes += 6;
18578 }
18579 else
18580 {
18581 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18582 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
18583 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
18584 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
18585 bytes += 12;
18586 }
18587 }
18588 else
18589 {
18590 // copy byte to buffer (all previous bytes
18591 // been copied have in default case above)
18592 string_buffer[bytes++] = s[i];
18593 }
18594 break;
18595 }
18596 }
18597
18598 // write buffer and reset index; there must be 13 bytes
18599 // left, as this is the maximal number of bytes to be
18600 // written ("\uxxxx\uxxxx\0") for one code point
18601 if (string_buffer.size() - bytes < 13)
18602 {
18603 o->write_characters(string_buffer.data(), bytes);
18604 bytes = 0;
18605 }
18606
18607 // remember the byte position of this accept
18609 undumped_chars = 0;
18610 break;
18611 }
18612
18613 case UTF8_REJECT: // decode found invalid UTF-8 byte
18614 {
18615 switch (error_handler)
18616 {
18618 {
18619 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
18620 }
18621
18624 {
18625 // in case we saw this character the first time, we
18626 // would like to read it again, because the byte
18627 // may be OK for itself, but just not OK for the
18628 // previous sequence
18629 if (undumped_chars > 0)
18630 {
18631 --i;
18632 }
18633
18634 // reset length buffer to the last accepted index;
18635 // thus removing/ignoring the invalid characters
18637
18639 {
18640 // add a replacement character
18641 if (ensure_ascii)
18642 {
18643 string_buffer[bytes++] = '\\';
18644 string_buffer[bytes++] = 'u';
18645 string_buffer[bytes++] = 'f';
18646 string_buffer[bytes++] = 'f';
18647 string_buffer[bytes++] = 'f';
18648 string_buffer[bytes++] = 'd';
18649 }
18650 else
18651 {
18655 }
18656
18657 // write buffer and reset index; there must be 13 bytes
18658 // left, as this is the maximal number of bytes to be
18659 // written ("\uxxxx\uxxxx\0") for one code point
18660 if (string_buffer.size() - bytes < 13)
18661 {
18662 o->write_characters(string_buffer.data(), bytes);
18663 bytes = 0;
18664 }
18665
18667 }
18668
18669 undumped_chars = 0;
18670
18671 // continue processing the string
18672 state = UTF8_ACCEPT;
18673 break;
18674 }
18675
18676 default: // LCOV_EXCL_LINE
18677 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18678 }
18679 break;
18680 }
18681
18682 default: // decode found yet incomplete multi-byte code point
18683 {
18684 if (!ensure_ascii)
18685 {
18686 // code point will not be escaped - copy byte to buffer
18687 string_buffer[bytes++] = s[i];
18688 }
18690 break;
18691 }
18692 }
18693 }
18694
18695 // we finished processing the string
18696 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
18697 {
18698 // write buffer
18699 if (bytes > 0)
18700 {
18701 o->write_characters(string_buffer.data(), bytes);
18702 }
18703 }
18704 else
18705 {
18706 // we finish reading, but do not accept: string was incomplete
18707 switch (error_handler)
18708 {
18710 {
18711 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));
18712 }
18713
18715 {
18716 // write all accepted bytes
18717 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18718 break;
18719 }
18720
18722 {
18723 // write all accepted bytes
18724 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18725 // add a replacement character
18726 if (ensure_ascii)
18727 {
18728 o->write_characters("\\ufffd", 6);
18729 }
18730 else
18731 {
18732 o->write_characters("\xEF\xBF\xBD", 3);
18733 }
18734 break;
18735 }
18736
18737 default: // LCOV_EXCL_LINE
18738 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18739 }
18740 }
18741 }
18742
18743 private:
18752 unsigned int count_digits(number_unsigned_t x) noexcept
18753 {
18754 unsigned int n_digits = 1;
18755 for (;;)
18756 {
18757 if (x < 10)
18758 {
18759 return n_digits;
18760 }
18761 if (x < 100)
18762 {
18763 return n_digits + 1;
18764 }
18765 if (x < 1000)
18766 {
18767 return n_digits + 2;
18768 }
18769 if (x < 10000)
18770 {
18771 return n_digits + 3;
18772 }
18773 x = x / 10000u;
18774 n_digits += 4;
18775 }
18776 }
18777
18783 static std::string hex_bytes(std::uint8_t byte)
18784 {
18785 std::string result = "FF";
18786 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
18787 result[0] = nibble_to_hex[byte / 16];
18788 result[1] = nibble_to_hex[byte % 16];
18789 return result;
18790 }
18791
18792 // templates to avoid warnings about useless casts
18793 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
18794 bool is_negative_number(NumberType x)
18795 {
18796 return x < 0;
18797 }
18798
18799 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
18800 bool is_negative_number(NumberType /*unused*/)
18801 {
18802 return false;
18803 }
18804
18814 template < typename NumberType, detail::enable_if_t <
18815 std::is_integral<NumberType>::value ||
18816 std::is_same<NumberType, number_unsigned_t>::value ||
18817 std::is_same<NumberType, number_integer_t>::value ||
18818 std::is_same<NumberType, binary_char_t>::value,
18819 int > = 0 >
18820 void dump_integer(NumberType x)
18821 {
18822 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18823 {
18824 {
18825 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
18826 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
18827 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
18828 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
18829 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
18830 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
18831 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
18832 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
18833 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
18834 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
18835 }
18836 };
18837
18838 // special case for "0"
18839 if (x == 0)
18840 {
18841 o->write_character('0');
18842 return;
18843 }
18844
18845 // use a pointer to fill the buffer
18846 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18847
18848 number_unsigned_t abs_value;
18849
18850 unsigned int n_chars{};
18851
18852 if (is_negative_number(x))
18853 {
18854 *buffer_ptr = '-';
18855 abs_value = remove_sign(static_cast<number_integer_t>(x));
18856
18857 // account one more byte for the minus sign
18858 n_chars = 1 + count_digits(abs_value);
18859 }
18860 else
18861 {
18862 abs_value = static_cast<number_unsigned_t>(x);
18863 n_chars = count_digits(abs_value);
18864 }
18865
18866 // spare 1 byte for '\0'
18867 JSON_ASSERT(n_chars < number_buffer.size() - 1);
18868
18869 // jump to the end to generate the string from backward,
18870 // so we later avoid reversing the result
18871 buffer_ptr += n_chars;
18872
18873 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
18874 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
18875 while (abs_value >= 100)
18876 {
18877 const auto digits_index = static_cast<unsigned>((abs_value % 100));
18878 abs_value /= 100;
18879 *(--buffer_ptr) = digits_to_99[digits_index][1];
18880 *(--buffer_ptr) = digits_to_99[digits_index][0];
18881 }
18882
18883 if (abs_value >= 10)
18884 {
18885 const auto digits_index = static_cast<unsigned>(abs_value);
18886 *(--buffer_ptr) = digits_to_99[digits_index][1];
18887 *(--buffer_ptr) = digits_to_99[digits_index][0];
18888 }
18889 else
18890 {
18891 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
18892 }
18893
18894 o->write_characters(number_buffer.data(), n_chars);
18895 }
18896
18905 void dump_float(number_float_t x)
18906 {
18907 // NaN / inf
18908 if (!std::isfinite(x))
18909 {
18910 o->write_characters("null", 4);
18911 return;
18912 }
18913
18914 // If number_float_t is an IEEE-754 single or double precision number,
18915 // use the Grisu2 algorithm to produce short numbers which are
18916 // guaranteed to round-trip, using strtof and strtod, resp.
18917 //
18918 // NB: The test below works if <long double> == <double>.
18919 static constexpr bool is_ieee_single_or_double
18920 = (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) ||
18921 (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);
18922
18923 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
18924 }
18925
18926 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
18927 {
18928 auto* begin = number_buffer.data();
18929 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
18930
18931 o->write_characters(begin, static_cast<size_t>(end - begin));
18932 }
18933
18934 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
18935 {
18936 // get number of digits for a float -> text -> float round-trip
18937 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
18938
18939 // the actual conversion
18940 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18941 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
18942
18943 // negative value indicates an error
18944 JSON_ASSERT(len > 0);
18945 // check if buffer was large enough
18946 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
18947
18948 // erase thousands separator
18949 if (thousands_sep != '\0')
18950 {
18951 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
18952 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
18953 std::fill(end, number_buffer.end(), '\0');
18954 JSON_ASSERT((end - number_buffer.begin()) <= len);
18955 len = (end - number_buffer.begin());
18956 }
18957
18958 // convert decimal point to '.'
18959 if (decimal_point != '\0' && decimal_point != '.')
18960 {
18961 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
18962 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
18963 if (dec_pos != number_buffer.end())
18964 {
18965 *dec_pos = '.';
18966 }
18967 }
18968
18969 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
18970
18971 // determine if we need to append ".0"
18972 const bool value_is_int_like =
18973 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
18974 [](char c)
18975 {
18976 return c == '.' || c == 'e';
18977 });
18978
18979 if (value_is_int_like)
18980 {
18981 o->write_characters(".0", 2);
18982 }
18983 }
18984
19006 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
19007 {
19008 static const std::array<std::uint8_t, 400> utf8d =
19009 {
19010 {
19011 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
19012 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
19013 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
19014 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
19015 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
19016 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
19017 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
19018 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
19019 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
19020 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
19021 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
19022 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
19023 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
19024 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
19025 }
19026 };
19027
19028 JSON_ASSERT(byte < utf8d.size());
19029 const std::uint8_t type = utf8d[byte];
19030
19031 codep = (state != UTF8_ACCEPT)
19032 ? (byte & 0x3fu) | (codep << 6u)
19033 : (0xFFu >> type) & (byte);
19034
19035 const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
19036 JSON_ASSERT(index < utf8d.size());
19037 state = utf8d[index];
19038 return state;
19039 }
19040
19041 /*
19042 * Overload to make the compiler happy while it is instantiating
19043 * dump_integer for number_unsigned_t.
19044 * Must never be called.
19045 */
19046 number_unsigned_t remove_sign(number_unsigned_t x)
19047 {
19048 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19049 return x; // LCOV_EXCL_LINE
19050 }
19051
19052 /*
19053 * Helper function for dump_integer
19054 *
19055 * This function takes a negative signed integer and returns its absolute
19056 * value as unsigned integer. The plus/minus shuffling is necessary as we can
19057 * not directly remove the sign of an arbitrary signed integer as the
19058 * absolute values of INT_MIN and INT_MAX are usually not the same. See
19059 * #1708 for details.
19060 */
19061 number_unsigned_t remove_sign(number_integer_t x) noexcept
19062 {
19063 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
19064 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
19065 }
19066
19067 private:
19069 output_adapter_t<char> o = nullptr;
19070
19072 std::array<char, 64> number_buffer{{}};
19073
19075 const std::lconv* loc = nullptr;
19077 const char thousands_sep = '\0';
19079 const char decimal_point = '\0';
19080
19082 std::array<char, 512> string_buffer{{}};
19083
19085 const char indent_char;
19088
19091};
19092
19093} // namespace detail
19095
19096// #include <nlohmann/detail/value_t.hpp>
19097
19098// #include <nlohmann/json_fwd.hpp>
19099
19100// #include <nlohmann/ordered_map.hpp>
19101// __ _____ _____ _____
19102// __| | __| | | | JSON for Modern C++
19103// | | |__ | | | | | | version 3.11.3
19104// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19105//
19106// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
19107// SPDX-License-Identifier: MIT
19108
19109
19110
19111#include <functional> // equal_to, less
19112#include <initializer_list> // initializer_list
19113#include <iterator> // input_iterator_tag, iterator_traits
19114#include <memory> // allocator
19115#include <stdexcept> // for out_of_range
19116#include <type_traits> // enable_if, is_convertible
19117#include <utility> // pair
19118#include <vector> // vector
19119
19120// #include <nlohmann/detail/macro_scope.hpp>
19121
19122// #include <nlohmann/detail/meta/type_traits.hpp>
19123
19124
19126
19129template <class Key, class T, class IgnoredLess = std::less<Key>,
19130 class Allocator = std::allocator<std::pair<const Key, T>>>
19131 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19132{
19133 using key_type = Key;
19134 using mapped_type = T;
19135 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19136 using iterator = typename Container::iterator;
19137 using const_iterator = typename Container::const_iterator;
19138 using size_type = typename Container::size_type;
19139 using value_type = typename Container::value_type;
19140#ifdef JSON_HAS_CPP_14
19141 using key_compare = std::equal_to<>;
19142#else
19143 using key_compare = std::equal_to<Key>;
19144#endif
19145
19146 // Explicit constructors instead of `using Container::Container`
19147 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19148 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19149 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19150 template <class It>
19151 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19152 : Container{first, last, alloc} {}
19153 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19154 : Container{init, alloc} {}
19155
19156 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19157 {
19158 for (auto it = this->begin(); it != this->end(); ++it)
19159 {
19160 if (m_compare(it->first, key))
19161 {
19162 return {it, false};
19163 }
19164 }
19165 Container::emplace_back(key, std::forward<T>(t));
19166 return {std::prev(this->end()), true};
19167 }
19168
19169 template<class KeyType, detail::enable_if_t<
19171 std::pair<iterator, bool> emplace(KeyType && key, T && t)
19172 {
19173 for (auto it = this->begin(); it != this->end(); ++it)
19174 {
19175 if (m_compare(it->first, key))
19176 {
19177 return {it, false};
19178 }
19179 }
19180 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19181 return {std::prev(this->end()), true};
19182 }
19183
19184 T& operator[](const key_type& key)
19185 {
19186 return emplace(key, T{}).first->second;
19187 }
19188
19189 template<class KeyType, detail::enable_if_t<
19191 T & operator[](KeyType && key)
19192 {
19193 return emplace(std::forward<KeyType>(key), T{}).first->second;
19194 }
19195
19196 const T& operator[](const key_type& key) const
19197 {
19198 return at(key);
19199 }
19200
19201 template<class KeyType, detail::enable_if_t<
19203 const T & operator[](KeyType && key) const
19204 {
19205 return at(std::forward<KeyType>(key));
19206 }
19207
19208 T& at(const key_type& key)
19209 {
19210 for (auto it = this->begin(); it != this->end(); ++it)
19211 {
19212 if (m_compare(it->first, key))
19213 {
19214 return it->second;
19215 }
19216 }
19217
19218 JSON_THROW(std::out_of_range("key not found"));
19219 }
19220
19221 template<class KeyType, detail::enable_if_t<
19223 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19224 {
19225 for (auto it = this->begin(); it != this->end(); ++it)
19226 {
19227 if (m_compare(it->first, key))
19228 {
19229 return it->second;
19230 }
19231 }
19232
19233 JSON_THROW(std::out_of_range("key not found"));
19234 }
19235
19236 const T& at(const key_type& key) const
19237 {
19238 for (auto it = this->begin(); it != this->end(); ++it)
19239 {
19240 if (m_compare(it->first, key))
19241 {
19242 return it->second;
19243 }
19244 }
19245
19246 JSON_THROW(std::out_of_range("key not found"));
19247 }
19248
19249 template<class KeyType, detail::enable_if_t<
19251 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19252 {
19253 for (auto it = this->begin(); it != this->end(); ++it)
19254 {
19255 if (m_compare(it->first, key))
19256 {
19257 return it->second;
19258 }
19259 }
19260
19261 JSON_THROW(std::out_of_range("key not found"));
19262 }
19263
19265 {
19266 for (auto it = this->begin(); it != this->end(); ++it)
19267 {
19268 if (m_compare(it->first, key))
19269 {
19270 // Since we cannot move const Keys, re-construct them in place
19271 for (auto next = it; ++next != this->end(); ++it)
19272 {
19273 it->~value_type(); // Destroy but keep allocation
19274 new (&*it) value_type{std::move(*next)};
19275 }
19276 Container::pop_back();
19277 return 1;
19278 }
19279 }
19280 return 0;
19281 }
19282
19283 template<class KeyType, detail::enable_if_t<
19285 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19286 {
19287 for (auto it = this->begin(); it != this->end(); ++it)
19288 {
19289 if (m_compare(it->first, key))
19290 {
19291 // Since we cannot move const Keys, re-construct them in place
19292 for (auto next = it; ++next != this->end(); ++it)
19293 {
19294 it->~value_type(); // Destroy but keep allocation
19295 new (&*it) value_type{std::move(*next)};
19296 }
19297 Container::pop_back();
19298 return 1;
19299 }
19300 }
19301 return 0;
19302 }
19303
19305 {
19306 return erase(pos, std::next(pos));
19307 }
19308
19310 {
19311 if (first == last)
19312 {
19313 return first;
19314 }
19315
19316 const auto elements_affected = std::distance(first, last);
19317 const auto offset = std::distance(Container::begin(), first);
19318
19319 // This is the start situation. We need to delete elements_affected
19320 // elements (3 in this example: e, f, g), and need to return an
19321 // iterator past the last deleted element (h in this example).
19322 // Note that offset is the distance from the start of the vector
19323 // to first. We will need this later.
19324
19325 // [ a, b, c, d, e, f, g, h, i, j ]
19326 // ^ ^
19327 // first last
19328
19329 // Since we cannot move const Keys, we re-construct them in place.
19330 // We start at first and re-construct (viz. copy) the elements from
19331 // the back of the vector. Example for first iteration:
19332
19333 // ,--------.
19334 // v | destroy e and re-construct with h
19335 // [ a, b, c, d, e, f, g, h, i, j ]
19336 // ^ ^
19337 // it it + elements_affected
19338
19339 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19340 {
19341 it->~value_type(); // destroy but keep allocation
19342 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
19343 }
19344
19345 // [ a, b, c, d, h, i, j, h, i, j ]
19346 // ^ ^
19347 // first last
19348
19349 // remove the unneeded elements at the end of the vector
19350 Container::resize(this->size() - static_cast<size_type>(elements_affected));
19351
19352 // [ a, b, c, d, h, i, j ]
19353 // ^ ^
19354 // first last
19355
19356 // first is now pointing past the last deleted element, but we cannot
19357 // use this iterator, because it may have been invalidated by the
19358 // resize call. Instead, we can return begin() + offset.
19359 return Container::begin() + offset;
19360 }
19361
19362 size_type count(const key_type& key) const
19363 {
19364 for (auto it = this->begin(); it != this->end(); ++it)
19365 {
19366 if (m_compare(it->first, key))
19367 {
19368 return 1;
19369 }
19370 }
19371 return 0;
19372 }
19373
19374 template<class KeyType, detail::enable_if_t<
19376 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19377 {
19378 for (auto it = this->begin(); it != this->end(); ++it)
19379 {
19380 if (m_compare(it->first, key))
19381 {
19382 return 1;
19383 }
19384 }
19385 return 0;
19386 }
19387
19389 {
19390 for (auto it = this->begin(); it != this->end(); ++it)
19391 {
19392 if (m_compare(it->first, key))
19393 {
19394 return it;
19395 }
19396 }
19397 return Container::end();
19398 }
19399
19400 template<class KeyType, detail::enable_if_t<
19402 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19403 {
19404 for (auto it = this->begin(); it != this->end(); ++it)
19405 {
19406 if (m_compare(it->first, key))
19407 {
19408 return it;
19409 }
19410 }
19411 return Container::end();
19412 }
19413
19414 const_iterator find(const key_type& key) const
19415 {
19416 for (auto it = this->begin(); it != this->end(); ++it)
19417 {
19418 if (m_compare(it->first, key))
19419 {
19420 return it;
19421 }
19422 }
19423 return Container::end();
19424 }
19425
19426 std::pair<iterator, bool> insert( value_type&& value )
19427 {
19428 return emplace(value.first, std::move(value.second));
19429 }
19430
19431 std::pair<iterator, bool> insert( const value_type& value )
19432 {
19433 for (auto it = this->begin(); it != this->end(); ++it)
19434 {
19435 if (m_compare(it->first, value.first))
19436 {
19437 return {it, false};
19438 }
19439 }
19440 Container::push_back(value);
19441 return {--this->end(), true};
19442 }
19443
19444 template<typename InputIt>
19445 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
19446 std::input_iterator_tag>::value>::type;
19447
19448 template<typename InputIt, typename = require_input_iter<InputIt>>
19449 void insert(InputIt first, InputIt last)
19450 {
19451 for (auto it = first; it != last; ++it)
19452 {
19453 insert(*it);
19454 }
19455 }
19456
19457private:
19459};
19460
19462
19463
19464#if defined(JSON_HAS_CPP_17)
19465 #if JSON_HAS_STATIC_RTTI
19466 #include <any>
19467 #endif
19468 #include <string_view>
19469#endif
19470
19477
19497class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
19498 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
19499{
19500 private:
19501 template<detail::value_t> friend struct detail::external_constructor;
19502
19503 template<typename>
19504 friend class ::nlohmann::json_pointer;
19505 // can be restored when json_pointer backwards compatibility is removed
19506 // friend ::nlohmann::json_pointer<StringType>;
19507
19508 template<typename BasicJsonType, typename InputType>
19509 friend class ::nlohmann::detail::parser;
19510 friend ::nlohmann::detail::serializer<basic_json>;
19511 template<typename BasicJsonType>
19512 friend class ::nlohmann::detail::iter_impl;
19513 template<typename BasicJsonType, typename CharType>
19514 friend class ::nlohmann::detail::binary_writer;
19515 template<typename BasicJsonType, typename InputType, typename SAX>
19516 friend class ::nlohmann::detail::binary_reader;
19517 template<typename BasicJsonType>
19518 friend class ::nlohmann::detail::json_sax_dom_parser;
19519 template<typename BasicJsonType>
19520 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
19521 friend class ::nlohmann::detail::exception;
19522
19524 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
19525 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
19526
19528 // convenience aliases for types residing in namespace detail;
19529 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
19530
19531 template<typename InputAdapterType>
19532 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
19533 InputAdapterType adapter,
19535 const bool allow_exceptions = true,
19536 const bool ignore_comments = false
19537 )
19538 {
19539 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
19540 std::move(cb), allow_exceptions, ignore_comments);
19541 }
19542
19543 private:
19544 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
19545 template<typename BasicJsonType>
19546 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
19547 template<typename BasicJsonType>
19548 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
19549 template<typename Iterator>
19550 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
19551 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
19552
19553 template<typename CharType>
19554 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
19555
19556 template<typename InputType>
19557 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
19558 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
19559
19561 using serializer = ::nlohmann::detail::serializer<basic_json>;
19562
19563 public:
19566 using json_pointer = ::nlohmann::json_pointer<StringType>;
19567 template<typename T, typename SFINAE>
19568 using json_serializer = JSONSerializer<T, SFINAE>;
19574 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
19575
19579
19581 // exceptions //
19583
19587
19594
19596
19598 // container types //
19600
19605
19608
19613
19615 using difference_type = std::ptrdiff_t;
19617 using size_type = std::size_t;
19618
19620 using allocator_type = AllocatorType<basic_json>;
19621
19623 using pointer = typename std::allocator_traits<allocator_type>::pointer;
19625 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
19626
19628 using iterator = iter_impl<basic_json>;
19630 using const_iterator = iter_impl<const basic_json>;
19632 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
19634 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
19635
19637
19641 {
19642 return allocator_type();
19643 }
19644
19649 {
19650 basic_json result;
19651
19652 result["copyright"] = "(C) 2013-2023 Niels Lohmann";
19653 result["name"] = "JSON for Modern C++";
19654 result["url"] = "https://github.com/nlohmann/json";
19655 result["version"]["string"] =
19656 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
19657 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
19658 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19659 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
19660 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
19661 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
19662
19663#ifdef _WIN32
19664 result["platform"] = "win32";
19665#elif defined __linux__
19666 result["platform"] = "linux";
19667#elif defined __APPLE__
19668 result["platform"] = "apple";
19669#elif defined __unix__
19670 result["platform"] = "unix";
19671#else
19672 result["platform"] = "unknown";
19673#endif
19674
19675#if defined(__ICC) || defined(__INTEL_COMPILER)
19676 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
19677#elif defined(__clang__)
19678 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
19679#elif defined(__GNUC__) || defined(__GNUG__)
19680 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
19681 std::to_string(__GNUC__), '.',
19682 std::to_string(__GNUC_MINOR__), '.',
19683 std::to_string(__GNUC_PATCHLEVEL__))
19684 }
19685 };
19686#elif defined(__HP_cc) || defined(__HP_aCC)
19687 result["compiler"] = "hp"
19688#elif defined(__IBMCPP__)
19689 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
19690#elif defined(_MSC_VER)
19691 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
19692#elif defined(__PGI)
19693 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
19694#elif defined(__SUNPRO_CC)
19695 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
19696#else
19697 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
19698#endif
19699
19700#if defined(_MSVC_LANG)
19701 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
19702#elif defined(__cplusplus)
19703 result["compiler"]["c++"] = std::to_string(__cplusplus);
19704#else
19705 result["compiler"]["c++"] = "unknown";
19706#endif
19707 return result;
19708 }
19709
19711 // JSON value data types //
19713
19718
19723#if defined(JSON_HAS_CPP_14)
19724 // use of transparent comparator avoids unnecessary repeated construction of temporaries
19725 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
19726 using default_object_comparator_t = std::less<>;
19727#else
19728 using default_object_comparator_t = std::less<StringType>;
19729#endif
19730
19733 using object_t = ObjectType<StringType,
19734 basic_json,
19736 AllocatorType<std::pair<const StringType,
19737 basic_json>>>;
19738
19741 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19742
19745 using string_t = StringType;
19746
19749 using boolean_t = BooleanType;
19750
19753 using number_integer_t = NumberIntegerType;
19754
19757 using number_unsigned_t = NumberUnsignedType;
19758
19761 using number_float_t = NumberFloatType;
19762
19765 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19766
19770
19772
19773 private:
19774
19776 template<typename T, typename... Args>
19778 static T* create(Args&& ... args)
19779 {
19780 AllocatorType<T> alloc;
19781 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19782
19783 auto deleter = [&](T * obj)
19784 {
19785 AllocatorTraits::deallocate(alloc, obj, 1);
19786 };
19787 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19788 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19789 JSON_ASSERT(obj != nullptr);
19790 return obj.release();
19791 }
19792
19794 // JSON value storage //
19796
19823 union json_value
19824 {
19828 array_t* array;
19830 string_t* string;
19832 binary_t* binary;
19834 boolean_t boolean;
19836 number_integer_t number_integer;
19838 number_unsigned_t number_unsigned;
19840 number_float_t number_float;
19841
19843 json_value() = default;
19845 json_value(boolean_t v) noexcept : boolean(v) {}
19847 json_value(number_integer_t v) noexcept : number_integer(v) {}
19849 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19851 json_value(number_float_t v) noexcept : number_float(v) {}
19853 json_value(value_t t)
19854 {
19855 switch (t)
19856 {
19857 case value_t::object:
19858 {
19859 object = create<object_t>();
19860 break;
19861 }
19862
19863 case value_t::array:
19864 {
19865 array = create<array_t>();
19866 break;
19867 }
19868
19869 case value_t::string:
19870 {
19871 string = create<string_t>("");
19872 break;
19873 }
19874
19875 case value_t::binary:
19876 {
19877 binary = create<binary_t>();
19878 break;
19879 }
19880
19881 case value_t::boolean:
19882 {
19883 boolean = static_cast<boolean_t>(false);
19884 break;
19885 }
19886
19887 case value_t::number_integer:
19888 {
19889 number_integer = static_cast<number_integer_t>(0);
19890 break;
19891 }
19892
19893 case value_t::number_unsigned:
19894 {
19895 number_unsigned = static_cast<number_unsigned_t>(0);
19896 break;
19897 }
19898
19899 case value_t::number_float:
19900 {
19901 number_float = static_cast<number_float_t>(0.0);
19902 break;
19903 }
19904
19905 case value_t::null:
19906 {
19907 object = nullptr; // silence warning, see #821
19908 break;
19909 }
19910
19911 case value_t::discarded:
19912 default:
19913 {
19914 object = nullptr; // silence warning, see #821
19915 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
19916 {
19917 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE
19918 }
19919 break;
19920 }
19921 }
19922 }
19923
19925 json_value(const string_t& value) : string(create<string_t>(value)) {}
19926
19928 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
19929
19931 json_value(const object_t& value) : object(create<object_t>(value)) {}
19932
19934 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
19935
19937 json_value(const array_t& value) : array(create<array_t>(value)) {}
19938
19940 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
19941
19943 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
19944
19946 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
19947
19949 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
19950
19952 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
19953
19954 void destroy(value_t t)
19955 {
19956 if (
19957 (t == value_t::object && object == nullptr) ||
19958 (t == value_t::array && array == nullptr) ||
19959 (t == value_t::string && string == nullptr) ||
19960 (t == value_t::binary && binary == nullptr)
19961 )
19962 {
19963 //not initialized (e.g. due to exception in the ctor)
19964 return;
19965 }
19966 if (t == value_t::array || t == value_t::object)
19967 {
19968 // flatten the current json_value to a heap-allocated stack
19969 std::vector<basic_json> stack;
19970
19971 // move the top-level items to stack
19972 if (t == value_t::array)
19973 {
19974 stack.reserve(array->size());
19975 std::move(array->begin(), array->end(), std::back_inserter(stack));
19976 }
19977 else
19978 {
19979 stack.reserve(object->size());
19980 for (auto&& it : *object)
19981 {
19982 stack.push_back(std::move(it.second));
19983 }
19984 }
19985
19986 while (!stack.empty())
19987 {
19988 // move the last item to local variable to be processed
19989 basic_json current_item(std::move(stack.back()));
19990 stack.pop_back();
19991
19992 // if current_item is array/object, move
19993 // its children to the stack to be processed later
19994 if (current_item.is_array())
19995 {
19996 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
19997
19998 current_item.m_data.m_value.array->clear();
19999 }
20000 else if (current_item.is_object())
20001 {
20002 for (auto&& it : *current_item.m_data.m_value.object)
20003 {
20004 stack.push_back(std::move(it.second));
20005 }
20006
20007 current_item.m_data.m_value.object->clear();
20008 }
20009
20010 // it's now safe that current_item get destructed
20011 // since it doesn't have any children
20012 }
20013 }
20014
20015 switch (t)
20016 {
20017 case value_t::object:
20018 {
20019 AllocatorType<object_t> alloc;
20020 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
20021 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
20022 break;
20023 }
20024
20025 case value_t::array:
20026 {
20027 AllocatorType<array_t> alloc;
20028 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
20029 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
20030 break;
20031 }
20032
20033 case value_t::string:
20034 {
20035 AllocatorType<string_t> alloc;
20036 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
20037 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
20038 break;
20039 }
20040
20041 case value_t::binary:
20042 {
20043 AllocatorType<binary_t> alloc;
20044 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
20045 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
20046 break;
20047 }
20048
20049 case value_t::null:
20050 case value_t::boolean:
20051 case value_t::number_integer:
20052 case value_t::number_unsigned:
20053 case value_t::number_float:
20054 case value_t::discarded:
20055 default:
20056 {
20057 break;
20058 }
20059 }
20060 }
20061 };
20062
20063 private:
20082 void assert_invariant(bool check_parents = true) const noexcept
20083 {
20084 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20085 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20086 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20087 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20088
20089#if JSON_DIAGNOSTICS
20090 JSON_TRY
20091 {
20092 // cppcheck-suppress assertWithSideEffect
20093 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20094 {
20095 return j.m_parent == this;
20096 }));
20097 }
20098 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20099#endif
20100 static_cast<void>(check_parents);
20101 }
20102
20103 void set_parents()
20104 {
20105#if JSON_DIAGNOSTICS
20106 switch (m_data.m_type)
20107 {
20108 case value_t::array:
20109 {
20110 for (auto& element : *m_data.m_value.array)
20111 {
20112 element.m_parent = this;
20113 }
20114 break;
20115 }
20116
20117 case value_t::object:
20118 {
20119 for (auto& element : *m_data.m_value.object)
20120 {
20121 element.second.m_parent = this;
20122 }
20123 break;
20124 }
20125
20126 case value_t::null:
20127 case value_t::string:
20128 case value_t::boolean:
20129 case value_t::number_integer:
20130 case value_t::number_unsigned:
20131 case value_t::number_float:
20132 case value_t::binary:
20133 case value_t::discarded:
20134 default:
20135 break;
20136 }
20137#endif
20138 }
20139
20140 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20141 {
20142#if JSON_DIAGNOSTICS
20143 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20144 {
20145 (it + i)->m_parent = this;
20146 }
20147#else
20148 static_cast<void>(count_set_parents);
20149#endif
20150 return it;
20151 }
20152
20153 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
20154 {
20155#if JSON_DIAGNOSTICS
20156 if (old_capacity != static_cast<std::size_t>(-1))
20157 {
20158 // see https://github.com/nlohmann/json/issues/2838
20159 JSON_ASSERT(type() == value_t::array);
20160 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20161 {
20162 // capacity has changed: update all parents
20163 set_parents();
20164 return j;
20165 }
20166 }
20167
20168 // ordered_json uses a vector internally, so pointers could have
20169 // been invalidated; see https://github.com/nlohmann/json/issues/2962
20170#ifdef JSON_HEDLEY_MSVC_VERSION
20171#pragma warning(push )
20172#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20173#endif
20175 {
20176 set_parents();
20177 return j;
20178 }
20179#ifdef JSON_HEDLEY_MSVC_VERSION
20180#pragma warning( pop )
20181#endif
20182
20183 j.m_parent = this;
20184#else
20185 static_cast<void>(j);
20186 static_cast<void>(old_capacity);
20187#endif
20188 return j;
20189 }
20190
20191 public:
20193 // JSON parser callback //
20195
20199
20203
20205 // constructors //
20207
20212
20216 : m_data(v)
20217 {
20218 assert_invariant();
20219 }
20220
20223 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20224 : basic_json(value_t::null)
20225 {
20226 assert_invariant();
20227 }
20228
20231 template < typename CompatibleType,
20235 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20236 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20237 std::forward<CompatibleType>(val))))
20238 {
20239 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20240 set_parents();
20241 assert_invariant();
20242 }
20243
20246 template < typename BasicJsonType,
20248 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20249 basic_json(const BasicJsonType& val)
20250 {
20251 using other_boolean_t = typename BasicJsonType::boolean_t;
20252 using other_number_float_t = typename BasicJsonType::number_float_t;
20253 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20254 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20255 using other_string_t = typename BasicJsonType::string_t;
20256 using other_object_t = typename BasicJsonType::object_t;
20257 using other_array_t = typename BasicJsonType::array_t;
20258 using other_binary_t = typename BasicJsonType::binary_t;
20259
20260 switch (val.type())
20261 {
20262 case value_t::boolean:
20263 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20264 break;
20265 case value_t::number_float:
20266 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20267 break;
20268 case value_t::number_integer:
20269 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20270 break;
20271 case value_t::number_unsigned:
20272 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20273 break;
20274 case value_t::string:
20275 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20276 break;
20277 case value_t::object:
20278 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20279 break;
20280 case value_t::array:
20281 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20282 break;
20283 case value_t::binary:
20284 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20285 break;
20286 case value_t::null:
20287 *this = nullptr;
20288 break;
20289 case value_t::discarded:
20290 m_data.m_type = value_t::discarded;
20291 break;
20292 default: // LCOV_EXCL_LINE
20293 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20294 }
20295 JSON_ASSERT(m_data.m_type == val.type());
20296 set_parents();
20297 assert_invariant();
20298 }
20299
20303 bool type_deduction = true,
20304 value_t manual_type = value_t::array)
20305 {
20306 // check if each element is an array with two elements whose first
20307 // element is a string
20308 bool is_an_object = std::all_of(init.begin(), init.end(),
20309 [](const detail::json_ref<basic_json>& element_ref)
20310 {
20311 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
20312 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
20313 // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
20314 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
20315 });
20316
20317 // adjust type if type deduction is not wanted
20318 if (!type_deduction)
20319 {
20320 // if array is wanted, do not create an object though possible
20321 if (manual_type == value_t::array)
20322 {
20323 is_an_object = false;
20324 }
20325
20326 // if object is wanted but impossible, throw an exception
20327 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20328 {
20329 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
20330 }
20331 }
20332
20333 if (is_an_object)
20334 {
20335 // the initializer list is a list of pairs -> create object
20336 m_data.m_type = value_t::object;
20337 m_data.m_value = value_t::object;
20338
20339 for (auto& element_ref : init)
20340 {
20341 auto element = element_ref.moved_or_copied();
20342 m_data.m_value.object->emplace(
20343 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
20344 std::move((*element.m_data.m_value.array)[1]));
20345 }
20346 }
20347 else
20348 {
20349 // the initializer list describes an array -> create array
20350 m_data.m_type = value_t::array;
20351 m_data.m_value.array = create<array_t>(init.begin(), init.end());
20352 }
20353
20354 set_parents();
20355 assert_invariant();
20356 }
20357
20361 static basic_json binary(const typename binary_t::container_type& init)
20362 {
20363 auto res = basic_json();
20364 res.m_data.m_type = value_t::binary;
20365 res.m_data.m_value = init;
20366 return res;
20367 }
20368
20372 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
20373 {
20374 auto res = basic_json();
20375 res.m_data.m_type = value_t::binary;
20376 res.m_data.m_value = binary_t(init, subtype);
20377 return res;
20378 }
20379
20383 static basic_json binary(typename binary_t::container_type&& init)
20384 {
20385 auto res = basic_json();
20386 res.m_data.m_type = value_t::binary;
20387 res.m_data.m_value = std::move(init);
20388 return res;
20389 }
20390
20394 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
20395 {
20396 auto res = basic_json();
20397 res.m_data.m_type = value_t::binary;
20398 res.m_data.m_value = binary_t(std::move(init), subtype);
20399 return res;
20400 }
20401
20406 {
20407 return basic_json(init, false, value_t::array);
20408 }
20409
20414 {
20415 return basic_json(init, false, value_t::object);
20416 }
20417
20421 m_data{cnt, val}
20422 {
20423 set_parents();
20424 assert_invariant();
20425 }
20426
20429 template < class InputIT, typename std::enable_if <
20430 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
20431 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
20432 basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
20433 {
20434 JSON_ASSERT(first.m_object != nullptr);
20435 JSON_ASSERT(last.m_object != nullptr);
20436
20437 // make sure iterator fits the current value
20438 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20439 {
20440 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
20441 }
20442
20443 // copy type from first iterator
20444 m_data.m_type = first.m_object->m_data.m_type;
20445
20446 // check if iterator range is complete for primitive values
20447 switch (m_data.m_type)
20448 {
20449 case value_t::boolean:
20450 case value_t::number_float:
20451 case value_t::number_integer:
20452 case value_t::number_unsigned:
20453 case value_t::string:
20454 {
20455 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
20456 || !last.m_it.primitive_iterator.is_end()))
20457 {
20458 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
20459 }
20460 break;
20461 }
20462
20463 case value_t::null:
20464 case value_t::object:
20465 case value_t::array:
20466 case value_t::binary:
20467 case value_t::discarded:
20468 default:
20469 break;
20470 }
20471
20472 switch (m_data.m_type)
20473 {
20474 case value_t::number_integer:
20475 {
20476 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
20477 break;
20478 }
20479
20480 case value_t::number_unsigned:
20481 {
20482 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
20483 break;
20484 }
20485
20486 case value_t::number_float:
20487 {
20488 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
20489 break;
20490 }
20491
20492 case value_t::boolean:
20493 {
20494 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
20495 break;
20496 }
20497
20498 case value_t::string:
20499 {
20500 m_data.m_value = *first.m_object->m_data.m_value.string;
20501 break;
20502 }
20503
20504 case value_t::object:
20505 {
20506 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
20507 last.m_it.object_iterator);
20508 break;
20509 }
20510
20511 case value_t::array:
20512 {
20513 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
20514 last.m_it.array_iterator);
20515 break;
20516 }
20517
20518 case value_t::binary:
20519 {
20520 m_data.m_value = *first.m_object->m_data.m_value.binary;
20521 break;
20522 }
20523
20524 case value_t::null:
20525 case value_t::discarded:
20526 default:
20527 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
20528 }
20529
20530 set_parents();
20531 assert_invariant();
20532 }
20533
20535 // other constructors and destructor //
20537
20538 template<typename JsonRef,
20540 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
20541 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
20542
20546 : json_base_class_t(other)
20547 {
20548 m_data.m_type = other.m_data.m_type;
20549 // check of passed value is valid
20550 other.assert_invariant();
20551
20552 switch (m_data.m_type)
20553 {
20554 case value_t::object:
20555 {
20556 m_data.m_value = *other.m_data.m_value.object;
20557 break;
20558 }
20559
20560 case value_t::array:
20561 {
20562 m_data.m_value = *other.m_data.m_value.array;
20563 break;
20564 }
20565
20566 case value_t::string:
20567 {
20568 m_data.m_value = *other.m_data.m_value.string;
20569 break;
20570 }
20571
20572 case value_t::boolean:
20573 {
20574 m_data.m_value = other.m_data.m_value.boolean;
20575 break;
20576 }
20577
20578 case value_t::number_integer:
20579 {
20580 m_data.m_value = other.m_data.m_value.number_integer;
20581 break;
20582 }
20583
20584 case value_t::number_unsigned:
20585 {
20586 m_data.m_value = other.m_data.m_value.number_unsigned;
20587 break;
20588 }
20589
20590 case value_t::number_float:
20591 {
20592 m_data.m_value = other.m_data.m_value.number_float;
20593 break;
20594 }
20595
20596 case value_t::binary:
20597 {
20598 m_data.m_value = *other.m_data.m_value.binary;
20599 break;
20600 }
20601
20602 case value_t::null:
20603 case value_t::discarded:
20604 default:
20605 break;
20606 }
20607
20608 set_parents();
20609 assert_invariant();
20610 }
20611
20614 basic_json(basic_json&& other) noexcept
20615 : json_base_class_t(std::forward<json_base_class_t>(other)),
20616 m_data(std::move(other.m_data))
20617 {
20618 // check that passed value is valid
20619 other.assert_invariant(false);
20620
20621 // invalidate payload
20622 other.m_data.m_type = value_t::null;
20623 other.m_data.m_value = {};
20624
20625 set_parents();
20626 assert_invariant();
20627 }
20628
20632 std::is_nothrow_move_constructible<value_t>::value&&
20633 std::is_nothrow_move_assignable<value_t>::value&&
20634 std::is_nothrow_move_constructible<json_value>::value&&
20635 std::is_nothrow_move_assignable<json_value>::value&&
20636 std::is_nothrow_move_assignable<json_base_class_t>::value
20637 )
20638 {
20639 // check that passed value is valid
20640 other.assert_invariant();
20641
20642 using std::swap;
20643 swap(m_data.m_type, other.m_data.m_type);
20644 swap(m_data.m_value, other.m_data.m_value);
20645 json_base_class_t::operator=(std::move(other));
20646
20647 set_parents();
20648 assert_invariant();
20649 return *this;
20650 }
20651
20654 ~basic_json() noexcept
20655 {
20656 assert_invariant(false);
20657 }
20658
20660
20661 public:
20663 // object inspection //
20665
20669
20672 string_t dump(const int indent = -1,
20673 const char indent_char = ' ',
20674 const bool ensure_ascii = false,
20675 const error_handler_t error_handler = error_handler_t::strict) const
20676 {
20677 string_t result;
20678 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
20679
20680 if (indent >= 0)
20681 {
20682 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
20683 }
20684 else
20685 {
20686 s.dump(*this, false, ensure_ascii, 0);
20687 }
20688
20689 return result;
20690 }
20691
20694 constexpr value_t type() const noexcept
20695 {
20696 return m_data.m_type;
20697 }
20698
20701 constexpr bool is_primitive() const noexcept
20702 {
20703 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20704 }
20705
20708 constexpr bool is_structured() const noexcept
20709 {
20710 return is_array() || is_object();
20711 }
20712
20715 constexpr bool is_null() const noexcept
20716 {
20717 return m_data.m_type == value_t::null;
20718 }
20719
20722 constexpr bool is_boolean() const noexcept
20723 {
20724 return m_data.m_type == value_t::boolean;
20725 }
20726
20729 constexpr bool is_number() const noexcept
20730 {
20731 return is_number_integer() || is_number_float();
20732 }
20733
20736 constexpr bool is_number_integer() const noexcept
20737 {
20738 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
20739 }
20740
20743 constexpr bool is_number_unsigned() const noexcept
20744 {
20745 return m_data.m_type == value_t::number_unsigned;
20746 }
20747
20750 constexpr bool is_number_float() const noexcept
20751 {
20752 return m_data.m_type == value_t::number_float;
20753 }
20754
20757 constexpr bool is_object() const noexcept
20758 {
20759 return m_data.m_type == value_t::object;
20760 }
20761
20764 constexpr bool is_array() const noexcept
20765 {
20766 return m_data.m_type == value_t::array;
20767 }
20768
20771 constexpr bool is_string() const noexcept
20772 {
20773 return m_data.m_type == value_t::string;
20774 }
20775
20778 constexpr bool is_binary() const noexcept
20779 {
20780 return m_data.m_type == value_t::binary;
20781 }
20782
20785 constexpr bool is_discarded() const noexcept
20786 {
20787 return m_data.m_type == value_t::discarded;
20788 }
20789
20792 constexpr operator value_t() const noexcept
20793 {
20794 return m_data.m_type;
20795 }
20796
20798
20799 private:
20801 // value access //
20803
20805 boolean_t get_impl(boolean_t* /*unused*/) const
20806 {
20808 {
20809 return m_data.m_value.boolean;
20810 }
20811
20812 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
20813 }
20814
20816 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
20817 {
20818 return is_object() ? m_data.m_value.object : nullptr;
20819 }
20820
20822 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
20823 {
20824 return is_object() ? m_data.m_value.object : nullptr;
20825 }
20826
20828 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
20829 {
20830 return is_array() ? m_data.m_value.array : nullptr;
20831 }
20832
20834 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
20835 {
20836 return is_array() ? m_data.m_value.array : nullptr;
20837 }
20838
20840 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
20841 {
20842 return is_string() ? m_data.m_value.string : nullptr;
20843 }
20844
20846 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
20847 {
20848 return is_string() ? m_data.m_value.string : nullptr;
20849 }
20850
20852 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
20853 {
20854 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20855 }
20856
20858 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
20859 {
20860 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20861 }
20862
20864 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
20865 {
20866 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20867 }
20868
20870 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
20871 {
20872 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20873 }
20874
20876 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
20877 {
20878 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20879 }
20880
20882 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
20883 {
20884 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20885 }
20886
20888 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
20889 {
20890 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20891 }
20892
20894 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
20895 {
20896 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20897 }
20898
20900 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
20901 {
20902 return is_binary() ? m_data.m_value.binary : nullptr;
20903 }
20904
20906 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
20907 {
20908 return is_binary() ? m_data.m_value.binary : nullptr;
20909 }
20910
20922 template<typename ReferenceType, typename ThisType>
20923 static ReferenceType get_ref_impl(ThisType& obj)
20924 {
20925 // delegate the call to get_ptr<>()
20926 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
20927
20928 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
20929 {
20930 return *ptr;
20931 }
20932
20933 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
20934 }
20935
20936 public:
20940
20943 template<typename PointerType, typename std::enable_if<
20944 std::is_pointer<PointerType>::value, int>::type = 0>
20945 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20946 {
20947 // delegate the call to get_impl_ptr<>()
20948 return get_impl_ptr(static_cast<PointerType>(nullptr));
20949 }
20950
20953 template < typename PointerType, typename std::enable_if <
20954 std::is_pointer<PointerType>::value&&
20955 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
20956 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20957 {
20958 // delegate the call to get_impl_ptr<>() const
20959 return get_impl_ptr(static_cast<PointerType>(nullptr));
20960 }
20961
20962 private:
21001 template < typename ValueType,
21005 int > = 0 >
21006 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
21007 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
21008 {
21009 auto ret = ValueType();
21010 JSONSerializer<ValueType>::from_json(*this, ret);
21011 return ret;
21012 }
21013
21044 template < typename ValueType,
21047 int > = 0 >
21048 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
21049 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
21050 {
21051 return JSONSerializer<ValueType>::from_json(*this);
21052 }
21053
21069 template < typename BasicJsonType,
21072 int > = 0 >
21073 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
21074 {
21075 return *this;
21076 }
21077
21092 template<typename BasicJsonType,
21094 std::is_same<BasicJsonType, basic_json_t>::value,
21095 int> = 0>
21096 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
21097 {
21098 return *this;
21099 }
21100
21105 template<typename PointerType,
21107 std::is_pointer<PointerType>::value,
21108 int> = 0>
21109 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21110 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21111 {
21112 // delegate the call to get_ptr
21113 return get_ptr<PointerType>();
21114 }
21115
21116 public:
21140 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21141#if defined(JSON_HAS_CPP_14)
21142 constexpr
21143#endif
21144 auto get() const noexcept(
21145 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21146 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21147 {
21148 // we cannot static_assert on ValueTypeCV being non-const, because
21149 // there is support for get<const basic_json_t>(), which is why we
21150 // still need the uncvref
21151 static_assert(!std::is_reference<ValueTypeCV>::value,
21152 "get() cannot be used with reference types, you might want to use get_ref()");
21153 return get_impl<ValueType>(detail::priority_tag<4> {});
21154 }
21155
21183 template<typename PointerType, typename std::enable_if<
21184 std::is_pointer<PointerType>::value, int>::type = 0>
21185 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21186 {
21187 // delegate the call to get_ptr
21188 return get_ptr<PointerType>();
21189 }
21190
21193 template < typename ValueType,
21197 int > = 0 >
21198 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21199 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21200 {
21201 JSONSerializer<ValueType>::from_json(*this, v);
21202 return v;
21203 }
21204
21205 // specialization to allow calling get_to with a basic_json value
21206 // see https://github.com/nlohmann/json/issues/2175
21207 template<typename ValueType,
21210 int> = 0>
21211 ValueType & get_to(ValueType& v) const
21212 {
21213 v = *this;
21214 return v;
21215 }
21216
21217 template <
21218 typename T, std::size_t N,
21219 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21222 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21223 noexcept(noexcept(JSONSerializer<Array>::from_json(
21224 std::declval<const basic_json_t&>(), v)))
21225 {
21226 JSONSerializer<Array>::from_json(*this, v);
21227 return v;
21228 }
21229
21232 template<typename ReferenceType, typename std::enable_if<
21233 std::is_reference<ReferenceType>::value, int>::type = 0>
21234 ReferenceType get_ref()
21235 {
21236 // delegate call to get_ref_impl
21237 return get_ref_impl<ReferenceType>(*this);
21238 }
21239
21242 template < typename ReferenceType, typename std::enable_if <
21243 std::is_reference<ReferenceType>::value&&
21244 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21245 ReferenceType get_ref() const
21246 {
21247 // delegate call to get_ref_impl
21248 return get_ref_impl<ReferenceType>(*this);
21249 }
21250
21280 template < typename ValueType, typename std::enable_if <
21288#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21290#endif
21291#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
21293#endif
21295 >::value, int >::type = 0 >
21296 JSON_EXPLICIT operator ValueType() const
21297 {
21298 // delegate the call to get<>() const
21299 return get<ValueType>();
21300 }
21301
21305 {
21306 if (!is_binary())
21307 {
21308 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21309 }
21310
21311 return *get_ptr<binary_t*>();
21312 }
21313
21316 const binary_t& get_binary() const
21317 {
21318 if (!is_binary())
21319 {
21320 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21321 }
21322
21323 return *get_ptr<const binary_t*>();
21324 }
21325
21327
21329 // element access //
21331
21335
21339 {
21340 // at only works for arrays
21342 {
21343 JSON_TRY
21344 {
21345 return set_parent(m_data.m_value.array->at(idx));
21346 }
21347 JSON_CATCH (std::out_of_range&)
21348 {
21349 // create better exception explanation
21350 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21351 }
21352 }
21353 else
21354 {
21355 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21356 }
21357 }
21358
21362 {
21363 // at only works for arrays
21365 {
21366 JSON_TRY
21367 {
21368 return m_data.m_value.array->at(idx);
21369 }
21370 JSON_CATCH (std::out_of_range&)
21371 {
21372 // create better exception explanation
21373 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21374 }
21375 }
21376 else
21377 {
21378 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21379 }
21380 }
21381
21384 reference at(const typename object_t::key_type& key)
21385 {
21386 // at only works for objects
21388 {
21389 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21390 }
21391
21392 auto it = m_data.m_value.object->find(key);
21393 if (it == m_data.m_value.object->end())
21394 {
21395 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21396 }
21397 return set_parent(it->second);
21398 }
21399
21402 template<class KeyType, detail::enable_if_t<
21404 reference at(KeyType && key)
21405 {
21406 // at only works for objects
21408 {
21409 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21410 }
21411
21412 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21413 if (it == m_data.m_value.object->end())
21414 {
21415 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21416 }
21417 return set_parent(it->second);
21418 }
21419
21422 const_reference at(const typename object_t::key_type& key) const
21423 {
21424 // at only works for objects
21426 {
21427 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21428 }
21429
21430 auto it = m_data.m_value.object->find(key);
21431 if (it == m_data.m_value.object->end())
21432 {
21433 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21434 }
21435 return it->second;
21436 }
21437
21440 template<class KeyType, detail::enable_if_t<
21442 const_reference at(KeyType && key) const
21443 {
21444 // at only works for objects
21446 {
21447 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21448 }
21449
21450 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21451 if (it == m_data.m_value.object->end())
21452 {
21453 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21454 }
21455 return it->second;
21456 }
21457
21461 {
21462 // implicitly convert null value to an empty array
21463 if (is_null())
21464 {
21465 m_data.m_type = value_t::array;
21466 m_data.m_value.array = create<array_t>();
21467 assert_invariant();
21468 }
21469
21470 // operator[] only works for arrays
21472 {
21473 // fill up array with null values if given idx is outside range
21474 if (idx >= m_data.m_value.array->size())
21475 {
21476#if JSON_DIAGNOSTICS
21477 // remember array size & capacity before resizing
21478 const auto old_size = m_data.m_value.array->size();
21479 const auto old_capacity = m_data.m_value.array->capacity();
21480#endif
21481 m_data.m_value.array->resize(idx + 1);
21482
21483#if JSON_DIAGNOSTICS
21484 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
21485 {
21486 // capacity has changed: update all parents
21487 set_parents();
21488 }
21489 else
21490 {
21491 // set parent for values added above
21492 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
21493 }
21494#endif
21495 assert_invariant();
21496 }
21497
21498 return m_data.m_value.array->operator[](idx);
21499 }
21500
21501 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21502 }
21503
21507 {
21508 // const operator[] only works for arrays
21510 {
21511 return m_data.m_value.array->operator[](idx);
21512 }
21513
21514 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21515 }
21516
21519 reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
21520 {
21521 // implicitly convert null value to an empty object
21522 if (is_null())
21523 {
21524 m_data.m_type = value_t::object;
21525 m_data.m_value.object = create<object_t>();
21526 assert_invariant();
21527 }
21528
21529 // operator[] only works for objects
21531 {
21532 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
21533 return set_parent(result.first->second);
21534 }
21535
21536 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21537 }
21538
21541 const_reference operator[](const typename object_t::key_type& key) const
21542 {
21543 // const operator[] only works for objects
21545 {
21546 auto it = m_data.m_value.object->find(key);
21547 JSON_ASSERT(it != m_data.m_value.object->end());
21548 return it->second;
21549 }
21550
21551 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21552 }
21553
21554 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
21555 // (they seemingly cannot be constrained to resolve the ambiguity)
21556 template<typename T>
21558 {
21559 return operator[](typename object_t::key_type(key));
21560 }
21561
21562 template<typename T>
21564 {
21565 return operator[](typename object_t::key_type(key));
21566 }
21567
21570 template<class KeyType, detail::enable_if_t<
21572 reference operator[](KeyType && key)
21573 {
21574 // implicitly convert null value to an empty object
21575 if (is_null())
21576 {
21577 m_data.m_type = value_t::object;
21578 m_data.m_value.object = create<object_t>();
21579 assert_invariant();
21580 }
21581
21582 // operator[] only works for objects
21584 {
21585 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
21586 return set_parent(result.first->second);
21587 }
21588
21589 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21590 }
21591
21594 template<class KeyType, detail::enable_if_t<
21596 const_reference operator[](KeyType && key) const
21597 {
21598 // const operator[] only works for objects
21600 {
21601 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21602 JSON_ASSERT(it != m_data.m_value.object->end());
21603 return it->second;
21604 }
21605
21606 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21607 }
21608
21609 private:
21610 template<typename KeyType>
21611 using is_comparable_with_object_key = detail::is_comparable <
21612 object_comparator_t, const typename object_t::key_type&, KeyType >;
21613
21614 template<typename ValueType>
21615 using value_return_type = std::conditional <
21617 string_t, typename std::decay<ValueType>::type >;
21618
21619 public:
21622 template < class ValueType, detail::enable_if_t <
21625 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21626 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
21627 {
21628 // value only works for objects
21630 {
21631 // if key is found, return value and given default value otherwise
21632 const auto it = find(key);
21633 if (it != end())
21634 {
21635 return it->template get<ValueType>();
21636 }
21637
21638 return default_value;
21639 }
21640
21641 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21642 }
21643
21646 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21650 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21651 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
21652 {
21653 // value only works for objects
21655 {
21656 // if key is found, return value and given default value otherwise
21657 const auto it = find(key);
21658 if (it != end())
21659 {
21660 return it->template get<ReturnType>();
21661 }
21662
21663 return std::forward<ValueType>(default_value);
21664 }
21665
21666 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21667 }
21668
21671 template < class ValueType, class KeyType, detail::enable_if_t <
21674 && is_comparable_with_object_key<KeyType>::value
21676 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21677 ValueType value(KeyType && key, const ValueType& default_value) const
21678 {
21679 // value only works for objects
21681 {
21682 // if key is found, return value and given default value otherwise
21683 const auto it = find(std::forward<KeyType>(key));
21684 if (it != end())
21685 {
21686 return it->template get<ValueType>();
21687 }
21688
21689 return default_value;
21690 }
21691
21692 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21693 }
21694
21697 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
21701 && is_comparable_with_object_key<KeyType>::value
21703 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21704 ReturnType value(KeyType && key, ValueType && default_value) const
21705 {
21706 // value only works for objects
21708 {
21709 // if key is found, return value and given default value otherwise
21710 const auto it = find(std::forward<KeyType>(key));
21711 if (it != end())
21712 {
21713 return it->template get<ReturnType>();
21714 }
21715
21716 return std::forward<ValueType>(default_value);
21717 }
21718
21719 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21720 }
21721
21724 template < class ValueType, detail::enable_if_t <
21726 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21727 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
21728 {
21729 // value only works for objects
21731 {
21732 // if pointer resolves a value, return it or use default value
21733 JSON_TRY
21734 {
21735 return ptr.get_checked(this).template get<ValueType>();
21736 }
21738 {
21739 return default_value;
21740 }
21741 }
21742
21743 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21744 }
21745
21748 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21751 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21752 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
21753 {
21754 // value only works for objects
21756 {
21757 // if pointer resolves a value, return it or use default value
21758 JSON_TRY
21759 {
21760 return ptr.get_checked(this).template get<ReturnType>();
21761 }
21763 {
21764 return std::forward<ValueType>(default_value);
21765 }
21766 }
21767
21768 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21769 }
21770
21771 template < class ValueType, class BasicJsonType, detail::enable_if_t <
21774 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21775 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21776 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
21777 {
21778 return value(ptr.convert(), default_value);
21779 }
21780
21781 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
21785 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21786 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21787 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
21788 {
21789 return value(ptr.convert(), std::forward<ValueType>(default_value));
21790 }
21791
21795 {
21796 return *begin();
21797 }
21798
21802 {
21803 return *cbegin();
21804 }
21805
21809 {
21810 auto tmp = end();
21811 --tmp;
21812 return *tmp;
21813 }
21814
21818 {
21819 auto tmp = cend();
21820 --tmp;
21821 return *tmp;
21822 }
21823
21826 template < class IteratorType, detail::enable_if_t <
21827 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21828 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21829 IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
21830 {
21831 // make sure iterator fits the current value
21832 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
21833 {
21834 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21835 }
21836
21837 IteratorType result = end();
21838
21839 switch (m_data.m_type)
21840 {
21841 case value_t::boolean:
21842 case value_t::number_float:
21843 case value_t::number_integer:
21844 case value_t::number_unsigned:
21845 case value_t::string:
21846 case value_t::binary:
21847 {
21848 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
21849 {
21850 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
21851 }
21852
21853 if (is_string())
21854 {
21855 AllocatorType<string_t> alloc;
21856 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21857 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21858 m_data.m_value.string = nullptr;
21859 }
21860 else if (is_binary())
21861 {
21862 AllocatorType<binary_t> alloc;
21863 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21864 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21865 m_data.m_value.binary = nullptr;
21866 }
21867
21868 m_data.m_type = value_t::null;
21869 assert_invariant();
21870 break;
21871 }
21872
21873 case value_t::object:
21874 {
21875 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
21876 break;
21877 }
21878
21879 case value_t::array:
21880 {
21881 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
21882 break;
21883 }
21884
21885 case value_t::null:
21886 case value_t::discarded:
21887 default:
21888 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21889 }
21890
21891 return result;
21892 }
21893
21896 template < class IteratorType, detail::enable_if_t <
21897 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21898 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21899 IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
21900 {
21901 // make sure iterator fits the current value
21902 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
21903 {
21904 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
21905 }
21906
21907 IteratorType result = end();
21908
21909 switch (m_data.m_type)
21910 {
21911 case value_t::boolean:
21912 case value_t::number_float:
21913 case value_t::number_integer:
21914 case value_t::number_unsigned:
21915 case value_t::string:
21916 case value_t::binary:
21917 {
21918 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
21919 || !last.m_it.primitive_iterator.is_end()))
21920 {
21921 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
21922 }
21923
21924 if (is_string())
21925 {
21926 AllocatorType<string_t> alloc;
21927 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21928 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21929 m_data.m_value.string = nullptr;
21930 }
21931 else if (is_binary())
21932 {
21933 AllocatorType<binary_t> alloc;
21934 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21935 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21936 m_data.m_value.binary = nullptr;
21937 }
21938
21939 m_data.m_type = value_t::null;
21940 assert_invariant();
21941 break;
21942 }
21943
21944 case value_t::object:
21945 {
21946 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
21947 last.m_it.object_iterator);
21948 break;
21949 }
21950
21951 case value_t::array:
21952 {
21953 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
21954 last.m_it.array_iterator);
21955 break;
21956 }
21957
21958 case value_t::null:
21959 case value_t::discarded:
21960 default:
21961 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21962 }
21963
21964 return result;
21965 }
21966
21967 private:
21968 template < typename KeyType, detail::enable_if_t <
21970 size_type erase_internal(KeyType && key)
21971 {
21972 // this erase only works for objects
21974 {
21975 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21976 }
21977
21978 return m_data.m_value.object->erase(std::forward<KeyType>(key));
21979 }
21980
21981 template < typename KeyType, detail::enable_if_t <
21983 size_type erase_internal(KeyType && key)
21984 {
21985 // this erase only works for objects
21987 {
21988 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21989 }
21990
21991 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21992 if (it != m_data.m_value.object->end())
21993 {
21994 m_data.m_value.object->erase(it);
21995 return 1;
21996 }
21997 return 0;
21998 }
21999
22000 public:
22001
22004 size_type erase(const typename object_t::key_type& key)
22005 {
22006 // the indirection via erase_internal() is added to avoid making this
22007 // function a template and thus de-rank it during overload resolution
22008 return erase_internal(key);
22009 }
22010
22013 template<class KeyType, detail::enable_if_t<
22015 size_type erase(KeyType && key)
22016 {
22017 return erase_internal(std::forward<KeyType>(key));
22018 }
22019
22022 void erase(const size_type idx)
22023 {
22024 // this erase only works for arrays
22026 {
22027 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
22028 {
22029 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22030 }
22031
22032 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
22033 }
22034 else
22035 {
22036 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22037 }
22038 }
22039
22041
22043 // lookup //
22045
22048
22051 iterator find(const typename object_t::key_type& key)
22052 {
22053 auto result = end();
22054
22055 if (is_object())
22056 {
22057 result.m_it.object_iterator = m_data.m_value.object->find(key);
22058 }
22059
22060 return result;
22061 }
22062
22065 const_iterator find(const typename object_t::key_type& key) const
22066 {
22067 auto result = cend();
22068
22069 if (is_object())
22070 {
22071 result.m_it.object_iterator = m_data.m_value.object->find(key);
22072 }
22073
22074 return result;
22075 }
22076
22079 template<class KeyType, detail::enable_if_t<
22081 iterator find(KeyType && key)
22082 {
22083 auto result = end();
22084
22085 if (is_object())
22086 {
22087 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22088 }
22089
22090 return result;
22091 }
22092
22095 template<class KeyType, detail::enable_if_t<
22097 const_iterator find(KeyType && key) const
22098 {
22099 auto result = cend();
22100
22101 if (is_object())
22102 {
22103 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22104 }
22105
22106 return result;
22107 }
22108
22111 size_type count(const typename object_t::key_type& key) const
22112 {
22113 // return 0 for all nonobject types
22114 return is_object() ? m_data.m_value.object->count(key) : 0;
22115 }
22116
22119 template<class KeyType, detail::enable_if_t<
22121 size_type count(KeyType && key) const
22122 {
22123 // return 0 for all nonobject types
22124 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22125 }
22126
22129 bool contains(const typename object_t::key_type& key) const
22130 {
22131 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22132 }
22133
22136 template<class KeyType, detail::enable_if_t<
22138 bool contains(KeyType && key) const
22139 {
22140 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22141 }
22142
22145 bool contains(const json_pointer& ptr) const
22146 {
22147 return ptr.contains(this);
22148 }
22149
22150 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22151 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22152 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22153 {
22154 return ptr.contains(this);
22155 }
22156
22158
22160 // iterators //
22162
22165
22168 iterator begin() noexcept
22169 {
22170 iterator result(this);
22171 result.set_begin();
22172 return result;
22173 }
22174
22177 const_iterator begin() const noexcept
22178 {
22179 return cbegin();
22180 }
22181
22184 const_iterator cbegin() const noexcept
22185 {
22186 const_iterator result(this);
22187 result.set_begin();
22188 return result;
22189 }
22190
22193 iterator end() noexcept
22194 {
22195 iterator result(this);
22196 result.set_end();
22197 return result;
22198 }
22199
22202 const_iterator end() const noexcept
22203 {
22204 return cend();
22205 }
22206
22209 const_iterator cend() const noexcept
22210 {
22211 const_iterator result(this);
22212 result.set_end();
22213 return result;
22214 }
22215
22219 {
22220 return reverse_iterator(end());
22221 }
22222
22226 {
22227 return crbegin();
22228 }
22229
22233 {
22234 return reverse_iterator(begin());
22235 }
22236
22240 {
22241 return crend();
22242 }
22243
22247 {
22248 return const_reverse_iterator(cend());
22249 }
22250
22254 {
22256 }
22257
22258 public:
22265 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22266 {
22267 return ref.items();
22268 }
22269
22276 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
22277 {
22278 return ref.items();
22279 }
22280
22283 iteration_proxy<iterator> items() noexcept
22284 {
22285 return iteration_proxy<iterator>(*this);
22286 }
22287
22290 iteration_proxy<const_iterator> items() const noexcept
22291 {
22292 return iteration_proxy<const_iterator>(*this);
22293 }
22294
22296
22298 // capacity //
22300
22303
22306 bool empty() const noexcept
22307 {
22308 switch (m_data.m_type)
22309 {
22310 case value_t::null:
22311 {
22312 // null values are empty
22313 return true;
22314 }
22315
22316 case value_t::array:
22317 {
22318 // delegate call to array_t::empty()
22319 return m_data.m_value.array->empty();
22320 }
22321
22322 case value_t::object:
22323 {
22324 // delegate call to object_t::empty()
22325 return m_data.m_value.object->empty();
22326 }
22327
22328 case value_t::string:
22329 case value_t::boolean:
22330 case value_t::number_integer:
22331 case value_t::number_unsigned:
22332 case value_t::number_float:
22333 case value_t::binary:
22334 case value_t::discarded:
22335 default:
22336 {
22337 // all other types are nonempty
22338 return false;
22339 }
22340 }
22341 }
22342
22345 size_type size() const noexcept
22346 {
22347 switch (m_data.m_type)
22348 {
22349 case value_t::null:
22350 {
22351 // null values are empty
22352 return 0;
22353 }
22354
22355 case value_t::array:
22356 {
22357 // delegate call to array_t::size()
22358 return m_data.m_value.array->size();
22359 }
22360
22361 case value_t::object:
22362 {
22363 // delegate call to object_t::size()
22364 return m_data.m_value.object->size();
22365 }
22366
22367 case value_t::string:
22368 case value_t::boolean:
22369 case value_t::number_integer:
22370 case value_t::number_unsigned:
22371 case value_t::number_float:
22372 case value_t::binary:
22373 case value_t::discarded:
22374 default:
22375 {
22376 // all other types have size 1
22377 return 1;
22378 }
22379 }
22380 }
22381
22384 size_type max_size() const noexcept
22385 {
22386 switch (m_data.m_type)
22387 {
22388 case value_t::array:
22389 {
22390 // delegate call to array_t::max_size()
22391 return m_data.m_value.array->max_size();
22392 }
22393
22394 case value_t::object:
22395 {
22396 // delegate call to object_t::max_size()
22397 return m_data.m_value.object->max_size();
22398 }
22399
22400 case value_t::null:
22401 case value_t::string:
22402 case value_t::boolean:
22403 case value_t::number_integer:
22404 case value_t::number_unsigned:
22405 case value_t::number_float:
22406 case value_t::binary:
22407 case value_t::discarded:
22408 default:
22409 {
22410 // all other types have max_size() == size()
22411 return size();
22412 }
22413 }
22414 }
22415
22417
22419 // modifiers //
22421
22424
22427 void clear() noexcept
22428 {
22429 switch (m_data.m_type)
22430 {
22431 case value_t::number_integer:
22432 {
22433 m_data.m_value.number_integer = 0;
22434 break;
22435 }
22436
22437 case value_t::number_unsigned:
22438 {
22439 m_data.m_value.number_unsigned = 0;
22440 break;
22441 }
22442
22443 case value_t::number_float:
22444 {
22445 m_data.m_value.number_float = 0.0;
22446 break;
22447 }
22448
22449 case value_t::boolean:
22450 {
22451 m_data.m_value.boolean = false;
22452 break;
22453 }
22454
22455 case value_t::string:
22456 {
22457 m_data.m_value.string->clear();
22458 break;
22459 }
22460
22461 case value_t::binary:
22462 {
22463 m_data.m_value.binary->clear();
22464 break;
22465 }
22466
22467 case value_t::array:
22468 {
22469 m_data.m_value.array->clear();
22470 break;
22471 }
22472
22473 case value_t::object:
22474 {
22475 m_data.m_value.object->clear();
22476 break;
22477 }
22478
22479 case value_t::null:
22480 case value_t::discarded:
22481 default:
22482 break;
22483 }
22484 }
22485
22489 {
22490 // push_back only works for null objects or arrays
22491 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22492 {
22493 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22494 }
22495
22496 // transform null object into an array
22497 if (is_null())
22498 {
22499 m_data.m_type = value_t::array;
22500 m_data.m_value = value_t::array;
22501 assert_invariant();
22502 }
22503
22504 // add element to array (move semantics)
22505 const auto old_capacity = m_data.m_value.array->capacity();
22506 m_data.m_value.array->push_back(std::move(val));
22507 set_parent(m_data.m_value.array->back(), old_capacity);
22508 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
22509 }
22510
22514 {
22515 push_back(std::move(val));
22516 return *this;
22517 }
22518
22521 void push_back(const basic_json& val)
22522 {
22523 // push_back only works for null objects or arrays
22524 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22525 {
22526 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22527 }
22528
22529 // transform null object into an array
22530 if (is_null())
22531 {
22532 m_data.m_type = value_t::array;
22533 m_data.m_value = value_t::array;
22534 assert_invariant();
22535 }
22536
22537 // add element to array
22538 const auto old_capacity = m_data.m_value.array->capacity();
22539 m_data.m_value.array->push_back(val);
22540 set_parent(m_data.m_value.array->back(), old_capacity);
22541 }
22542
22546 {
22547 push_back(val);
22548 return *this;
22549 }
22550
22553 void push_back(const typename object_t::value_type& val)
22554 {
22555 // push_back only works for null objects or objects
22556 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22557 {
22558 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22559 }
22560
22561 // transform null object into an object
22562 if (is_null())
22563 {
22564 m_data.m_type = value_t::object;
22565 m_data.m_value = value_t::object;
22566 assert_invariant();
22567 }
22568
22569 // add element to object
22570 auto res = m_data.m_value.object->insert(val);
22571 set_parent(res.first->second);
22572 }
22573
22576 reference operator+=(const typename object_t::value_type& val)
22577 {
22578 push_back(val);
22579 return *this;
22580 }
22581
22585 {
22586 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
22587 {
22588 basic_json&& key = init.begin()->moved_or_copied();
22589 push_back(typename object_t::value_type(
22590 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
22591 }
22592 else
22593 {
22594 push_back(basic_json(init));
22595 }
22596 }
22597
22601 {
22602 push_back(init);
22603 return *this;
22604 }
22605
22608 template<class... Args>
22609 reference emplace_back(Args&& ... args)
22610 {
22611 // emplace_back only works for null objects or arrays
22612 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22613 {
22614 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
22615 }
22616
22617 // transform null object into an array
22618 if (is_null())
22619 {
22620 m_data.m_type = value_t::array;
22621 m_data.m_value = value_t::array;
22622 assert_invariant();
22623 }
22624
22625 // add element to array (perfect forwarding)
22626 const auto old_capacity = m_data.m_value.array->capacity();
22627 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
22628 return set_parent(m_data.m_value.array->back(), old_capacity);
22629 }
22630
22633 template<class... Args>
22634 std::pair<iterator, bool> emplace(Args&& ... args)
22635 {
22636 // emplace only works for null objects or arrays
22637 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22638 {
22639 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
22640 }
22641
22642 // transform null object into an object
22643 if (is_null())
22644 {
22645 m_data.m_type = value_t::object;
22646 m_data.m_value = value_t::object;
22647 assert_invariant();
22648 }
22649
22650 // add element to array (perfect forwarding)
22651 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
22652 set_parent(res.first->second);
22653
22654 // create result iterator and set iterator to the result of emplace
22655 auto it = begin();
22656 it.m_it.object_iterator = res.first;
22657
22658 // return pair of iterator and boolean
22659 return {it, res.second};
22660 }
22661
22665 template<typename... Args>
22666 iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
22667 {
22668 iterator result(this);
22669 JSON_ASSERT(m_data.m_value.array != nullptr);
22670
22671 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
22672 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
22673 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
22674
22675 // This could have been written as:
22676 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
22677 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
22678
22679 set_parents();
22680 return result;
22681 }
22682
22685 iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
22686 {
22687 // insert only works for arrays
22689 {
22690 // check if iterator pos fits to this JSON value
22691 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22692 {
22693 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22694 }
22695
22696 // insert to array and return iterator
22697 return insert_iterator(pos, val);
22698 }
22699
22700 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22701 }
22702
22705 iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
22706 {
22707 return insert(pos, val);
22708 }
22709
22712 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
22713 {
22714 // insert only works for arrays
22716 {
22717 // check if iterator pos fits to this JSON value
22718 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22719 {
22720 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22721 }
22722
22723 // insert to array and return iterator
22724 return insert_iterator(pos, cnt, val);
22725 }
22726
22727 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22728 }
22729
22732 iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
22733 {
22734 // insert only works for arrays
22736 {
22737 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22738 }
22739
22740 // check if iterator pos fits to this JSON value
22741 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22742 {
22743 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22744 }
22745
22746 // check if range iterators belong to the same JSON object
22747 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22748 {
22749 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22750 }
22751
22752 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
22753 {
22754 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
22755 }
22756
22757 // insert to array and return iterator
22758 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22759 }
22760
22763 iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
22764 {
22765 // insert only works for arrays
22767 {
22768 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22769 }
22770
22771 // check if iterator pos fits to this JSON value
22772 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22773 {
22774 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22775 }
22776
22777 // insert to array and return iterator
22778 return insert_iterator(pos, ilist.begin(), ilist.end());
22779 }
22780
22783 void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
22784 {
22785 // insert only works for objects
22787 {
22788 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22789 }
22790
22791 // check if range iterators belong to the same JSON object
22792 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22793 {
22794 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22795 }
22796
22797 // passed iterators must belong to objects
22798 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22799 {
22800 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
22801 }
22802
22803 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22804 }
22805
22808 void update(const_reference j, bool merge_objects = false)
22809 {
22810 update(j.begin(), j.end(), merge_objects);
22811 }
22812
22815 void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
22816 {
22817 // implicitly convert null value to an empty object
22818 if (is_null())
22819 {
22820 m_data.m_type = value_t::object;
22821 m_data.m_value.object = create<object_t>();
22822 assert_invariant();
22823 }
22824
22826 {
22827 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
22828 }
22829
22830 // check if range iterators belong to the same JSON object
22831 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22832 {
22833 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22834 }
22835
22836 // passed iterators must belong to objects
22837 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22838 {
22839 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
22840 }
22841
22842 for (auto it = first; it != last; ++it)
22843 {
22844 if (merge_objects && it.value().is_object())
22845 {
22846 auto it2 = m_data.m_value.object->find(it.key());
22847 if (it2 != m_data.m_value.object->end())
22848 {
22849 it2->second.update(it.value(), true);
22850 continue;
22851 }
22852 }
22853 m_data.m_value.object->operator[](it.key()) = it.value();
22854#if JSON_DIAGNOSTICS
22855 m_data.m_value.object->operator[](it.key()).m_parent = this;
22856#endif
22857 }
22858 }
22859
22862 void swap(reference other) noexcept (
22863 std::is_nothrow_move_constructible<value_t>::value&&
22864 std::is_nothrow_move_assignable<value_t>::value&&
22865 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22866 std::is_nothrow_move_assignable<json_value>::value
22867 )
22868 {
22869 std::swap(m_data.m_type, other.m_data.m_type);
22870 std::swap(m_data.m_value, other.m_data.m_value);
22871
22872 set_parents();
22873 other.set_parents();
22874 assert_invariant();
22875 }
22876
22879 friend void swap(reference left, reference right) noexcept (
22880 std::is_nothrow_move_constructible<value_t>::value&&
22881 std::is_nothrow_move_assignable<value_t>::value&&
22882 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22883 std::is_nothrow_move_assignable<json_value>::value
22884 )
22885 {
22886 left.swap(right);
22887 }
22888
22891 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22892 {
22893 // swap only works for arrays
22895 {
22896 using std::swap;
22897 swap(*(m_data.m_value.array), other);
22898 }
22899 else
22900 {
22901 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
22902 }
22903 }
22904
22907 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22908 {
22909 // swap only works for objects
22911 {
22912 using std::swap;
22913 swap(*(m_data.m_value.object), other);
22914 }
22915 else
22916 {
22917 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
22918 }
22919 }
22920
22923 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22924 {
22925 // swap only works for strings
22927 {
22928 using std::swap;
22929 swap(*(m_data.m_value.string), other);
22930 }
22931 else
22932 {
22933 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
22934 }
22935 }
22936
22939 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22940 {
22941 // swap only works for strings
22943 {
22944 using std::swap;
22945 swap(*(m_data.m_value.binary), other);
22946 }
22947 else
22948 {
22949 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
22950 }
22951 }
22952
22955 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
22956 {
22957 // swap only works for strings
22959 {
22960 using std::swap;
22961 swap(*(m_data.m_value.binary), other);
22962 }
22963 else
22964 {
22965 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
22966 }
22967 }
22968
22970
22972 // lexicographical comparison operators //
22974
22977
22978 // note parentheses around operands are necessary; see
22979 // https://github.com/nlohmann/json/issues/1530
22980#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
22981 const auto lhs_type = lhs.type(); \
22982 const auto rhs_type = rhs.type(); \
22983 \
22984 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
22985 { \
22986 switch (lhs_type) \
22987 { \
22988 case value_t::array: \
22989 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
22990 \
22991 case value_t::object: \
22992 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
22993 \
22994 case value_t::null: \
22995 return (null_result); \
22996 \
22997 case value_t::string: \
22998 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
22999 \
23000 case value_t::boolean: \
23001 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
23002 \
23003 case value_t::number_integer: \
23004 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
23005 \
23006 case value_t::number_unsigned: \
23007 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
23008 \
23009 case value_t::number_float: \
23010 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
23011 \
23012 case value_t::binary: \
23013 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
23014 \
23015 case value_t::discarded: \
23016 default: \
23017 return (unordered_result); \
23018 } \
23019 } \
23020 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
23021 { \
23022 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
23023 } \
23024 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
23025 { \
23026 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
23027 } \
23028 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
23029 { \
23030 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
23031 } \
23032 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
23033 { \
23034 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
23035 } \
23036 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
23037 { \
23038 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
23039 } \
23040 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
23041 { \
23042 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
23043 } \
23044 else if(compares_unordered(lhs, rhs))\
23045 {\
23046 return (unordered_result);\
23047 }\
23048 \
23049 return (default_result);
23050
23052 // returns true if:
23053 // - any operand is NaN and the other operand is of number type
23054 // - any operand is discarded
23055 // in legacy mode, discarded values are considered ordered if
23056 // an operation is computed as an odd number of inverses of others
23057 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
23058 {
23059 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
23060 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
23061 {
23062 return true;
23063 }
23064#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23065 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
23066#else
23067 static_cast<void>(inverse);
23068 return lhs.is_discarded() || rhs.is_discarded();
23069#endif
23070 }
23071
23072 private:
23073 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
23074 {
23075 return compares_unordered(*this, rhs, inverse);
23076 }
23077
23078 public:
23079#if JSON_HAS_THREE_WAY_COMPARISON
23082 bool operator==(const_reference rhs) const noexcept
23083 {
23084#ifdef __GNUC__
23085#pragma GCC diagnostic push
23086#pragma GCC diagnostic ignored "-Wfloat-equal"
23087#endif
23088 const_reference lhs = *this;
23089 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23090#ifdef __GNUC__
23091#pragma GCC diagnostic pop
23092#endif
23093 }
23094
23097 template<typename ScalarType>
23098 requires std::is_scalar_v<ScalarType>
23099 bool operator==(ScalarType rhs) const noexcept
23100 {
23101 return *this == basic_json(rhs);
23102 }
23103
23106 bool operator!=(const_reference rhs) const noexcept
23107 {
23108 if (compares_unordered(rhs, true))
23109 {
23110 return false;
23111 }
23112 return !operator==(rhs);
23113 }
23114
23117 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23118 {
23119 const_reference lhs = *this;
23120 // default_result is used if we cannot compare values. In that case,
23121 // we compare types.
23122 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23123 std::partial_ordering::equivalent,
23124 std::partial_ordering::unordered,
23125 lhs_type <=> rhs_type) // *NOPAD*
23126 }
23127
23130 template<typename ScalarType>
23131 requires std::is_scalar_v<ScalarType>
23132 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23133 {
23134 return *this <=> basic_json(rhs); // *NOPAD*
23135 }
23136
23137#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23138 // all operators that are computed as an odd number of inverses of others
23139 // need to be overloaded to emulate the legacy comparison behavior
23140
23144 bool operator<=(const_reference rhs) const noexcept
23145 {
23146 if (compares_unordered(rhs, true))
23147 {
23148 return false;
23149 }
23150 return !(rhs < *this);
23151 }
23152
23155 template<typename ScalarType>
23156 requires std::is_scalar_v<ScalarType>
23157 bool operator<=(ScalarType rhs) const noexcept
23158 {
23159 return *this <= basic_json(rhs);
23160 }
23161
23165 bool operator>=(const_reference rhs) const noexcept
23166 {
23167 if (compares_unordered(rhs, true))
23168 {
23169 return false;
23170 }
23171 return !(*this < rhs);
23172 }
23173
23176 template<typename ScalarType>
23177 requires std::is_scalar_v<ScalarType>
23178 bool operator>=(ScalarType rhs) const noexcept
23179 {
23180 return *this >= basic_json(rhs);
23181 }
23182#endif
23183#else
23186 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23187 {
23188#ifdef __GNUC__
23189#pragma GCC diagnostic push
23190#pragma GCC diagnostic ignored "-Wfloat-equal"
23191#endif
23192 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23193#ifdef __GNUC__
23194#pragma GCC diagnostic pop
23195#endif
23196 }
23197
23200 template<typename ScalarType, typename std::enable_if<
23201 std::is_scalar<ScalarType>::value, int>::type = 0>
23202 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23203 {
23204 return lhs == basic_json(rhs);
23205 }
23206
23209 template<typename ScalarType, typename std::enable_if<
23210 std::is_scalar<ScalarType>::value, int>::type = 0>
23211 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23212 {
23213 return basic_json(lhs) == rhs;
23214 }
23215
23218 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23219 {
23220 if (compares_unordered(lhs, rhs, true))
23221 {
23222 return false;
23223 }
23224 return !(lhs == rhs);
23225 }
23226
23229 template<typename ScalarType, typename std::enable_if<
23230 std::is_scalar<ScalarType>::value, int>::type = 0>
23231 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23232 {
23233 return lhs != basic_json(rhs);
23234 }
23235
23238 template<typename ScalarType, typename std::enable_if<
23239 std::is_scalar<ScalarType>::value, int>::type = 0>
23240 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23241 {
23242 return basic_json(lhs) != rhs;
23243 }
23244
23247 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23248 {
23249 // default_result is used if we cannot compare values. In that case,
23250 // we compare types. Note we have to call the operator explicitly,
23251 // because MSVC has problems otherwise.
23252 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23253 }
23254
23257 template<typename ScalarType, typename std::enable_if<
23258 std::is_scalar<ScalarType>::value, int>::type = 0>
23259 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23260 {
23261 return lhs < basic_json(rhs);
23262 }
23263
23266 template<typename ScalarType, typename std::enable_if<
23267 std::is_scalar<ScalarType>::value, int>::type = 0>
23268 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23269 {
23270 return basic_json(lhs) < rhs;
23271 }
23272
23275 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23276 {
23277 if (compares_unordered(lhs, rhs, true))
23278 {
23279 return false;
23280 }
23281 return !(rhs < lhs);
23282 }
23283
23286 template<typename ScalarType, typename std::enable_if<
23287 std::is_scalar<ScalarType>::value, int>::type = 0>
23288 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23289 {
23290 return lhs <= basic_json(rhs);
23291 }
23292
23295 template<typename ScalarType, typename std::enable_if<
23296 std::is_scalar<ScalarType>::value, int>::type = 0>
23297 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23298 {
23299 return basic_json(lhs) <= rhs;
23300 }
23301
23304 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
23305 {
23306 // double inverse
23307 if (compares_unordered(lhs, rhs))
23308 {
23309 return false;
23310 }
23311 return !(lhs <= rhs);
23312 }
23313
23316 template<typename ScalarType, typename std::enable_if<
23317 std::is_scalar<ScalarType>::value, int>::type = 0>
23318 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
23319 {
23320 return lhs > basic_json(rhs);
23321 }
23322
23325 template<typename ScalarType, typename std::enable_if<
23326 std::is_scalar<ScalarType>::value, int>::type = 0>
23327 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
23328 {
23329 return basic_json(lhs) > rhs;
23330 }
23331
23334 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
23335 {
23336 if (compares_unordered(lhs, rhs, true))
23337 {
23338 return false;
23339 }
23340 return !(lhs < rhs);
23341 }
23342
23345 template<typename ScalarType, typename std::enable_if<
23346 std::is_scalar<ScalarType>::value, int>::type = 0>
23347 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
23348 {
23349 return lhs >= basic_json(rhs);
23350 }
23351
23354 template<typename ScalarType, typename std::enable_if<
23355 std::is_scalar<ScalarType>::value, int>::type = 0>
23356 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
23357 {
23358 return basic_json(lhs) >= rhs;
23359 }
23360#endif
23361
23362#undef JSON_IMPLEMENT_OPERATOR
23363
23365
23367 // serialization //
23369
23372#ifndef JSON_NO_IO
23375 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
23376 {
23377 // read width member and use it as indentation parameter if nonzero
23378 const bool pretty_print = o.width() > 0;
23379 const auto indentation = pretty_print ? o.width() : 0;
23380
23381 // reset width to 0 for subsequent calls to this stream
23382 o.width(0);
23383
23384 // do the actual serialization
23385 serializer s(detail::output_adapter<char>(o), o.fill());
23386 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
23387 return o;
23388 }
23389
23396 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
23397 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
23398 {
23399 return o << j;
23400 }
23401#endif // JSON_NO_IO
23403
23405 // deserialization //
23407
23410
23413 template<typename InputType>
23415 static basic_json parse(InputType&& i,
23416 parser_callback_t cb = nullptr,
23417 const bool allow_exceptions = true,
23418 const bool ignore_comments = false)
23419 {
23421 parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result);
23422 return result;
23423 }
23424
23427 template<typename IteratorType>
23429 static basic_json parse(IteratorType first,
23430 IteratorType last,
23431 parser_callback_t cb = nullptr,
23432 const bool allow_exceptions = true,
23433 const bool ignore_comments = false)
23434 {
23436 parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result);
23437 return result;
23438 }
23439
23441 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
23442 static basic_json parse(detail::span_input_adapter&& i,
23443 parser_callback_t cb = nullptr,
23444 const bool allow_exceptions = true,
23445 const bool ignore_comments = false)
23446 {
23448 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments).parse(true, result);
23449 return result;
23450 }
23451
23454 template<typename InputType>
23455 static bool accept(InputType&& i,
23456 const bool ignore_comments = false)
23457 {
23458 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
23459 }
23460
23463 template<typename IteratorType>
23464 static bool accept(IteratorType first, IteratorType last,
23465 const bool ignore_comments = false)
23466 {
23467 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
23468 }
23469
23471 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
23472 static bool accept(detail::span_input_adapter&& i,
23473 const bool ignore_comments = false)
23474 {
23475 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
23476 }
23477
23480 template <typename InputType, typename SAX>
23482 static bool sax_parse(InputType&& i, SAX* sax,
23484 const bool strict = true,
23485 const bool ignore_comments = false)
23486 {
23487 auto ia = detail::input_adapter(std::forward<InputType>(i));
23488 return format == input_format_t::json
23489 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23490 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23491 }
23492
23495 template<class IteratorType, class SAX>
23497 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23499 const bool strict = true,
23500 const bool ignore_comments = false)
23501 {
23502 auto ia = detail::input_adapter(std::move(first), std::move(last));
23503 return format == input_format_t::json
23504 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23505 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23506 }
23507
23513 template <typename SAX>
23514 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23516 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
23518 const bool strict = true,
23519 const bool ignore_comments = false)
23520 {
23521 auto ia = i.get();
23522 return format == input_format_t::json
23523 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23524 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23525 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23526 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23527 }
23528#ifndef JSON_NO_IO
23535 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
23536 friend std::istream& operator<<(basic_json& j, std::istream& i)
23537 {
23538 return operator>>(i, j);
23539 }
23540
23543 friend std::istream& operator>>(std::istream& i, basic_json& j)
23544 {
23545 parser(detail::input_adapter(i)).parse(false, j);
23546 return i;
23547 }
23548#endif // JSON_NO_IO
23550
23552 // convenience functions //
23554
23558 const char* type_name() const noexcept
23559 {
23560 switch (m_data.m_type)
23561 {
23562 case value_t::null:
23563 return "null";
23564 case value_t::object:
23565 return "object";
23566 case value_t::array:
23567 return "array";
23568 case value_t::string:
23569 return "string";
23570 case value_t::boolean:
23571 return "boolean";
23572 case value_t::binary:
23573 return "binary";
23574 case value_t::discarded:
23575 return "discarded";
23576 case value_t::number_integer:
23577 case value_t::number_unsigned:
23578 case value_t::number_float:
23579 default:
23580 return "number";
23581 }
23582 }
23583
23586 // member variables //
23588
23589 struct data
23590 {
23592 value_t m_type = value_t::null;
23593
23595 json_value m_value = {};
23596
23597 data(const value_t v)
23598 : m_type(v), m_value(v)
23599 {
23600 }
23601
23602 data(size_type cnt, const basic_json& val)
23603 : m_type(value_t::array)
23604 {
23605 m_value.array = create<array_t>(cnt, val);
23606 }
23607
23608 data() noexcept = default;
23609 data(data&&) noexcept = default;
23610 data(const data&) noexcept = delete;
23611 data& operator=(data&&) noexcept = delete;
23612 data& operator=(const data&) noexcept = delete;
23613
23614 ~data() noexcept
23615 {
23616 m_value.destroy(m_type);
23617 }
23618 };
23619
23621
23622#if JSON_DIAGNOSTICS
23624 basic_json* m_parent = nullptr;
23625#endif
23626
23628 // binary serialization/deserialization //
23630
23633
23634 public:
23637 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
23638 {
23639 std::vector<std::uint8_t> result;
23640 to_cbor(j, result);
23641 return result;
23642 }
23643
23647 {
23648 binary_writer<std::uint8_t>(o).write_cbor(j);
23649 }
23650
23654 {
23655 binary_writer<char>(o).write_cbor(j);
23656 }
23657
23660 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
23661 {
23662 std::vector<std::uint8_t> result;
23663 to_msgpack(j, result);
23664 return result;
23665 }
23666
23670 {
23671 binary_writer<std::uint8_t>(o).write_msgpack(j);
23672 }
23673
23677 {
23678 binary_writer<char>(o).write_msgpack(j);
23679 }
23680
23683 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
23684 const bool use_size = false,
23685 const bool use_type = false)
23686 {
23687 std::vector<std::uint8_t> result;
23688 to_ubjson(j, result, use_size, use_type);
23689 return result;
23690 }
23691
23695 const bool use_size = false, const bool use_type = false)
23696 {
23697 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
23698 }
23699
23703 const bool use_size = false, const bool use_type = false)
23704 {
23705 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23706 }
23707
23710 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
23711 const bool use_size = false,
23712 const bool use_type = false)
23713 {
23714 std::vector<std::uint8_t> result;
23715 to_bjdata(j, result, use_size, use_type);
23716 return result;
23717 }
23718
23722 const bool use_size = false, const bool use_type = false)
23723 {
23724 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
23725 }
23726
23730 const bool use_size = false, const bool use_type = false)
23731 {
23732 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
23733 }
23734
23737 static std::vector<std::uint8_t> to_bson(const basic_json& j)
23738 {
23739 std::vector<std::uint8_t> result;
23740 to_bson(j, result);
23741 return result;
23742 }
23743
23747 {
23748 binary_writer<std::uint8_t>(o).write_bson(j);
23749 }
23750
23754 {
23755 binary_writer<char>(o).write_bson(j);
23756 }
23757
23760 template<typename InputType>
23762 static basic_json from_cbor(InputType&& i,
23763 const bool strict = true,
23764 const bool allow_exceptions = true,
23765 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23766 {
23767 basic_json result;
23768 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23769 auto ia = detail::input_adapter(std::forward<InputType>(i));
23770 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23771 return res ? result : basic_json(value_t::discarded);
23772 }
23773
23776 template<typename IteratorType>
23778 static basic_json from_cbor(IteratorType first, IteratorType last,
23779 const bool strict = true,
23780 const bool allow_exceptions = true,
23781 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23782 {
23783 basic_json result;
23784 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23785 auto ia = detail::input_adapter(std::move(first), std::move(last));
23786 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23787 return res ? result : basic_json(value_t::discarded);
23788 }
23789
23790 template<typename T>
23792 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23793 static basic_json from_cbor(const T* ptr, std::size_t len,
23794 const bool strict = true,
23795 const bool allow_exceptions = true,
23796 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23797 {
23798 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23799 }
23800
23802 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23803 static basic_json from_cbor(detail::span_input_adapter&& i,
23804 const bool strict = true,
23805 const bool allow_exceptions = true,
23806 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23807 {
23808 basic_json result;
23809 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23810 auto ia = i.get();
23811 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23812 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23813 return res ? result : basic_json(value_t::discarded);
23814 }
23815
23818 template<typename InputType>
23820 static basic_json from_msgpack(InputType&& i,
23821 const bool strict = true,
23822 const bool allow_exceptions = true)
23823 {
23824 basic_json result;
23825 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23826 auto ia = detail::input_adapter(std::forward<InputType>(i));
23827 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23828 return res ? result : basic_json(value_t::discarded);
23829 }
23830
23833 template<typename IteratorType>
23835 static basic_json from_msgpack(IteratorType first, IteratorType last,
23836 const bool strict = true,
23837 const bool allow_exceptions = true)
23838 {
23839 basic_json result;
23840 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23841 auto ia = detail::input_adapter(std::move(first), std::move(last));
23842 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23843 return res ? result : basic_json(value_t::discarded);
23844 }
23845
23846 template<typename T>
23848 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23849 static basic_json from_msgpack(const T* ptr, std::size_t len,
23850 const bool strict = true,
23851 const bool allow_exceptions = true)
23852 {
23853 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
23854 }
23855
23857 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23858 static basic_json from_msgpack(detail::span_input_adapter&& i,
23859 const bool strict = true,
23860 const bool allow_exceptions = true)
23861 {
23862 basic_json result;
23863 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23864 auto ia = i.get();
23865 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23866 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23867 return res ? result : basic_json(value_t::discarded);
23868 }
23869
23872 template<typename InputType>
23874 static basic_json from_ubjson(InputType&& i,
23875 const bool strict = true,
23876 const bool allow_exceptions = true)
23877 {
23878 basic_json result;
23879 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23880 auto ia = detail::input_adapter(std::forward<InputType>(i));
23881 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23882 return res ? result : basic_json(value_t::discarded);
23883 }
23884
23887 template<typename IteratorType>
23889 static basic_json from_ubjson(IteratorType first, IteratorType last,
23890 const bool strict = true,
23891 const bool allow_exceptions = true)
23892 {
23893 basic_json result;
23894 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23895 auto ia = detail::input_adapter(std::move(first), std::move(last));
23896 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23897 return res ? result : basic_json(value_t::discarded);
23898 }
23899
23900 template<typename T>
23902 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23903 static basic_json from_ubjson(const T* ptr, std::size_t len,
23904 const bool strict = true,
23905 const bool allow_exceptions = true)
23906 {
23907 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
23908 }
23909
23911 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23912 static basic_json from_ubjson(detail::span_input_adapter&& i,
23913 const bool strict = true,
23914 const bool allow_exceptions = true)
23915 {
23916 basic_json result;
23917 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23918 auto ia = i.get();
23919 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23920 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23921 return res ? result : basic_json(value_t::discarded);
23922 }
23923
23926 template<typename InputType>
23928 static basic_json from_bjdata(InputType&& i,
23929 const bool strict = true,
23930 const bool allow_exceptions = true)
23931 {
23932 basic_json result;
23933 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23934 auto ia = detail::input_adapter(std::forward<InputType>(i));
23935 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23936 return res ? result : basic_json(value_t::discarded);
23937 }
23938
23941 template<typename IteratorType>
23943 static basic_json from_bjdata(IteratorType first, IteratorType last,
23944 const bool strict = true,
23945 const bool allow_exceptions = true)
23946 {
23947 basic_json result;
23948 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23949 auto ia = detail::input_adapter(std::move(first), std::move(last));
23950 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23951 return res ? result : basic_json(value_t::discarded);
23952 }
23953
23956 template<typename InputType>
23958 static basic_json from_bson(InputType&& i,
23959 const bool strict = true,
23960 const bool allow_exceptions = true)
23961 {
23962 basic_json result;
23963 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23964 auto ia = detail::input_adapter(std::forward<InputType>(i));
23965 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23966 return res ? result : basic_json(value_t::discarded);
23967 }
23968
23971 template<typename IteratorType>
23973 static basic_json from_bson(IteratorType first, IteratorType last,
23974 const bool strict = true,
23975 const bool allow_exceptions = true)
23976 {
23977 basic_json result;
23978 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23979 auto ia = detail::input_adapter(std::move(first), std::move(last));
23980 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23981 return res ? result : basic_json(value_t::discarded);
23982 }
23983
23984 template<typename T>
23986 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23987 static basic_json from_bson(const T* ptr, std::size_t len,
23988 const bool strict = true,
23989 const bool allow_exceptions = true)
23990 {
23991 return from_bson(ptr, ptr + len, strict, allow_exceptions);
23992 }
23993
23995 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23996 static basic_json from_bson(detail::span_input_adapter&& i,
23997 const bool strict = true,
23998 const bool allow_exceptions = true)
23999 {
24000 basic_json result;
24001 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24002 auto ia = i.get();
24003 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24004 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
24005 return res ? result : basic_json(value_t::discarded);
24006 }
24008
24010 // JSON Pointer support //
24012
24015
24019 {
24020 return ptr.get_unchecked(this);
24021 }
24022
24023 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24024 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24025 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24026 {
24027 return ptr.get_unchecked(this);
24028 }
24029
24033 {
24034 return ptr.get_unchecked(this);
24035 }
24036
24037 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24038 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24039 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24040 {
24041 return ptr.get_unchecked(this);
24042 }
24043
24047 {
24048 return ptr.get_checked(this);
24049 }
24050
24051 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24052 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24053 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24054 {
24055 return ptr.get_checked(this);
24056 }
24057
24061 {
24062 return ptr.get_checked(this);
24063 }
24064
24065 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24066 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24067 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24068 {
24069 return ptr.get_checked(this);
24070 }
24071
24075 {
24076 basic_json result(value_t::object);
24077 json_pointer::flatten("", *this, result);
24078 return result;
24079 }
24080
24084 {
24085 return json_pointer::unflatten(*this);
24086 }
24087
24089
24091 // JSON Patch functions //
24093
24096
24099 void patch_inplace(const basic_json& json_patch)
24100 {
24101 basic_json& result = *this;
24102 // the valid JSON Patch operations
24103 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24104
24105 const auto get_op = [](const std::string & op)
24106 {
24107 if (op == "add")
24108 {
24109 return patch_operations::add;
24110 }
24111 if (op == "remove")
24112 {
24113 return patch_operations::remove;
24114 }
24115 if (op == "replace")
24116 {
24117 return patch_operations::replace;
24118 }
24119 if (op == "move")
24120 {
24121 return patch_operations::move;
24122 }
24123 if (op == "copy")
24124 {
24125 return patch_operations::copy;
24126 }
24127 if (op == "test")
24128 {
24129 return patch_operations::test;
24130 }
24131
24132 return patch_operations::invalid;
24133 };
24134
24135 // wrapper for "add" operation; add value at ptr
24136 const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
24137 {
24138 // adding to the root of the target document means replacing it
24139 if (ptr.empty())
24140 {
24141 result = val;
24142 return;
24143 }
24144
24145 // make sure the top element of the pointer exists
24146 json_pointer const top_pointer = ptr.top();
24147 if (top_pointer != ptr)
24148 {
24149 result.at(top_pointer);
24150 }
24151
24152 // get reference to parent of JSON pointer ptr
24153 const auto last_path = ptr.back();
24154 ptr.pop_back();
24155 // parent must exist when performing patch add per RFC6902 specs
24156 basic_json& parent = result.at(ptr);
24157
24158 switch (parent.m_data.m_type)
24159 {
24160 case value_t::null:
24161 case value_t::object:
24162 {
24163 // use operator[] to add value
24164 parent[last_path] = val;
24165 break;
24166 }
24167
24168 case value_t::array:
24169 {
24170 if (last_path == "-")
24171 {
24172 // special case: append to back
24173 parent.push_back(val);
24174 }
24175 else
24176 {
24177 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24178 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24179 {
24180 // avoid undefined behavior
24181 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24182 }
24183
24184 // default case: insert add offset
24185 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24186 }
24187 break;
24188 }
24189
24190 // if there exists a parent it cannot be primitive
24191 case value_t::string: // LCOV_EXCL_LINE
24192 case value_t::boolean: // LCOV_EXCL_LINE
24193 case value_t::number_integer: // LCOV_EXCL_LINE
24194 case value_t::number_unsigned: // LCOV_EXCL_LINE
24195 case value_t::number_float: // LCOV_EXCL_LINE
24196 case value_t::binary: // LCOV_EXCL_LINE
24197 case value_t::discarded: // LCOV_EXCL_LINE
24198 default: // LCOV_EXCL_LINE
24199 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24200 }
24201 };
24202
24203 // wrapper for "remove" operation; remove value at ptr
24204 const auto operation_remove = [this, & result](json_pointer & ptr)
24205 {
24206 // get reference to parent of JSON pointer ptr
24207 const auto last_path = ptr.back();
24208 ptr.pop_back();
24209 basic_json& parent = result.at(ptr);
24210
24211 // remove child
24212 if (parent.is_object())
24213 {
24214 // perform range check
24215 auto it = parent.find(last_path);
24216 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24217 {
24218 parent.erase(it);
24219 }
24220 else
24221 {
24222 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24223 }
24224 }
24225 else if (parent.is_array())
24226 {
24227 // note erase performs range check
24228 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24229 }
24230 };
24231
24232 // type check: top level value must be an array
24233 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24234 {
24235 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24236 }
24237
24238 // iterate and apply the operations
24239 for (const auto& val : json_patch)
24240 {
24241 // wrapper to get a value for an operation
24242 const auto get_value = [&val](const std::string & op,
24243 const std::string & member,
24244 bool string_type) -> basic_json &
24245 {
24246 // find value
24247 auto it = val.m_data.m_value.object->find(member);
24248
24249 // context-sensitive error message
24250 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
24251
24252 // check if desired value is present
24253 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24254 {
24255 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24256 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24257 }
24258
24259 // check if result is of type string
24260 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24261 {
24262 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24263 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24264 }
24265
24266 // no error: return value
24267 return it->second;
24268 };
24269
24270 // type check: every element of the array must be an object
24271 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24272 {
24273 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24274 }
24275
24276 // collect mandatory members
24277 const auto op = get_value("op", "op", true).template get<std::string>();
24278 const auto path = get_value(op, "path", true).template get<std::string>();
24279 json_pointer ptr(path);
24280
24281 switch (get_op(op))
24282 {
24283 case patch_operations::add:
24284 {
24285 operation_add(ptr, get_value("add", "value", false));
24286 break;
24287 }
24288
24289 case patch_operations::remove:
24290 {
24291 operation_remove(ptr);
24292 break;
24293 }
24294
24295 case patch_operations::replace:
24296 {
24297 // the "path" location must exist - use at()
24298 result.at(ptr) = get_value("replace", "value", false);
24299 break;
24300 }
24301
24302 case patch_operations::move:
24303 {
24304 const auto from_path = get_value("move", "from", true).template get<std::string>();
24305 json_pointer from_ptr(from_path);
24306
24307 // the "from" location must exist - use at()
24308 basic_json const v = result.at(from_ptr);
24309
24310 // The move operation is functionally identical to a
24311 // "remove" operation on the "from" location, followed
24312 // immediately by an "add" operation at the target
24313 // location with the value that was just removed.
24314 operation_remove(from_ptr);
24315 operation_add(ptr, v);
24316 break;
24317 }
24318
24319 case patch_operations::copy:
24320 {
24321 const auto from_path = get_value("copy", "from", true).template get<std::string>();
24322 const json_pointer from_ptr(from_path);
24323
24324 // the "from" location must exist - use at()
24325 basic_json const v = result.at(from_ptr);
24326
24327 // The copy is functionally identical to an "add"
24328 // operation at the target location using the value
24329 // specified in the "from" member.
24330 operation_add(ptr, v);
24331 break;
24332 }
24333
24334 case patch_operations::test:
24335 {
24336 bool success = false;
24337 JSON_TRY
24338 {
24339 // check if "value" matches the one at "path"
24340 // the "path" location must exist - use at()
24341 success = (result.at(ptr) == get_value("test", "value", false));
24342 }
24344 {
24345 // ignore out of range errors: success remains false
24346 }
24347
24348 // throw an exception if test fails
24349 if (JSON_HEDLEY_UNLIKELY(!success))
24350 {
24351 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
24352 }
24353
24354 break;
24355 }
24356
24357 case patch_operations::invalid:
24358 default:
24359 {
24360 // op must be "add", "remove", "replace", "move", "copy", or
24361 // "test"
24362 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
24363 }
24364 }
24365 }
24366 }
24367
24370 basic_json patch(const basic_json& json_patch) const
24371 {
24372 basic_json result = *this;
24373 result.patch_inplace(json_patch);
24374 return result;
24375 }
24376
24380 static basic_json diff(const basic_json& source, const basic_json& target,
24381 const std::string& path = "")
24382 {
24383 // the patch
24384 basic_json result(value_t::array);
24385
24386 // if the values are the same, return empty patch
24387 if (source == target)
24388 {
24389 return result;
24390 }
24391
24392 if (source.type() != target.type())
24393 {
24394 // different types: replace value
24395 result.push_back(
24396 {
24397 {"op", "replace"}, {"path", path}, {"value", target}
24398 });
24399 return result;
24400 }
24401
24402 switch (source.type())
24403 {
24404 case value_t::array:
24405 {
24406 // first pass: traverse common elements
24407 std::size_t i = 0;
24408 while (i < source.size() && i < target.size())
24409 {
24410 // recursive call to compare array values at index i
24411 auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
24412 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24413 ++i;
24414 }
24415
24416 // We now reached the end of at least one array
24417 // in a second pass, traverse the remaining elements
24418
24419 // remove my remaining elements
24420 const auto end_index = static_cast<difference_type>(result.size());
24421 while (i < source.size())
24422 {
24423 // add operations in reverse order to avoid invalid
24424 // indices
24425 result.insert(result.begin() + end_index, object(
24426 {
24427 {"op", "remove"},
24428 {"path", detail::concat(path, '/', std::to_string(i))}
24429 }));
24430 ++i;
24431 }
24432
24433 // add other remaining elements
24434 while (i < target.size())
24435 {
24436 result.push_back(
24437 {
24438 {"op", "add"},
24439 {"path", detail::concat(path, "/-")},
24440 {"value", target[i]}
24441 });
24442 ++i;
24443 }
24444
24445 break;
24446 }
24447
24448 case value_t::object:
24449 {
24450 // first pass: traverse this object's elements
24451 for (auto it = source.cbegin(); it != source.cend(); ++it)
24452 {
24453 // escape the key name to be used in a JSON patch
24454 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24455
24456 if (target.find(it.key()) != target.end())
24457 {
24458 // recursive call to compare object values at key it
24459 auto temp_diff = diff(it.value(), target[it.key()], path_key);
24460 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24461 }
24462 else
24463 {
24464 // found a key that is not in o -> remove it
24465 result.push_back(object(
24466 {
24467 {"op", "remove"}, {"path", path_key}
24468 }));
24469 }
24470 }
24471
24472 // second pass: traverse other object's elements
24473 for (auto it = target.cbegin(); it != target.cend(); ++it)
24474 {
24475 if (source.find(it.key()) == source.end())
24476 {
24477 // found a key that is not in this -> add it
24478 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24479 result.push_back(
24480 {
24481 {"op", "add"}, {"path", path_key},
24482 {"value", it.value()}
24483 });
24484 }
24485 }
24486
24487 break;
24488 }
24489
24490 case value_t::null:
24491 case value_t::string:
24492 case value_t::boolean:
24493 case value_t::number_integer:
24494 case value_t::number_unsigned:
24495 case value_t::number_float:
24496 case value_t::binary:
24497 case value_t::discarded:
24498 default:
24499 {
24500 // both primitive type: replace value
24501 result.push_back(
24502 {
24503 {"op", "replace"}, {"path", path}, {"value", target}
24504 });
24505 break;
24506 }
24507 }
24508
24509 return result;
24510 }
24512
24514 // JSON Merge Patch functions //
24516
24519
24522 void merge_patch(const basic_json& apply_patch)
24523 {
24524 if (apply_patch.is_object())
24525 {
24526 if (!is_object())
24527 {
24528 *this = object();
24529 }
24530 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
24531 {
24532 if (it.value().is_null())
24533 {
24534 erase(it.key());
24535 }
24536 else
24537 {
24538 operator[](it.key()).merge_patch(it.value());
24539 }
24540 }
24541 }
24542 else
24543 {
24544 *this = apply_patch;
24545 }
24546 }
24547
24549};
24550
24555{
24556 return j.dump();
24557}
24558
24559inline namespace literals
24560{
24561inline namespace json_literals
24562{
24563
24567#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24568 inline nlohmann::json operator ""_json(const char* s, std::size_t n)
24569#else
24570 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
24571#endif
24572{
24573 return nlohmann::json::parse(s, s + n);
24574}
24575
24579#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24580 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
24581#else
24582 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
24583#endif
24584{
24585 return nlohmann::json::json_pointer(std::string(s, n));
24586}
24587
24588} // namespace json_literals
24589} // namespace literals
24591
24593// nonmember support //
24595
24596namespace std // NOLINT(cert-dcl58-cpp)
24597{
24598
24602struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
24603{
24604 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
24605 {
24606 return nlohmann::detail::hash(j);
24607 }
24608};
24609
24610// specialization for std::less<value_t>
24611template<>
24612struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
24613{
24618 bool operator()(::nlohmann::detail::value_t lhs,
24619 ::nlohmann::detail::value_t rhs) const noexcept
24620 {
24621#if JSON_HAS_THREE_WAY_COMPARISON
24622 return std::is_lt(lhs <=> rhs); // *NOPAD*
24623#else
24624 return ::nlohmann::detail::operator<(lhs, rhs);
24625#endif
24626 }
24627};
24628
24629// C++20 prohibit function specialization in the std namespace.
24630#ifndef JSON_HAS_CPP_20
24631
24635inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
24636 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
24637 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
24638{
24639 j1.swap(j2);
24640}
24641
24642#endif
24643
24644} // namespace std
24645
24646#if JSON_USE_GLOBAL_UDLS
24647 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24648 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24649 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24650 #else
24651 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24652 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24653 #endif
24654#endif
24655
24656// #include <nlohmann/detail/macro_unscope.hpp>
24657// __ _____ _____ _____
24658// __| | __| | | | JSON for Modern C++
24659// | | |__ | | | | | | version 3.11.3
24660// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24661//
24662// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
24663// SPDX-License-Identifier: MIT
24664
24665
24666
24667// restore clang diagnostic settings
24668#if defined(__clang__)
24669 #pragma clang diagnostic pop
24670#endif
24671
24672// clean up
24673#undef JSON_ASSERT
24674#undef JSON_INTERNAL_CATCH
24675#undef JSON_THROW
24676#undef JSON_PRIVATE_UNLESS_TESTED
24677#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
24678#undef NLOHMANN_BASIC_JSON_TPL
24679#undef JSON_EXPLICIT
24680#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
24681#undef JSON_INLINE_VARIABLE
24682#undef JSON_NO_UNIQUE_ADDRESS
24683#undef JSON_DISABLE_ENUM_SERIALIZATION
24684#undef JSON_USE_GLOBAL_UDLS
24685
24686#ifndef JSON_TEST_KEEP_MACROS
24687 #undef JSON_CATCH
24688 #undef JSON_TRY
24689 #undef JSON_HAS_CPP_11
24690 #undef JSON_HAS_CPP_14
24691 #undef JSON_HAS_CPP_17
24692 #undef JSON_HAS_CPP_20
24693 #undef JSON_HAS_FILESYSTEM
24694 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
24695 #undef JSON_HAS_THREE_WAY_COMPARISON
24696 #undef JSON_HAS_RANGES
24697 #undef JSON_HAS_STATIC_RTTI
24698 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
24699#endif
24700
24701// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
24702// __ _____ _____ _____
24703// __| | __| | | | JSON for Modern C++
24704// | | |__ | | | | | | version 3.11.3
24705// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24706//
24707// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
24708// SPDX-License-Identifier: MIT
24709
24710
24711
24712#undef JSON_HEDLEY_ALWAYS_INLINE
24713#undef JSON_HEDLEY_ARM_VERSION
24714#undef JSON_HEDLEY_ARM_VERSION_CHECK
24715#undef JSON_HEDLEY_ARRAY_PARAM
24716#undef JSON_HEDLEY_ASSUME
24717#undef JSON_HEDLEY_BEGIN_C_DECLS
24718#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
24719#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
24720#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
24721#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
24722#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
24723#undef JSON_HEDLEY_CLANG_HAS_FEATURE
24724#undef JSON_HEDLEY_CLANG_HAS_WARNING
24725#undef JSON_HEDLEY_COMPCERT_VERSION
24726#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
24727#undef JSON_HEDLEY_CONCAT
24728#undef JSON_HEDLEY_CONCAT3
24729#undef JSON_HEDLEY_CONCAT3_EX
24730#undef JSON_HEDLEY_CONCAT_EX
24731#undef JSON_HEDLEY_CONST
24732#undef JSON_HEDLEY_CONSTEXPR
24733#undef JSON_HEDLEY_CONST_CAST
24734#undef JSON_HEDLEY_CPP_CAST
24735#undef JSON_HEDLEY_CRAY_VERSION
24736#undef JSON_HEDLEY_CRAY_VERSION_CHECK
24737#undef JSON_HEDLEY_C_DECL
24738#undef JSON_HEDLEY_DEPRECATED
24739#undef JSON_HEDLEY_DEPRECATED_FOR
24740#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
24741#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
24742#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
24743#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
24744#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
24745#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
24746#undef JSON_HEDLEY_DIAGNOSTIC_POP
24747#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
24748#undef JSON_HEDLEY_DMC_VERSION
24749#undef JSON_HEDLEY_DMC_VERSION_CHECK
24750#undef JSON_HEDLEY_EMPTY_BASES
24751#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
24752#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
24753#undef JSON_HEDLEY_END_C_DECLS
24754#undef JSON_HEDLEY_FLAGS
24755#undef JSON_HEDLEY_FLAGS_CAST
24756#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
24757#undef JSON_HEDLEY_GCC_HAS_BUILTIN
24758#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
24759#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
24760#undef JSON_HEDLEY_GCC_HAS_EXTENSION
24761#undef JSON_HEDLEY_GCC_HAS_FEATURE
24762#undef JSON_HEDLEY_GCC_HAS_WARNING
24763#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
24764#undef JSON_HEDLEY_GCC_VERSION
24765#undef JSON_HEDLEY_GCC_VERSION_CHECK
24766#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
24767#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
24768#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
24769#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
24770#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
24771#undef JSON_HEDLEY_GNUC_HAS_FEATURE
24772#undef JSON_HEDLEY_GNUC_HAS_WARNING
24773#undef JSON_HEDLEY_GNUC_VERSION
24774#undef JSON_HEDLEY_GNUC_VERSION_CHECK
24775#undef JSON_HEDLEY_HAS_ATTRIBUTE
24776#undef JSON_HEDLEY_HAS_BUILTIN
24777#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
24778#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
24779#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
24780#undef JSON_HEDLEY_HAS_EXTENSION
24781#undef JSON_HEDLEY_HAS_FEATURE
24782#undef JSON_HEDLEY_HAS_WARNING
24783#undef JSON_HEDLEY_IAR_VERSION
24784#undef JSON_HEDLEY_IAR_VERSION_CHECK
24785#undef JSON_HEDLEY_IBM_VERSION
24786#undef JSON_HEDLEY_IBM_VERSION_CHECK
24787#undef JSON_HEDLEY_IMPORT
24788#undef JSON_HEDLEY_INLINE
24789#undef JSON_HEDLEY_INTEL_CL_VERSION
24790#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
24791#undef JSON_HEDLEY_INTEL_VERSION
24792#undef JSON_HEDLEY_INTEL_VERSION_CHECK
24793#undef JSON_HEDLEY_IS_CONSTANT
24794#undef JSON_HEDLEY_IS_CONSTEXPR_
24795#undef JSON_HEDLEY_LIKELY
24796#undef JSON_HEDLEY_MALLOC
24797#undef JSON_HEDLEY_MCST_LCC_VERSION
24798#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
24799#undef JSON_HEDLEY_MESSAGE
24800#undef JSON_HEDLEY_MSVC_VERSION
24801#undef JSON_HEDLEY_MSVC_VERSION_CHECK
24802#undef JSON_HEDLEY_NEVER_INLINE
24803#undef JSON_HEDLEY_NON_NULL
24804#undef JSON_HEDLEY_NO_ESCAPE
24805#undef JSON_HEDLEY_NO_RETURN
24806#undef JSON_HEDLEY_NO_THROW
24807#undef JSON_HEDLEY_NULL
24808#undef JSON_HEDLEY_PELLES_VERSION
24809#undef JSON_HEDLEY_PELLES_VERSION_CHECK
24810#undef JSON_HEDLEY_PGI_VERSION
24811#undef JSON_HEDLEY_PGI_VERSION_CHECK
24812#undef JSON_HEDLEY_PREDICT
24813#undef JSON_HEDLEY_PRINTF_FORMAT
24814#undef JSON_HEDLEY_PRIVATE
24815#undef JSON_HEDLEY_PUBLIC
24816#undef JSON_HEDLEY_PURE
24817#undef JSON_HEDLEY_REINTERPRET_CAST
24818#undef JSON_HEDLEY_REQUIRE
24819#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
24820#undef JSON_HEDLEY_REQUIRE_MSG
24821#undef JSON_HEDLEY_RESTRICT
24822#undef JSON_HEDLEY_RETURNS_NON_NULL
24823#undef JSON_HEDLEY_SENTINEL
24824#undef JSON_HEDLEY_STATIC_ASSERT
24825#undef JSON_HEDLEY_STATIC_CAST
24826#undef JSON_HEDLEY_STRINGIFY
24827#undef JSON_HEDLEY_STRINGIFY_EX
24828#undef JSON_HEDLEY_SUNPRO_VERSION
24829#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
24830#undef JSON_HEDLEY_TINYC_VERSION
24831#undef JSON_HEDLEY_TINYC_VERSION_CHECK
24832#undef JSON_HEDLEY_TI_ARMCL_VERSION
24833#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
24834#undef JSON_HEDLEY_TI_CL2000_VERSION
24835#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
24836#undef JSON_HEDLEY_TI_CL430_VERSION
24837#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
24838#undef JSON_HEDLEY_TI_CL6X_VERSION
24839#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
24840#undef JSON_HEDLEY_TI_CL7X_VERSION
24841#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
24842#undef JSON_HEDLEY_TI_CLPRU_VERSION
24843#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
24844#undef JSON_HEDLEY_TI_VERSION
24845#undef JSON_HEDLEY_TI_VERSION_CHECK
24846#undef JSON_HEDLEY_UNAVAILABLE
24847#undef JSON_HEDLEY_UNLIKELY
24848#undef JSON_HEDLEY_UNPREDICTABLE
24849#undef JSON_HEDLEY_UNREACHABLE
24850#undef JSON_HEDLEY_UNREACHABLE_RETURN
24851#undef JSON_HEDLEY_VERSION
24852#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
24853#undef JSON_HEDLEY_VERSION_DECODE_MINOR
24854#undef JSON_HEDLEY_VERSION_DECODE_REVISION
24855#undef JSON_HEDLEY_VERSION_ENCODE
24856#undef JSON_HEDLEY_WARNING
24857#undef JSON_HEDLEY_WARN_UNUSED_RESULT
24858#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
24859#undef JSON_HEDLEY_FALL_THROUGH
24860
24861
24862
24863#endif // INCLUDE_NLOHMANN_JSON_HPP_
namespace for Niels Lohmann
Definition: json.hpp:19499
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:20771
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:22004
reference operator[](KeyType &&key)
access specified object element
Definition: json.hpp:21572
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:22345
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition: json.hpp:23778
static std::vector< std::uint8_t > to_bjdata(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition: json.hpp:23710
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
get a (pointer) value (explicit)
Definition: json.hpp:21144
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition: json.hpp:22202
reference back()
access the last element
Definition: json.hpp:21808
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value from compatible types
Definition: json.hpp:20235
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:22218
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition: json.hpp:24370
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
Definition: json.hpp:23558
const_reference front() const
access the first element
Definition: json.hpp:21801
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:20764
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.hpp:22862
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:21752
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition: json.hpp:22121
iter_impl< const basic_json > const_iterator
a const iterator for a basic_json container
Definition: json.hpp:19630
static void to_bjdata(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition: json.hpp:23729
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition: json.hpp:19574
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:20736
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition: json.hpp:19634
data(size_type cnt, const basic_json &val)
Definition: json.hpp:23602
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition: json.hpp:23973
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)
create a BJData serialization of a given JSON value
Definition: json.hpp:23721
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:24018
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:19625
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:19617
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:20708
const_reference operator[](KeyType &&key) const
access specified object element
Definition: json.hpp:21596
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:19612
void swap(binary_t &other)
exchanges the values
Definition: json.hpp:22939
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:21234
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:22384
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition: json.hpp:22808
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:21245
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:20785
JSON_PRIVATE_UNLESS_TESTED const_reference rhs
Definition: json.hpp:23057
reference operator+=(initializer_list_t init)
add an object to an object
Definition: json.hpp:22600
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:22488
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition: json.hpp:21541
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition: json.hpp:22290
const_reference back() const
access the last element
Definition: json.hpp:21817
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:21899
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:22545
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.hpp:22879
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition: json.hpp:23874
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition: json.hpp:20372
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition: json.hpp:22712
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition: json.hpp:23958
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:19640
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
Definition: json.hpp:19765
reference at(KeyType &&key)
access specified object element with bounds checking
Definition: json.hpp:21404
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:22193
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:20743
void update(const_iterator first, const_iterator last, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition: json.hpp:22815
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition: json.hpp:23737
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:22225
data m_data
Definition: json.hpp:23620
void push_back(initializer_list_t init)
add an object to an object
Definition: json.hpp:22584
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
Definition: json.hpp:20202
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition: json.hpp:20413
ValueType & get_to(ValueType &v) const
Definition: json.hpp:21211
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:23676
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:22168
JSON_PRIVATE_UNLESS_TESTED const_reference bool inverse
Definition: json.hpp:23057
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition: json.hpp:21651
const_iterator cend() const noexcept
returns an iterator to one past the last element
Definition: json.hpp:22209
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition: json.hpp:23928
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:24060
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition: json.hpp:20383
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:20223
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition: json.hpp:23762
basic_json flatten() const
return flattened JSON value
Definition: json.hpp:24074
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition: json.hpp:23889
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition: json.hpp:22015
const binary_t & get_binary() const
get a binary value
Definition: json.hpp:21316
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition: json.hpp:22732
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition: json.hpp:24099
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:21704
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
Definition: json.hpp:24380
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:24032
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition: json.hpp:19741
value_type & reference
the type of an element reference
Definition: json.hpp:19610
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition: json.hpp:22138
static void to_cbor(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a CBOR serialization of a given JSON value
Definition: json.hpp:23646
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
create a BSON serialization of a given JSON value
Definition: json.hpp:23753
iterator find(const typename object_t::key_type &key)
find an element in a JSON object
Definition: json.hpp:22051
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
Definition: json.hpp:20361
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition: json.hpp:21442
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition: json.hpp:19648
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:20420
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition: json.hpp:22065
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition: json.hpp:23637
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:21829
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition: json.hpp:22685
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:19761
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition: json.hpp:21626
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:19620
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:19623
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition: json.hpp:20672
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition: json.hpp:24522
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition: json.hpp:21198
reference operator[](T *key)
Definition: json.hpp:21557
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:21338
iterator find(KeyType &&key)
find an element in a JSON object
Definition: json.hpp:22081
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:20750
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:22232
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition: json.hpp:23683
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:24046
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:19749
detail::value_t value_t
Definition: json.hpp:19564
std::less< StringType > default_object_comparator_t
default object key comparator type The actual object key comparator type (object_comparator_t) may be...
Definition: json.hpp:19728
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:22576
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:22184
reference operator[](typename object_t::key_type key)
access specified object element
Definition: json.hpp:21519
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition: json.hpp:20956
~basic_json() noexcept
destructor
Definition: json.hpp:20654
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:22253
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition: json.hpp:20302
void swap(typename binary_t::container_type &other)
exchanges the values
Definition: json.hpp:22955
binary_t & get_binary()
get a binary value
Definition: json.hpp:21304
const_iterator begin() const noexcept
returns an iterator to the first element
Definition: json.hpp:22177
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:20729
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition: json.hpp:22783
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition: json.hpp:23820
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition: json.hpp:21185
const_reference operator[](T *key) const
Definition: json.hpp:21563
data(const value_t v)
Definition: json.hpp:23597
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:21460
basic_json(const JsonRef &ref)
Definition: json.hpp:20541
JSONSerializer< T, SFINAE > json_serializer
Definition: json.hpp:19568
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value &&std::is_nothrow_move_assignable< json_base_class_t >::value)
copy assignment
Definition: json.hpp:20631
static iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
wrapper to access iterator member functions in range-based for
Definition: json.hpp:22265
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition: json.hpp:23702
Array get_to(T(&v)[N]) const noexcept(noexcept(JSONSerializer< Array >::from_json(std::declval< const basic_json_t & >(), v)))
Definition: json.hpp:21222
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:19753
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition: json.hpp:20945
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:21422
constexpr bool is_binary() const noexcept
return whether value is a binary array
Definition: json.hpp:20778
void swap(object_t &other)
exchanges the values
Definition: json.hpp:22907
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition: json.hpp:24083
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition: json.hpp:22763
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition: json.hpp:20394
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition: json.hpp:22283
bool empty() const noexcept
checks whether the container is empty.
Definition: json.hpp:22306
void swap(array_t &other)
exchanges the values
Definition: json.hpp:22891
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:22022
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:22513
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition: json.hpp:22145
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:20694
reference emplace_back(Args &&... args)
add an object to an array
Definition: json.hpp:22609
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:21727
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition: json.hpp:20405
data() noexcept=default
StringType string_t
a type for a string
Definition: json.hpp:19745
friend class ::nlohmann::detail::parser
Definition: json.hpp:19509
ObjectType< StringType, basic_json, default_object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
Definition: json.hpp:19737
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:22521
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition: json.hpp:21677
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:21384
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition: json.hpp:23943
json_value m_value
the value of the current element
Definition: json.hpp:23595
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:22246
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:20722
size_type count(const typename object_t::key_type &key) const
returns the number of occurrences of a key in a JSON object
Definition: json.hpp:22111
reference front()
access the first element
Definition: json.hpp:21794
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:20701
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:20715
void clear() noexcept
clears the contents
Definition: json.hpp:22427
static void to_ubjson(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition: json.hpp:23694
JSON_PRIVATE_UNLESS_TESTED const_reference bool static SAX bool sax_parse(InputType &&i, SAX *sax, input_format_t format=input_format_t::json, const bool strict=true, const bool ignore_comments=false)
Definition: json.hpp:23482
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:20614
iter_impl< basic_json > iterator
an iterator for a basic_json container
Definition: json.hpp:19628
basic_json(const value_t v)
create an empty value with a given type
Definition: json.hpp:20215
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:21506
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:19615
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition: json.hpp:22705
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition: json.hpp:22239
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:19757
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:23543
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:23660
void swap(string_t &other)
exchanges the values
Definition: json.hpp:22923
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition: json.hpp:20249
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition: json.hpp:19632
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:21361
detail::actual_object_comparator_t< basic_json > object_comparator_t
object key comparator type
Definition: json.hpp:19769
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:20545
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:22553
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition: json.hpp:22634
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
create a CBOR serialization of a given JSON value
Definition: json.hpp:23653
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:20757
static void to_msgpack(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:23669
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition: json.hpp:23835
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition: json.hpp:22666
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:20432
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:23536
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition: json.hpp:22129
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a BSON serialization of a given JSON value
Definition: json.hpp:23746
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition: json.hpp:22097
::nlohmann::json_pointer< StringType > json_pointer
JSON Pointer, see nlohmann::json_pointer.
Definition: json.hpp:19566
an internal type for a backed binary type
Definition: json.hpp:5979
bool operator!=(const byte_container_with_subtype &rhs) const
Definition: json.hpp:6019
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition: json.hpp:5985
std::uint64_t subtype_type
Definition: json.hpp:5982
bool operator==(const byte_container_with_subtype &rhs) const
Definition: json.hpp:6013
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition: json.hpp:6007
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition: json.hpp:5995
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition: json.hpp:6034
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition: json.hpp:6000
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition: json.hpp:6041
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition: json.hpp:5990
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition: json.hpp:6026
void clear_subtype() noexcept
clears the binary subtype
Definition: json.hpp:6048
deserialization of CBOR, MessagePack, and UBJSON values
Definition: json.hpp:9310
binary_reader(const binary_reader &)=delete
binary_reader(binary_reader &&)=default
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition: json.hpp:9326
binary_reader & operator=(const binary_reader &)=delete
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
Definition: json.hpp:9347
binary_reader & operator=(binary_reader &&)=default
serialization to CBOR and MessagePack values
Definition: json.hpp:15177
void write_bson(const BasicJsonType &j)
Definition: json.hpp:15197
static constexpr CharType to_char_type(std::uint8_t x) noexcept
Definition: json.hpp:16932
static CharType to_char_type(std::uint8_t x) noexcept
Definition: json.hpp:16939
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition: json.hpp:15188
static constexpr CharType to_char_type(InputCharType x) noexcept
Definition: json.hpp:16961
void write_ubjson(const BasicJsonType &j, const bool use_count, const bool use_type, const bool add_prefix=true, const bool use_bjdata=false)
Definition: json.hpp:15876
void write_msgpack(const BasicJsonType &j)
Definition: json.hpp:15550
void write_cbor(const BasicJsonType &j)
Definition: json.hpp:15226
general exception of the basic_json class
Definition: json.hpp:4418
const int id
the id of the exception
Definition: json.hpp:4427
static std::string diagnostics(std::nullptr_t)
Definition: json.hpp:4438
static std::string name(const std::string &ename, int id_)
Definition: json.hpp:4433
const char * what() const noexcept override
returns the explanatory string
Definition: json.hpp:4421
static std::string diagnostics(const BasicJsonType *leaf_element)
Definition: json.hpp:4444
file_input_adapter(const file_input_adapter &)=delete
std::char_traits< char >::int_type get_character() noexcept
Definition: json.hpp:6296
file_input_adapter(file_input_adapter &&) noexcept=default
input_stream_adapter & operator=(input_stream_adapter &&)=delete
input_stream_adapter(input_stream_adapter &&rhs) noexcept
Definition: json.hpp:6339
std::char_traits< char >::int_type get_character()
Definition: json.hpp:6349
input_stream_adapter(const input_stream_adapter &)=delete
input_stream_adapter & operator=(input_stream_adapter &)=delete
input_stream_adapter(std::istream &i)
Definition: json.hpp:6330
exception indicating errors with iterators
Definition: json.hpp:4569
static invalid_iterator create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition: json.hpp:4572
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition: json.hpp:13014
~iter_impl()=default
iter_impl operator+(difference_type i) const
add to iterator
Definition: json.hpp:13588
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition: json.hpp:13151
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition: json.hpp:13533
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition: json.hpp:13141
bool operator<(const iter_impl &other) const
comparison: smaller
Definition: json.hpp:13480
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition: json.hpp:13515
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:13579
iter_impl & operator--()
pre-decrement (–it)
Definition: json.hpp:13394
const object_t::key_type & key() const
return the key of an object iterator
Definition: json.hpp:13688
bool operator==(const IterImpl &other) const
comparison: equal
Definition: json.hpp:13435
iter_impl operator++(int) &
post-increment (it++)
Definition: json.hpp:13332
iter_impl & operator+=(difference_type i)
add to iterator
Definition: json.hpp:13542
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:13650
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:13044
pointer operator->() const
dereference the iterator
Definition: json.hpp:13290
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
Definition: json.hpp:13713
difference_type operator-(const iter_impl &other) const
return difference
Definition: json.hpp:13621
iter_impl(iter_impl &&) noexcept=default
std::bidirectional_iterator_tag iterator_category
Definition: json.hpp:13039
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition: json.hpp:13599
reference value() const
return the value of an iterator
Definition: json.hpp:13704
bool operator>(const iter_impl &other) const
comparison: greater than
Definition: json.hpp:13524
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:13048
iter_impl & operator++()
pre-increment (++it)
Definition: json.hpp:13343
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:13042
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:13246
iter_impl operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:13610
iter_impl()=default
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition: json.hpp:13126
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition: json.hpp:13471
iter_impl operator--(int) &
post-decrement (it–)
Definition: json.hpp:13383
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:13053
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition: json.hpp:13116
void set_end() noexcept
set the iterator past the last value
Definition: json.hpp:13207
iteration_proxy_value operator++(int) &
Definition: json.hpp:5313
iteration_proxy_value(iteration_proxy_value const &)=default
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition: json.hpp:5322
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition: json.hpp:5328
std::ptrdiff_t difference_type
Definition: json.hpp:5259
iteration_proxy_value(IteratorType it, std::size_t array_index_=0) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_default_constructible< string_type >::value)
Definition: json.hpp:5280
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition: json.hpp:5305
std::forward_iterator_tag iterator_category
Definition: json.hpp:5263
iteration_proxy_value(iteration_proxy_value &&) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_move_constructible< string_type >::value)=default
IteratorType::reference value() const
return value of the iterator
Definition: json.hpp:5370
const string_type & key() const
return key of the iterator
Definition: json.hpp:5334
iteration_proxy_value & operator=(iteration_proxy_value const &)=default
typename std::remove_cv< typename std::remove_reference< decltype(std::declval< IteratorType >().key()) >::type >::type string_type
Definition: json.hpp:5264
proxy class for the items() function
Definition: json.hpp:5378
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition: json.hpp:5403
iteration_proxy(iteration_proxy const &)=default
iteration_proxy(iteration_proxy &&) noexcept=default
iteration_proxy_value< IteratorType > begin() const noexcept
return iterator begin (needed for range-based for)
Definition: json.hpp:5397
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition: json.hpp:5387
iteration_proxy & operator=(iteration_proxy const &)=default
char_traits< char_type >::int_type get_character()
Definition: json.hpp:6379
iterator_input_adapter(IteratorType first, IteratorType last)
Definition: json.hpp:6375
typename std::iterator_traits< IteratorType >::value_type char_type
Definition: json.hpp:6373
json_ref(json_ref &&) noexcept=default
json_ref(const value_type &value)
Definition: json.hpp:14926
json_ref(value_type &&value)
Definition: json.hpp:14922
value_type const & operator*() const
Definition: json.hpp:14957
value_type const * operator->() const
Definition: json.hpp:14962
json_ref(std::initializer_list< json_ref > init)
Definition: json.hpp:14930
json_ref(Args &&... args)
Definition: json.hpp:14937
value_type moved_or_copied() const
Definition: json.hpp:14948
BasicJsonType value_type
Definition: json.hpp:14920
a template for a reverse iterator class
Definition: json.hpp:13767
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition: json.hpp:13783
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition: json.hpp:13795
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:13789
std::ptrdiff_t difference_type
Definition: json.hpp:13769
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:13807
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:13831
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition: json.hpp:13837
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:13825
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:13773
reference value() const
return the value of an iterator
Definition: json.hpp:13844
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:13780
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:13801
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition: json.hpp:13771
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:13819
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:13776
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:13813
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition: json.hpp:7391
bool start_object(std::size_t=static_cast< std::size_t >(-1))
Definition: json.hpp:7431
bool binary(binary_t &)
Definition: json.hpp:7426
bool number_integer(number_integer_t)
Definition: json.hpp:7406
bool start_array(std::size_t=static_cast< std::size_t >(-1))
Definition: json.hpp:7446
bool number_unsigned(number_unsigned_t)
Definition: json.hpp:7411
bool string(string_t &)
Definition: json.hpp:7421
typename BasicJsonType::binary_t binary_t
Definition: json.hpp:7394
bool number_float(number_float_t, const string_t &)
Definition: json.hpp:7416
bool parse_error(std::size_t, const std::string &, const detail::exception &)
Definition: json.hpp:7456
bool key(string_t &)
Definition: json.hpp:7436
typename BasicJsonType::number_integer_t number_integer_t
Definition: json.hpp:7390
typename BasicJsonType::number_float_t number_float_t
Definition: json.hpp:7392
typename BasicJsonType::string_t string_t
Definition: json.hpp:7393
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition: json.hpp:7269
json_sax_dom_callback_parser(BasicJsonType &r, parser_callback_t cb, const bool allow_exceptions_=true)
Definition: json.hpp:7091
typename BasicJsonType::string_t string_t
Definition: json.hpp:7086
bool number_float(number_float_t val, const string_t &)
Definition: json.hpp:7130
constexpr bool is_errored() const
Definition: json.hpp:7281
bool string(string_t &val)
Definition: json.hpp:7136
json_sax_dom_callback_parser & operator=(const json_sax_dom_callback_parser &)=delete
json_sax_dom_callback_parser(const json_sax_dom_callback_parser &)=delete
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition: json.hpp:7084
typename BasicJsonType::binary_t binary_t
Definition: json.hpp:7087
bool start_object(std::size_t len)
Definition: json.hpp:7148
bool start_array(std::size_t len)
Definition: json.hpp:7219
typename BasicJsonType::number_integer_t number_integer_t
Definition: json.hpp:7083
json_sax_dom_callback_parser(json_sax_dom_callback_parser &&)=default
typename BasicJsonType::parse_event_t parse_event_t
Definition: json.hpp:7089
typename BasicJsonType::parser_callback_t parser_callback_t
Definition: json.hpp:7088
bool number_unsigned(number_unsigned_t val)
Definition: json.hpp:7124
json_sax_dom_callback_parser & operator=(json_sax_dom_callback_parser &&)=default
typename BasicJsonType::number_float_t number_float_t
Definition: json.hpp:7085
bool number_integer(number_integer_t val)
Definition: json.hpp:7118
bool binary(binary_t &val)
Definition: json.hpp:7142
SAX implementation to create a JSON value from SAX events.
Definition: json.hpp:6898
json_sax_dom_parser(const json_sax_dom_parser &)=delete
json_sax_dom_parser & operator=(json_sax_dom_parser &&)=default
bool string(string_t &val)
Definition: json.hpp:6952
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true)
Definition: json.hpp:6911
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition: json.hpp:7019
typename BasicJsonType::string_t string_t
Definition: json.hpp:6903
bool start_object(std::size_t len)
Definition: json.hpp:6964
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition: json.hpp:6901
bool number_unsigned(number_unsigned_t val)
Definition: json.hpp:6940
bool number_integer(number_integer_t val)
Definition: json.hpp:6934
typename BasicJsonType::number_integer_t number_integer_t
Definition: json.hpp:6900
json_sax_dom_parser & operator=(const json_sax_dom_parser &)=delete
bool binary(binary_t &val)
Definition: json.hpp:6958
json_sax_dom_parser(json_sax_dom_parser &&)=default
bool boolean(bool val)
Definition: json.hpp:6928
bool number_float(number_float_t val, const string_t &)
Definition: json.hpp:6946
constexpr bool is_errored() const
Definition: json.hpp:7031
typename BasicJsonType::binary_t binary_t
Definition: json.hpp:6904
typename BasicJsonType::number_float_t number_float_t
Definition: json.hpp:6902
bool start_array(std::size_t len)
Definition: json.hpp:6996
bool key(string_t &val)
Definition: json.hpp:6976
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
Definition: json.hpp:7532
token_type
token types for the parser
Definition: json.hpp:7509
lexical analysis
Definition: json.hpp:7582
bool skip_bom()
skip the UTF-8 byte order mark
Definition: json.hpp:8956
void skip_whitespace()
Definition: json.hpp:8970
lexer(InputAdapterType &&adapter, bool ignore_comments_=false) noexcept
Definition: json.hpp:7593
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition: json.hpp:8943
std::string get_token_string() const
Definition: json.hpp:8918
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition: json.hpp:8882
constexpr position_t get_position() const noexcept
return position of last read token
Definition: json.hpp:8910
token_type scan()
Definition: json.hpp:8979
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition: json.hpp:8888
typename lexer_base< BasicJsonType >::token_type token_type
Definition: json.hpp:7591
lexer(lexer &&)=default
~lexer()=default
lexer & operator=(lexer &&)=default
lexer(const lexer &)=delete
lexer & operator=(lexer &)=delete
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition: json.hpp:8900
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition: json.hpp:8894
exception indicating other library errors
Definition: json.hpp:4621
static other_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition: json.hpp:4624
exception indicating access out of the defined range
Definition: json.hpp:4604
static out_of_range create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition: json.hpp:4607
output_adapter(StringType &s)
Definition: json.hpp:15146
output_adapter(std::basic_ostream< CharType > &s)
Definition: json.hpp:15142
output_adapter(std::vector< CharType, AllocatorType > &vec)
Definition: json.hpp:15138
output adapter for output streams
Definition: json.hpp:15087
output_stream_adapter(std::basic_ostream< CharType > &s) noexcept
Definition: json.hpp:15089
void write_character(CharType c) override
Definition: json.hpp:15093
output adapter for basic_string
Definition: json.hpp:15112
void write_character(CharType c) override
Definition: json.hpp:15118
output_string_adapter(StringType &s) noexcept
Definition: json.hpp:15114
output adapter for byte vectors
Definition: json.hpp:15062
output_vector_adapter(std::vector< CharType, AllocatorType > &vec) noexcept
Definition: json.hpp:15064
void write_character(CharType c) override
Definition: json.hpp:15068
exception indicating a parse error
Definition: json.hpp:4516
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
Definition: json.hpp:4528
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg, BasicJsonContext context)
Definition: json.hpp:4536
const std::size_t byte
byte index of the parse error
Definition: json.hpp:4553
syntax analysis
Definition: json.hpp:12327
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition: json.hpp:12359
bool accept(const bool strict=true)
public accept interface
Definition: json.hpp:12419
parser(InputAdapterType &&adapter, parser_callback_t< BasicJsonType > cb=nullptr, const bool allow_exceptions_=true, const bool skip_comments=false)
a parser reading from an input adapter
Definition: json.hpp:12337
bool sax_parse(SAX *sax, const bool strict=true)
Definition: json.hpp:12427
primitive_iterator_t & operator++() noexcept
Definition: json.hpp:12893
primitive_iterator_t & operator-=(difference_type n) noexcept
Definition: json.hpp:12925
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition: json.hpp:12860
primitive_iterator_t & operator--() noexcept
Definition: json.hpp:12906
void set_end() noexcept
set iterator to a defined past the end
Definition: json.hpp:12854
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition: json.hpp:12876
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition: json.hpp:12866
primitive_iterator_t operator++(int) &noexcept
Definition: json.hpp:12899
primitive_iterator_t & operator+=(difference_type n) noexcept
Definition: json.hpp:12919
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition: json.hpp:12871
constexpr difference_type get_value() const noexcept
Definition: json.hpp:12842
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition: json.hpp:12888
primitive_iterator_t operator+(difference_type n) noexcept
Definition: json.hpp:12881
void set_begin() noexcept
set iterator to a defined beginning
Definition: json.hpp:12848
primitive_iterator_t operator--(int) &noexcept
Definition: json.hpp:12912
std::array< char, 512 > string_buffer
string buffer
Definition: json.hpp:19082
std::uint8_t state
Definition: json.hpp:18500
std::size_t bytes_after_last_accept
Definition: json.hpp:18504
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition: json.hpp:18173
JSON_PRIVATE_UNLESS_TESTED const bool ensure_ascii
Definition: json.hpp:18498
std::size_t undumped_chars
Definition: json.hpp:18505
const char thousands_sep
the locale's thousand separator character
Definition: json.hpp:19077
const char decimal_point
the locale's decimal point character
Definition: json.hpp:19079
serializer & operator=(const serializer &)=delete
~serializer()=default
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition: json.hpp:19090
string_t indent_string
the indentation string
Definition: json.hpp:19087
const std::lconv * loc
the locale
Definition: json.hpp:19075
serializer & operator=(serializer &&)=delete
std::array< char, 64 > number_buffer
a (hopefully) large enough character buffer
Definition: json.hpp:19072
const char indent_char
the indentation character
Definition: json.hpp:19085
std::size_t bytes
Definition: json.hpp:18501
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition: json.hpp:18213
serializer(const serializer &)=delete
serializer(serializer &&)=delete
span_input_adapter(CharT b, std::size_t l)
Definition: json.hpp:6711
span_input_adapter(IteratorType first, IteratorType last)
Definition: json.hpp:6718
contiguous_bytes_input_adapter && get()
Definition: json.hpp:6721
exception indicating executing a member function with a wrong type
Definition: json.hpp:4587
static type_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition: json.hpp:4590
std::char_traits< char >::int_type get_character() noexcept
Definition: json.hpp:6537
wide_string_input_adapter(BaseInputAdapter base)
Definition: json.hpp:6534
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition: json.hpp:13939
friend json_pointer operator/(const json_pointer &lhs, string_t token)
create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
Definition: json.hpp:14034
typename string_t_helper< RefStringType >::type string_t
Definition: json.hpp:13961
friend json_pointer operator/(const json_pointer &lhs, std::size_t array_idx)
create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
Definition: json.hpp:14041
json_pointer(const string_t &s="")
create JSON pointer
Definition: json.hpp:13965
bool empty() const noexcept
return whether pointer points to the root document
Definition: json.hpp:14100
friend bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for equality
Definition: json.hpp:14834
void pop_back()
remove last reference token
Definition: json.hpp:14062
string_t to_string() const
return a string representation of the JSON pointer
Definition: json.hpp:13971
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition: json.hpp:14019
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition: json.hpp:14093
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition: json.hpp:14001
friend json_pointer operator/(const json_pointer &lhs, const json_pointer &rhs)
create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
Definition: json.hpp:14026
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition: json.hpp:14048
friend bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for inequality
Definition: json.hpp:14859
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition: json.hpp:14011
friend class json_pointer
Definition: json.hpp:13945
const string_t & back() const
return last reference token
Definition: json.hpp:14074
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition: json.hpp:13992
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition: json.hpp:14086
friend bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointer for less-than
Definition: json.hpp:14884
decltype(get< N >(std::declval< ::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
Definition: json.hpp:5451
#define B(name, bit)
Definition: cpu.h:216
#define C(name, bit)
Definition: cpu.h:242
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
Definition: json.hpp:2604
#define JSON_HEDLEY_CONST
Definition: json.hpp:1822
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
Definition: json.hpp:1106
#define JSON_INLINE_VARIABLE
Definition: json.hpp:2503
#define JSON_HEDLEY_WARN_UNUSED_RESULT
Definition: json.hpp:1452
#define JSON_PRIVATE_UNLESS_TESTED
Definition: json.hpp:2563
#define NLOHMANN_JSON_VERSION_PATCH
Definition: json.hpp:70
#define JSON_HEDLEY_LIKELY(expr)
Definition: json.hpp:1717
#define JSON_HEDLEY_NON_NULL(...)
Definition: json.hpp:1610
#define JSON_INTERNAL_CATCH(exception)
Definition: json.hpp:2530
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.hpp:24554
#define JSON_HEDLEY_RETURNS_NON_NULL
Definition: json.hpp:2051
bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition: json.hpp:14834
#define JSON_CATCH(exception)
Definition: json.hpp:2529
#define JSON_ASSERT(x)
Definition: json.hpp:2556
#define JSON_THROW(exception)
Definition: json.hpp:2527
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
Definition: json.hpp:77
#define NLOHMANN_JSON_VERSION_MAJOR
Definition: json.hpp:68
#define NLOHMANN_BASIC_JSON_TPL
Definition: json.hpp:2614
#define JSON_HEDLEY_UNLIKELY(expr)
Definition: json.hpp:1718
#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
Definition: json.hpp:12217
#define JSON_TRY
Definition: json.hpp:2528
#define NLOHMANN_JSON_NAMESPACE_END
Definition: json.hpp:144
#define JSON_NO_UNIQUE_ADDRESS
Definition: json.hpp:2509
bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition: json.hpp:14859
#define NLOHMANN_JSON_VERSION_MINOR
Definition: json.hpp:69
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)
Definition: json.hpp:2820
#define NLOHMANN_JSON_NAMESPACE_BEGIN
Definition: json.hpp:134
#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
Definition: json.hpp:12214
#define JSON_HEDLEY_DIAGNOSTIC_POP
Definition: json.hpp:1107
#define JSON_EXPLICIT
Definition: json.hpp:2857
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
Definition: json.hpp:1400
#define JSON_HEDLEY_PURE
Definition: json.hpp:1791
bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition: json.hpp:14884
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)
Definition: json.hpp:22980
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
Definition: json.hpp:17497
cached_power get_cached_power_for_binary_exponent(int e)
Definition: json.hpp:17333
Target reinterpret_bits(const Source source)
Definition: json.hpp:17053
boundaries compute_boundaries(FloatType value)
Definition: json.hpp:17194
void grisu2_round(char *buf, int len, std::uint64_t dist, std::uint64_t delta, std::uint64_t rest, std::uint64_t ten_k)
Definition: json.hpp:17551
constexpr int kAlpha
Definition: json.hpp:17316
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition: json.hpp:17833
constexpr int kGamma
Definition: json.hpp:17317
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition: json.hpp:17592
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition: json.hpp:17933
JSON_HEDLEY_RETURNS_NON_NULL char * format_buffer(char *buf, int len, int decimal_exponent, int min_exp, int max_exp)
prettify v = buf * 10^decimal_exponent
Definition: json.hpp:17985
constexpr bool is_transparent()
Definition: json.hpp:4228
constexpr bool is_c_string()
Definition: json.hpp:4200
detail namespace with internal helper functions
Definition: json.hpp:253
input_format_t
the supported input formats
Definition: json.hpp:6266
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
Definition: json.hpp:5868
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
Definition: json.hpp:313
typename make_void< Ts... >::type void_t
Definition: json.hpp:259
decltype(std::declval< T & >().start_array(std::declval< std::size_t >())) start_array_function_t
Definition: json.hpp:9172
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition: json.hpp:15057
decltype(std::declval< StringType & >()+=std::declval< Arg && >()) string_can_append_op
Definition: json.hpp:4309
decltype(std::declval< T & >().parse_error(std::declval< std::size_t >(), std::declval< const std::string & >(), std::declval< const Exception & >())) parse_error_function_t
Definition: json.hpp:9180
std::function< bool(int, parse_event_t, BasicJsonType &)> parser_callback_t
Definition: json.hpp:12318
OutStringType concat(Args &&... args)
Definition: json.hpp:4383
is_detected< string_can_append_iter, StringType, Arg > detect_string_can_append_iter
Definition: json.hpp:4318
decltype(T::to_json(std::declval< Args >()...)) to_json_function
Definition: json.hpp:3551
constexpr std::array< T, sizeof...(Args)> make_array(Args &&... args)
Definition: json.hpp:3256
decltype(std::declval< T >().template get< U >()) get_template_function
Definition: json.hpp:3557
typename std::conditional< is_usable_as_key_type< typename BasicJsonType::object_comparator_t, typename BasicJsonType::object_t::key_type, KeyTypeCVRef, RequireTransparentComparator, ExcludeObjectKeyType >::value &&!is_json_iterator_of< BasicJsonType, KeyType >::value, std::true_type, std::false_type >::type is_usable_as_basic_json_key_type
Definition: json.hpp:4050
JSON_HEDLEY_RETURNS_NON_NULL char * to_chars(char *first, const char *last, FloatType value)
generates a decimal representation of the floating-point number value in [first, last).
Definition: json.hpp:18070
typename T::pointer pointer_t
Definition: json.hpp:3542
parse_event_t
Definition: json.hpp:12301
@ 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.hpp:4312
std::pair< A1, A2 > from_json_tuple_impl(BasicJsonType &&j, identity_tag< std::pair< A1, A2 > >, priority_tag< 0 >)
Definition: json.hpp:5078
void from_json_array_impl(const BasicJsonType &j, typename BasicJsonType::array_t &arr, priority_tag< 3 >)
Definition: json.hpp:4889
typename utility_internal::Gen< T, N >::type make_integer_sequence
Definition: json.hpp:3217
typename T::value_type value_type_t
Definition: json.hpp:3536
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
Definition: json.hpp:317
T conditional_static_cast(U value)
Definition: json.hpp:4084
is_detected< string_can_append_data, StringType, Arg > detect_string_can_append_data
Definition: json.hpp:4324
typename std::enable_if< B, T >::type enable_if_t
Definition: json.hpp:3129
decltype(std::declval< T & >().number_integer(std::declval< Integer >())) number_integer_function_t
Definition: json.hpp:9141
typename T::mapped_type mapped_type_t
Definition: json.hpp:3530
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition: json.hpp:3005
decltype(std::declval< T & >().number_float(std::declval< Float >(), std::declval< const String & >())) number_float_function_t
Definition: json.hpp:9149
enable_if_t< is_range< R >::value, result_of_begin< decltype(std::declval< R & >())> > iterator_t
Definition: json.hpp:3778
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.hpp:5413
cbor_tag_handler_t
how to treat CBOR tags
Definition: json.hpp:9283
@ 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.hpp:310
decltype(T::from_json(std::declval< Args >()...)) from_json_function
Definition: json.hpp:3554
decltype(input_adapter(std::declval< const char * >(), std::declval< const char * >())) contiguous_bytes_input_adapter
Definition: json.hpp:6672
make_integer_sequence< size_t, N > make_index_sequence
Definition: json.hpp:3225
std::integral_constant< bool, Value > bool_constant
Definition: json.hpp:4190
void concat_into(OutStringType &)
Definition: json.hpp:4299
typename T::key_type key_type_t
Definition: json.hpp:3533
constexpr bool value_in_range_of(T val)
Definition: json.hpp:4184
value_t
the JSON type enumeration
Definition: json.hpp:2907
@ 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.hpp:4107
decltype(std::declval< T & >().binary(std::declval< Binary & >())) binary_function_t
Definition: json.hpp:9157
std::array< T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType &&j, identity_tag< std::array< T, sizeof...(Idx)> >, index_sequence< Idx... >)
Definition: json.hpp:4972
typename detector< nonesuch, void, Op, Args... >::type detected_t
Definition: json.hpp:304
typename std::conditional< is_comparable< Comparator, ObjectKeyType, KeyTypeCVRef >::value &&!(ExcludeObjectKeyType &&std::is_same< KeyType, ObjectKeyType >::value) &&(!RequireTransparentComparator||is_detected< detect_is_transparent, Comparator >::value) &&!is_json_pointer< KeyType >::value, std::true_type, std::false_type >::type is_usable_as_key_type
Definition: json.hpp:4034
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition: json.hpp:6110
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().begin(), std::declval< const Arg & >().end())) string_can_append_iter
Definition: json.hpp:4315
typename T::iterator_category iterator_category_t
Definition: json.hpp:3548
std::size_t combine(std::size_t seed, std::size_t h) noexcept
Definition: json.hpp:6092
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:2936
iterator_input_adapter_factory< IteratorType >::adapter_type input_adapter(IteratorType first, IteratorType last)
Definition: json.hpp:6611
decltype(std::declval< T & >().end_array()) end_array_function_t
Definition: json.hpp:9175
typename std::conditional< is_detected< detect_erase_with_key_type, typename BasicJsonType::object_t, KeyType >::value, std::true_type, std::false_type >::type has_erase_with_key_type
Definition: json.hpp:4062
error_handler_t
how to treat decoding errors
Definition: json.hpp:18150
@ strict
throw a type_error exception in case of invalid UTF-8
@ ignore
ignore invalid UTF-8 sequences
@ replace
replace invalid UTF-8 sequences with U+FFFD
std::size_t concat_length()
Definition: json.hpp:4268
value_type_t< iterator_traits< iterator_t< T > > > range_value_t
Definition: json.hpp:3781
void from_json(const BasicJsonType &j, typename std::nullptr_t &n)
Definition: json.hpp:4714
typename actual_object_comparator< BasicJsonType >::type actual_object_comparator_t
Definition: json.hpp:3630
decltype(std::declval< StringType & >().append(std::declval< Arg && >())) string_can_append
Definition: json.hpp:4303
void to_json(BasicJsonType &j, T b) noexcept
Definition: json.hpp:5729
void get_arithmetic_value(const BasicJsonType &j, ArithmeticType &val)
Definition: json.hpp:4746
decltype(std::declval< T & >().null()) null_function_t
Definition: json.hpp:9133
make_index_sequence< sizeof...(Ts)> index_sequence_for
Definition: json.hpp:3233
typename T::difference_type difference_type_t
Definition: json.hpp:3539
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition: json.hpp:3115
std::tuple< Args... > from_json_tuple_impl_base(BasicJsonType &&j, index_sequence< Idx... >)
Definition: json.hpp:5072
typename T::is_transparent detect_is_transparent
Definition: json.hpp:4020
decltype(std::declval< T & >().string(std::declval< String & >())) string_function_t
Definition: json.hpp:9153
typename std::conditional< std::is_same< T, void >::value, json_default_base, T >::type json_base_class
Definition: json.hpp:13893
typename T::reference reference_t
Definition: json.hpp:3545
decltype(std::declval< T & >().boolean(std::declval< bool >())) boolean_function_t
Definition: json.hpp:9137
decltype(std::declval< T & >().end_object()) end_object_function_t
Definition: json.hpp:9168
decltype(std::declval< ObjectType & >().erase(std::declval< KeyType >())) detect_erase_with_key_type
Definition: json.hpp:4053
typename T::key_compare detect_key_compare
Definition: json.hpp:3614
decltype(std::declval< T & >().start_object(std::declval< std::size_t >())) start_object_function_t
Definition: json.hpp:9161
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().data(), std::declval< const Arg & >().size())) string_can_append_data
Definition: json.hpp:4321
decltype(std::declval< T & >().number_unsigned(std::declval< Unsigned >())) number_unsigned_function_t
Definition: json.hpp:9145
typename detector< nonesuch, void, Op, Args... >::value_t is_detected
Definition: json.hpp:298
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition: json.hpp:3024
void int_to_string(string_type &target, std::size_t value)
Definition: json.hpp:5250
std::integral_constant< bool,(std::is_signed< OfType >::value &&(sizeof(T)< sizeof(OfType)))||(same_sign< OfType, T >::value &&sizeof(OfType)==sizeof(T)) > never_out_of_range
Definition: json.hpp:4112
is_detected< string_can_append, StringType, Arg > detect_string_can_append
Definition: json.hpp:4306
decltype(std::declval< T & >().key(std::declval< String & >())) key_function_t
Definition: json.hpp:9165
void accept(sys::state &state, message const &m)
uint32_t size(sys::state const &state)
void reset(file_system &fs)
Definition: json.hpp:5434
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition: json.hpp:24635
element_type
uint uint32_t
ulong uint64_t
token_type
namespace for Niels Lohmann
Definition: json.hpp:5921
static auto to_json(BasicJsonType &j, TargetType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< TargetType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< TargetType >(val)), void())
convert any value type to a JSON value
Definition: json.hpp:5945
static auto from_json(BasicJsonType &&j) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))
convert a JSON value to any value type
Definition: json.hpp:5935
static auto from_json(BasicJsonType &&j, TargetType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
Definition: json.hpp:5925
typename BasicJsonType::object_t object_t
Definition: json.hpp:3623
typename BasicJsonType::default_object_comparator_t object_comparator_t
Definition: json.hpp:3624
typename std::conditional< has_key_compare< object_t >::value, typename object_t::key_compare, object_comparator_t >::type type
Definition: json.hpp:3626
static constexpr int_type eof() noexcept
Definition: json.hpp:3683
static char_type to_char_type(int_type i) noexcept
Definition: json.hpp:3678
static int_type to_int_type(char_type c) noexcept
Definition: json.hpp:3673
static char_type to_char_type(int_type i) noexcept
Definition: json.hpp:3654
static constexpr int_type eof() noexcept
Definition: json.hpp:3659
static int_type to_int_type(char_type c) noexcept
Definition: json.hpp:3649
std::false_type value_t
Definition: json.hpp:286
Default type
Definition: json.hpp:287
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition: json.hpp:17087
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
Definition: json.hpp:17169
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition: json.hpp:17152
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition: json.hpp:17075
constexpr diyfp(std::uint64_t f_, int e_) noexcept
Definition: json.hpp:17069
static constexpr int kPrecision
Definition: json.hpp:17064
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
Definition: json.hpp:5638
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
Definition: json.hpp:5613
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
Definition: json.hpp:5603
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
Definition: json.hpp:5625
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
Definition: json.hpp:5654
static void construct(BasicJsonType &j, const typename BasicJsonType::binary_t &b)
Definition: json.hpp:5542
static void construct(BasicJsonType &j, typename BasicJsonType::binary_t &&b)
Definition: json.hpp:5551
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
Definition: json.hpp:5496
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
Definition: json.hpp:5564
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
Definition: json.hpp:5590
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
Definition: json.hpp:5577
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
Definition: json.hpp:5673
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
Definition: json.hpp:5694
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
Definition: json.hpp:5683
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
Definition: json.hpp:5518
static void construct(BasicJsonType &j, const CompatibleStringType &str)
Definition: json.hpp:5529
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
Definition: json.hpp:5509
auto operator()(const BasicJsonType &j, T &&val) const noexcept(noexcept(from_json(j, std::forward< T >(val)))) -> decltype(from_json(j, std::forward< T >(val)))
Definition: json.hpp:5169
typename BasicJsonType::template json_serializer< T, void > serializer
Definition: json.hpp:3576
typename BasicJsonType::template json_serializer< T, void > serializer
Definition: json.hpp:3591
typename BasicJsonType::template json_serializer< T, void > serializer
Definition: json.hpp:3606
static constexpr std::size_t size() noexcept
Definition: json.hpp:3159
an iterator value
Definition: json.hpp:12947
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition: json.hpp:12951
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition: json.hpp:12953
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition: json.hpp:12949
static constexpr auto value
Definition: json.hpp:3853
ConstructibleStringType laundered_type
Definition: json.hpp:3864
static constexpr auto value
Definition: json.hpp:3867
static constexpr bool value
Definition: json.hpp:3570
typename std::iterator_traits< T >::value_type value_type
Definition: json.hpp:6588
static one test(decltype(&C::capacity))
static two test(...)
static constexpr bool value
Definition: json.hpp:3774
static constexpr bool value
Definition: json.hpp:9197
iterator_input_adapter< iterator_type > adapter_type
Definition: json.hpp:6577
typename std::iterator_traits< iterator_type >::value_type char_type
Definition: json.hpp:6576
static adapter_type create(IteratorType first, IteratorType last)
Definition: json.hpp:6579
Default base class of the basic_json class.
Definition: json.hpp:13886
nonesuch(nonesuch const &&)=delete
~nonesuch()=delete
void operator=(nonesuch &&)=delete
void operator=(nonesuch const &)=delete
nonesuch(nonesuch const &)=delete
abstract output adapter interface
Definition: json.hpp:15043
output_adapter_protocol(const output_adapter_protocol &)=default
virtual ~output_adapter_protocol()=default
virtual void write_character(CharType c)=0
output_adapter_protocol(output_adapter_protocol &&) noexcept=default
virtual void write_characters(const CharType *s, std::size_t length)=0
struct to capture the start position of the current token
Definition: json.hpp:3070
std::size_t chars_read_current_line
the number of characters read in the current line
Definition: json.hpp:3074
std::size_t lines_read
the number of lines read
Definition: json.hpp:3076
std::size_t chars_read_total
the total number of characters read
Definition: json.hpp:3072
static JSON_INLINE_VARIABLE constexpr T value
Definition: json.hpp:3247
auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward< T >(val)))) -> decltype(to_json(j, std::forward< T >(val)), void())
Definition: json.hpp:5890
typename Extend< typename Gen< T, N/2 >::type, N/2, N % 2 >::type type
Definition: json.hpp:3198
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition: json.hpp:6469
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition: json.hpp:6411
SAX interface.
Definition: json.hpp:6768
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
json_sax()=default
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
typename BasicJsonType::number_integer_t number_integer_t
Definition: json.hpp:6769
typename BasicJsonType::string_t string_t
Definition: json.hpp:6772
virtual bool end_array()=0
the end of an array was read
json_sax(const json_sax &)=default
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
typename BasicJsonType::number_float_t number_float_t
Definition: json.hpp:6771
virtual bool null()=0
a null value was read
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition: json.hpp:6770
json_sax(json_sax &&) noexcept=default
typename BasicJsonType::binary_t binary_t
Definition: json.hpp:6773
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
a minimal map-like container that preserves insertion order
Definition: json.hpp:19132
std::vector< std::pair< const Key, T >, Allocator > Container
Definition: json.hpp:19135
std::pair< iterator, bool > insert(value_type &&value)
Definition: json.hpp:19426
typename Container::value_type value_type
Definition: json.hpp:19139
std::equal_to< Key > key_compare
Definition: json.hpp:19143
iterator erase(iterator pos)
Definition: json.hpp:19304
ordered_map(const Allocator &alloc) noexcept(noexcept(Container(alloc)))
Definition: json.hpp:19149
T & operator[](KeyType &&key)
Definition: json.hpp:19191
typename Container::iterator iterator
Definition: json.hpp:19136
const T & at(KeyType &&key) const
Definition: json.hpp:19251
T & at(KeyType &&key)
Definition: json.hpp:19223
const T & operator[](KeyType &&key) const
Definition: json.hpp:19203
iterator find(const key_type &key)
Definition: json.hpp:19388
iterator erase(iterator first, iterator last)
Definition: json.hpp:19309
const T & at(const key_type &key) const
Definition: json.hpp:19236
const_iterator find(const key_type &key) const
Definition: json.hpp:19414
T & operator[](const key_type &key)
Definition: json.hpp:19184
size_type erase(KeyType &&key)
Definition: json.hpp:19285
typename Container::size_type size_type
Definition: json.hpp:19138
ordered_map() noexcept(noexcept(Container()))
Definition: json.hpp:19148
void insert(InputIt first, InputIt last)
Definition: json.hpp:19449
size_type count(const key_type &key) const
Definition: json.hpp:19362
std::pair< iterator, bool > emplace(KeyType &&key, T &&t)
Definition: json.hpp:19171
size_type erase(const key_type &key)
Definition: json.hpp:19264
ordered_map(std::initializer_list< value_type > init, const Allocator &alloc=Allocator())
Definition: json.hpp:19153
std::pair< iterator, bool > insert(const value_type &value)
Definition: json.hpp:19431
size_type count(KeyType &&key) const
Definition: json.hpp:19376
Key key_type
Definition: json.hpp:19133
ordered_map(It first, It last, const Allocator &alloc=Allocator())
Definition: json.hpp:19151
typename std::enable_if< std::is_convertible< typename std::iterator_traits< InputIt >::iterator_category, std::input_iterator_tag >::value >::type require_input_iter
Definition: json.hpp:19446
const T & operator[](const key_type &key) const
Definition: json.hpp:19196
iterator find(KeyType &&key)
Definition: json.hpp:19402
T & at(const key_type &key)
Definition: json.hpp:19208
typename Container::const_iterator const_iterator
Definition: json.hpp:19137
std::pair< iterator, bool > emplace(const key_type &key, T &&t)
Definition: json.hpp:19156
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL &j) const
Definition: json.hpp:24604
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition: json.hpp:24618