Clutter Engine 0.0.1
Loading...
Searching...
No Matches
json.h
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#include <string> // string
166#include <tuple> // tuple, make_tuple
167#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
168#include <unordered_map> // unordered_map
169#include <utility> // pair, declval
170#include <valarray> // valarray
171
172// #include <nlohmann/detail/exceptions.hpp>
173// __ _____ _____ _____
174// __| | __| | | | JSON for Modern C++
175// | | |__ | | | | | | version 3.11.3
176// |_____|_____|_____|_|___| https://github.com/nlohmann/json
177//
178// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
179// SPDX-License-Identifier: MIT
180
181
182
183#include <cstddef> // nullptr_t
184#include <exception> // exception
185#if JSON_DIAGNOSTICS
186 #include <numeric> // accumulate
187#endif
188#include <stdexcept> // runtime_error
189#include <string> // to_string
190#include <vector> // vector
191
192// #include <nlohmann/detail/value_t.hpp>
193// __ _____ _____ _____
194// __| | __| | | | JSON for Modern C++
195// | | |__ | | | | | | version 3.11.3
196// |_____|_____|_____|_|___| https://github.com/nlohmann/json
197//
198// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
199// SPDX-License-Identifier: MIT
200
201
202
203#include <array> // array
204#include <cstddef> // size_t
205#include <cstdint> // uint8_t
206#include <string> // string
207
208// #include <nlohmann/detail/macro_scope.hpp>
209// __ _____ _____ _____
210// __| | __| | | | JSON for Modern C++
211// | | |__ | | | | | | version 3.11.3
212// |_____|_____|_____|_|___| https://github.com/nlohmann/json
213//
214// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
215// SPDX-License-Identifier: MIT
216
217
218
219#include <utility> // declval, pair
220// #include <nlohmann/detail/meta/detected.hpp>
221// __ _____ _____ _____
222// __| | __| | | | JSON for Modern C++
223// | | |__ | | | | | | version 3.11.3
224// |_____|_____|_____|_|___| https://github.com/nlohmann/json
225//
226// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
227// SPDX-License-Identifier: MIT
228
229
230
231#include <type_traits>
232
233// #include <nlohmann/detail/meta/void_t.hpp>
234// __ _____ _____ _____
235// __| | __| | | | JSON for Modern C++
236// | | |__ | | | | | | version 3.11.3
237// |_____|_____|_____|_|___| https://github.com/nlohmann/json
238//
239// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
240// SPDX-License-Identifier: MIT
241
242
243
244// #include <nlohmann/detail/abi_macros.hpp>
245
246
247NLOHMANN_JSON_NAMESPACE_BEGIN
248namespace detail
249{
250
251template<typename ...Ts> struct make_void
252{
253 using type = void;
254};
255template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
256
257} // namespace detail
258NLOHMANN_JSON_NAMESPACE_END
259
260
261NLOHMANN_JSON_NAMESPACE_BEGIN
262namespace detail
263{
264
265// https://en.cppreference.com/w/cpp/experimental/is_detected
266struct nonesuch
267{
268 nonesuch() = delete;
269 ~nonesuch() = delete;
270 nonesuch(nonesuch const&) = delete;
271 nonesuch(nonesuch const&&) = delete;
272 void operator=(nonesuch const&) = delete;
273 void operator=(nonesuch&&) = delete;
274};
275
276template<class Default,
277 class AlwaysVoid,
278 template<class...> class Op,
279 class... Args>
280struct detector
281{
282 using value_t = std::false_type;
283 using type = Default;
284};
285
286template<class Default, template<class...> class Op, class... Args>
287struct detector<Default, void_t<Op<Args...>>, Op, Args...>
288{
289 using value_t = std::true_type;
290 using type = Op<Args...>;
291};
292
293template<template<class...> class Op, class... Args>
294using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
295
296template<template<class...> class Op, class... Args>
297struct is_detected_lazy : is_detected<Op, Args...> { };
298
299template<template<class...> class Op, class... Args>
300using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
301
302template<class Default, template<class...> class Op, class... Args>
303using detected_or = detector<Default, void, Op, Args...>;
304
305template<class Default, template<class...> class Op, class... Args>
306using detected_or_t = typename detected_or<Default, Op, Args...>::type;
307
308template<class Expected, template<class...> class Op, class... Args>
309using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
310
311template<class To, template<class...> class Op, class... Args>
312using is_detected_convertible =
313 std::is_convertible<detected_t<Op, Args...>, To>;
314
315} // namespace detail
316NLOHMANN_JSON_NAMESPACE_END
317
318// #include <nlohmann/thirdparty/hedley/hedley.hpp>
319
320
321// __ _____ _____ _____
322// __| | __| | | | JSON for Modern C++
323// | | |__ | | | | | | version 3.11.3
324// |_____|_____|_____|_|___| https://github.com/nlohmann/json
325//
326// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
327// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com>
328// SPDX-License-Identifier: MIT
329
330/* Hedley - https://nemequ.github.io/hedley
331 * Created by Evan Nemerson <evan@nemerson.com>
332 */
333
334#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
335#if defined(JSON_HEDLEY_VERSION)
336 #undef JSON_HEDLEY_VERSION
337#endif
338#define JSON_HEDLEY_VERSION 15
339
340#if defined(JSON_HEDLEY_STRINGIFY_EX)
341 #undef JSON_HEDLEY_STRINGIFY_EX
342#endif
343#define JSON_HEDLEY_STRINGIFY_EX(x) #x
344
345#if defined(JSON_HEDLEY_STRINGIFY)
346 #undef JSON_HEDLEY_STRINGIFY
347#endif
348#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
349
350#if defined(JSON_HEDLEY_CONCAT_EX)
351 #undef JSON_HEDLEY_CONCAT_EX
352#endif
353#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
354
355#if defined(JSON_HEDLEY_CONCAT)
356 #undef JSON_HEDLEY_CONCAT
357#endif
358#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
359
360#if defined(JSON_HEDLEY_CONCAT3_EX)
361 #undef JSON_HEDLEY_CONCAT3_EX
362#endif
363#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
364
365#if defined(JSON_HEDLEY_CONCAT3)
366 #undef JSON_HEDLEY_CONCAT3
367#endif
368#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
369
370#if defined(JSON_HEDLEY_VERSION_ENCODE)
371 #undef JSON_HEDLEY_VERSION_ENCODE
372#endif
373#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
374
375#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
376 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
377#endif
378#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
379
380#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
381 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
382#endif
383#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
384
385#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
386 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
387#endif
388#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
389
390#if defined(JSON_HEDLEY_GNUC_VERSION)
391 #undef JSON_HEDLEY_GNUC_VERSION
392#endif
393#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
394 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
395#elif defined(__GNUC__)
396 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
397#endif
398
399#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
400 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
401#endif
402#if defined(JSON_HEDLEY_GNUC_VERSION)
403 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
404#else
405 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
406#endif
407
408#if defined(JSON_HEDLEY_MSVC_VERSION)
409 #undef JSON_HEDLEY_MSVC_VERSION
410#endif
411#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
412 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
413#elif defined(_MSC_FULL_VER) && !defined(__ICL)
414 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
415#elif defined(_MSC_VER) && !defined(__ICL)
416 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
417#endif
418
419#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
420 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
421#endif
422#if !defined(JSON_HEDLEY_MSVC_VERSION)
423 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
424#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
425 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
426#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
427 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
428#else
429 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
430#endif
431
432#if defined(JSON_HEDLEY_INTEL_VERSION)
433 #undef JSON_HEDLEY_INTEL_VERSION
434#endif
435#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
436 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
437#elif defined(__INTEL_COMPILER) && !defined(__ICL)
438 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
439#endif
440
441#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
442 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
443#endif
444#if defined(JSON_HEDLEY_INTEL_VERSION)
445 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
446#else
447 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
448#endif
449
450#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
451 #undef JSON_HEDLEY_INTEL_CL_VERSION
452#endif
453#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
454 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
455#endif
456
457#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
458 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
459#endif
460#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
461 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
462#else
463 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
464#endif
465
466#if defined(JSON_HEDLEY_PGI_VERSION)
467 #undef JSON_HEDLEY_PGI_VERSION
468#endif
469#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
470 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
471#endif
472
473#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
474 #undef JSON_HEDLEY_PGI_VERSION_CHECK
475#endif
476#if defined(JSON_HEDLEY_PGI_VERSION)
477 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
478#else
479 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
480#endif
481
482#if defined(JSON_HEDLEY_SUNPRO_VERSION)
483 #undef JSON_HEDLEY_SUNPRO_VERSION
484#endif
485#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
486 #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)
487#elif defined(__SUNPRO_C)
488 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
489#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
490 #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)
491#elif defined(__SUNPRO_CC)
492 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
493#endif
494
495#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
496 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
497#endif
498#if defined(JSON_HEDLEY_SUNPRO_VERSION)
499 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
500#else
501 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
502#endif
503
504#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
505 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
506#endif
507#if defined(__EMSCRIPTEN__)
508 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
509#endif
510
511#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
512 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
513#endif
514#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
515 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
516#else
517 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
518#endif
519
520#if defined(JSON_HEDLEY_ARM_VERSION)
521 #undef JSON_HEDLEY_ARM_VERSION
522#endif
523#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
524 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
525#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
526 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
527#endif
528
529#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
530 #undef JSON_HEDLEY_ARM_VERSION_CHECK
531#endif
532#if defined(JSON_HEDLEY_ARM_VERSION)
533 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
534#else
535 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
536#endif
537
538#if defined(JSON_HEDLEY_IBM_VERSION)
539 #undef JSON_HEDLEY_IBM_VERSION
540#endif
541#if defined(__ibmxl__)
542 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
543#elif defined(__xlC__) && defined(__xlC_ver__)
544 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
545#elif defined(__xlC__)
546 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
547#endif
548
549#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
550 #undef JSON_HEDLEY_IBM_VERSION_CHECK
551#endif
552#if defined(JSON_HEDLEY_IBM_VERSION)
553 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
554#else
555 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
556#endif
557
558#if defined(JSON_HEDLEY_TI_VERSION)
559 #undef JSON_HEDLEY_TI_VERSION
560#endif
561#if \
562 defined(__TI_COMPILER_VERSION__) && \
563 ( \
564 defined(__TMS470__) || defined(__TI_ARM__) || \
565 defined(__MSP430__) || \
566 defined(__TMS320C2000__) \
567 )
568#if (__TI_COMPILER_VERSION__ >= 16000000)
569 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
570#endif
571#endif
572
573#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
574 #undef JSON_HEDLEY_TI_VERSION_CHECK
575#endif
576#if defined(JSON_HEDLEY_TI_VERSION)
577 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
578#else
579 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
580#endif
581
582#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
583 #undef JSON_HEDLEY_TI_CL2000_VERSION
584#endif
585#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
586 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
587#endif
588
589#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
590 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
591#endif
592#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
593 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
594#else
595 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
596#endif
597
598#if defined(JSON_HEDLEY_TI_CL430_VERSION)
599 #undef JSON_HEDLEY_TI_CL430_VERSION
600#endif
601#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
602 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
603#endif
604
605#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
606 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
607#endif
608#if defined(JSON_HEDLEY_TI_CL430_VERSION)
609 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
610#else
611 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
612#endif
613
614#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
615 #undef JSON_HEDLEY_TI_ARMCL_VERSION
616#endif
617#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
618 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
619#endif
620
621#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
622 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
623#endif
624#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
625 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
626#else
627 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
628#endif
629
630#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
631 #undef JSON_HEDLEY_TI_CL6X_VERSION
632#endif
633#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
634 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
635#endif
636
637#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
638 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
639#endif
640#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
641 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
642#else
643 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
644#endif
645
646#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
647 #undef JSON_HEDLEY_TI_CL7X_VERSION
648#endif
649#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
650 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
651#endif
652
653#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
654 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
655#endif
656#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
657 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
658#else
659 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
660#endif
661
662#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
663 #undef JSON_HEDLEY_TI_CLPRU_VERSION
664#endif
665#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
666 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
667#endif
668
669#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
670 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
671#endif
672#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
673 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
674#else
675 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
676#endif
677
678#if defined(JSON_HEDLEY_CRAY_VERSION)
679 #undef JSON_HEDLEY_CRAY_VERSION
680#endif
681#if defined(_CRAYC)
682 #if defined(_RELEASE_PATCHLEVEL)
683 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
684 #else
685 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
686 #endif
687#endif
688
689#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
690 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
691#endif
692#if defined(JSON_HEDLEY_CRAY_VERSION)
693 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
694#else
695 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
696#endif
697
698#if defined(JSON_HEDLEY_IAR_VERSION)
699 #undef JSON_HEDLEY_IAR_VERSION
700#endif
701#if defined(__IAR_SYSTEMS_ICC__)
702 #if __VER__ > 1000
703 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
704 #else
705 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
706 #endif
707#endif
708
709#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
710 #undef JSON_HEDLEY_IAR_VERSION_CHECK
711#endif
712#if defined(JSON_HEDLEY_IAR_VERSION)
713 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
714#else
715 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
716#endif
717
718#if defined(JSON_HEDLEY_TINYC_VERSION)
719 #undef JSON_HEDLEY_TINYC_VERSION
720#endif
721#if defined(__TINYC__)
722 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
723#endif
724
725#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
726 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
727#endif
728#if defined(JSON_HEDLEY_TINYC_VERSION)
729 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
730#else
731 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
732#endif
733
734#if defined(JSON_HEDLEY_DMC_VERSION)
735 #undef JSON_HEDLEY_DMC_VERSION
736#endif
737#if defined(__DMC__)
738 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
739#endif
740
741#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
742 #undef JSON_HEDLEY_DMC_VERSION_CHECK
743#endif
744#if defined(JSON_HEDLEY_DMC_VERSION)
745 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
746#else
747 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
748#endif
749
750#if defined(JSON_HEDLEY_COMPCERT_VERSION)
751 #undef JSON_HEDLEY_COMPCERT_VERSION
752#endif
753#if defined(__COMPCERT_VERSION__)
754 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
755#endif
756
757#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
758 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
759#endif
760#if defined(JSON_HEDLEY_COMPCERT_VERSION)
761 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
762#else
763 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
764#endif
765
766#if defined(JSON_HEDLEY_PELLES_VERSION)
767 #undef JSON_HEDLEY_PELLES_VERSION
768#endif
769#if defined(__POCC__)
770 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
771#endif
772
773#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
774 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
775#endif
776#if defined(JSON_HEDLEY_PELLES_VERSION)
777 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
778#else
779 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
780#endif
781
782#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
783 #undef JSON_HEDLEY_MCST_LCC_VERSION
784#endif
785#if defined(__LCC__) && defined(__LCC_MINOR__)
786 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
787#endif
788
789#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
790 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
791#endif
792#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
793 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
794#else
795 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
796#endif
797
798#if defined(JSON_HEDLEY_GCC_VERSION)
799 #undef JSON_HEDLEY_GCC_VERSION
800#endif
801#if \
802 defined(JSON_HEDLEY_GNUC_VERSION) && \
803 !defined(__clang__) && \
804 !defined(JSON_HEDLEY_INTEL_VERSION) && \
805 !defined(JSON_HEDLEY_PGI_VERSION) && \
806 !defined(JSON_HEDLEY_ARM_VERSION) && \
807 !defined(JSON_HEDLEY_CRAY_VERSION) && \
808 !defined(JSON_HEDLEY_TI_VERSION) && \
809 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
810 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
811 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
812 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
813 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
814 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
815 !defined(__COMPCERT__) && \
816 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
817 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
818#endif
819
820#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
821 #undef JSON_HEDLEY_GCC_VERSION_CHECK
822#endif
823#if defined(JSON_HEDLEY_GCC_VERSION)
824 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
825#else
826 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
827#endif
828
829#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
830 #undef JSON_HEDLEY_HAS_ATTRIBUTE
831#endif
832#if \
833 defined(__has_attribute) && \
834 ( \
835 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
836 )
837# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
838#else
839# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
840#endif
841
842#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
843 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
844#endif
845#if defined(__has_attribute)
846 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
847#else
848 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
849#endif
850
851#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
852 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
853#endif
854#if defined(__has_attribute)
855 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
856#else
857 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
858#endif
859
860#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
861 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
862#endif
863#if \
864 defined(__has_cpp_attribute) && \
865 defined(__cplusplus) && \
866 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
867 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
868#else
869 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
870#endif
871
872#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
873 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
874#endif
875#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
876 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
877#elif \
878 !defined(JSON_HEDLEY_PGI_VERSION) && \
879 !defined(JSON_HEDLEY_IAR_VERSION) && \
880 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
881 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
882 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
883#else
884 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
885#endif
886
887#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
888 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
889#endif
890#if defined(__has_cpp_attribute) && defined(__cplusplus)
891 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
892#else
893 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
894#endif
895
896#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
897 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
898#endif
899#if defined(__has_cpp_attribute) && defined(__cplusplus)
900 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
901#else
902 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
903#endif
904
905#if defined(JSON_HEDLEY_HAS_BUILTIN)
906 #undef JSON_HEDLEY_HAS_BUILTIN
907#endif
908#if defined(__has_builtin)
909 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
910#else
911 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
912#endif
913
914#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
915 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
916#endif
917#if defined(__has_builtin)
918 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
919#else
920 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
921#endif
922
923#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
924 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
925#endif
926#if defined(__has_builtin)
927 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
928#else
929 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
930#endif
931
932#if defined(JSON_HEDLEY_HAS_FEATURE)
933 #undef JSON_HEDLEY_HAS_FEATURE
934#endif
935#if defined(__has_feature)
936 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
937#else
938 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
939#endif
940
941#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
942 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
943#endif
944#if defined(__has_feature)
945 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
946#else
947 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
948#endif
949
950#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
951 #undef JSON_HEDLEY_GCC_HAS_FEATURE
952#endif
953#if defined(__has_feature)
954 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
955#else
956 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
957#endif
958
959#if defined(JSON_HEDLEY_HAS_EXTENSION)
960 #undef JSON_HEDLEY_HAS_EXTENSION
961#endif
962#if defined(__has_extension)
963 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
964#else
965 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
966#endif
967
968#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
969 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
970#endif
971#if defined(__has_extension)
972 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
973#else
974 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
975#endif
976
977#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
978 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
979#endif
980#if defined(__has_extension)
981 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
982#else
983 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
984#endif
985
986#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
987 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
988#endif
989#if defined(__has_declspec_attribute)
990 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
991#else
992 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
993#endif
994
995#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
996 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
997#endif
998#if defined(__has_declspec_attribute)
999 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1000#else
1001 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1002#endif
1003
1004#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1005 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1006#endif
1007#if defined(__has_declspec_attribute)
1008 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1009#else
1010 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1011#endif
1012
1013#if defined(JSON_HEDLEY_HAS_WARNING)
1014 #undef JSON_HEDLEY_HAS_WARNING
1015#endif
1016#if defined(__has_warning)
1017 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1018#else
1019 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1020#endif
1021
1022#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1023 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1024#endif
1025#if defined(__has_warning)
1026 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1027#else
1028 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1029#endif
1030
1031#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1032 #undef JSON_HEDLEY_GCC_HAS_WARNING
1033#endif
1034#if defined(__has_warning)
1035 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1036#else
1037 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1038#endif
1039
1040#if \
1041 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1042 defined(__clang__) || \
1043 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1044 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1045 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1046 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1047 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1048 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1049 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1050 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1051 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1052 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1053 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1054 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1055 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1056 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1057 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1058 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1059 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1060#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1061 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1062#else
1063 #define JSON_HEDLEY_PRAGMA(value)
1064#endif
1065
1066#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1067 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1068#endif
1069#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1070 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1071#endif
1072#if defined(__clang__)
1073 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1074 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1075#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1076 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1077 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1078#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1079 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1080 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1081#elif \
1082 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1083 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1084 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1085 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1086#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1087 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1088 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1089#elif \
1090 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1091 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1092 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1093 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1094 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1095 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1096 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1097 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1098#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1099 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1100 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1101#else
1102 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1103 #define JSON_HEDLEY_DIAGNOSTIC_POP
1104#endif
1105
1106/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1107 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1108#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1109 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1110#endif
1111#if defined(__cplusplus)
1112# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1113# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1114# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1115# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1116 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1117 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1118 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1119 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1120 xpr \
1121 JSON_HEDLEY_DIAGNOSTIC_POP
1122# else
1123# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1124 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1125 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1126 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1127 xpr \
1128 JSON_HEDLEY_DIAGNOSTIC_POP
1129# endif
1130# else
1131# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1132 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1133 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1134 xpr \
1135 JSON_HEDLEY_DIAGNOSTIC_POP
1136# endif
1137# endif
1138#endif
1139#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1140 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1141#endif
1142
1143#if defined(JSON_HEDLEY_CONST_CAST)
1144 #undef JSON_HEDLEY_CONST_CAST
1145#endif
1146#if defined(__cplusplus)
1147# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1148#elif \
1149 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1150 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1151 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1152# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1153 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1154 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1155 ((T) (expr)); \
1156 JSON_HEDLEY_DIAGNOSTIC_POP \
1157 }))
1158#else
1159# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1160#endif
1161
1162#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1163 #undef JSON_HEDLEY_REINTERPRET_CAST
1164#endif
1165#if defined(__cplusplus)
1166 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1167#else
1168 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1169#endif
1170
1171#if defined(JSON_HEDLEY_STATIC_CAST)
1172 #undef JSON_HEDLEY_STATIC_CAST
1173#endif
1174#if defined(__cplusplus)
1175 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1176#else
1177 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1178#endif
1179
1180#if defined(JSON_HEDLEY_CPP_CAST)
1181 #undef JSON_HEDLEY_CPP_CAST
1182#endif
1183#if defined(__cplusplus)
1184# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1185# define JSON_HEDLEY_CPP_CAST(T, expr) \
1186 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1187 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1188 ((T) (expr)) \
1189 JSON_HEDLEY_DIAGNOSTIC_POP
1190# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1191# define JSON_HEDLEY_CPP_CAST(T, expr) \
1192 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1193 _Pragma("diag_suppress=Pe137") \
1194 JSON_HEDLEY_DIAGNOSTIC_POP
1195# else
1196# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1197# endif
1198#else
1199# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1200#endif
1201
1202#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1203 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1204#endif
1205#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1206 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1207#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1208 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1209#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1210 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1211#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1212 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1213#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1214 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1215#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1216 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1217#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1218 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1219#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1220 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1221#elif \
1222 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1223 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1224 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1225 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1226 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1227 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1228 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1229 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1230 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1231 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1232 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1233 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1234#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1235 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1236#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1237 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1238#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1239 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1240#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1241 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1242#else
1243 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1244#endif
1245
1246#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1247 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1248#endif
1249#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1250 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1251#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1252 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1253#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1254 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1255#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1256 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1257#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1258 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1259#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1260 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1261#elif \
1262 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1263 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1264 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1265 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1266 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1267#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1268 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1269#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1270 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1271#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1272 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1273#else
1274 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1275#endif
1276
1277#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1278 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1279#endif
1280#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1281 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1282#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1283 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1284#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1285 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1286#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1287 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1288#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1289 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1290#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1291 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1292#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1293 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1294#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1295 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1296#elif \
1297 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1298 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1299 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1300 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1301#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1302 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1303#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1304 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1305#else
1306 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1307#endif
1308
1309#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1310 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1311#endif
1312#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1313 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1314#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1315 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1316#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1317 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1318#else
1319 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1320#endif
1321
1322#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1323 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1324#endif
1325#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1326 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1327#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1328 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1329#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1330 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1331#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1332 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1333#else
1334 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1335#endif
1336
1337#if defined(JSON_HEDLEY_DEPRECATED)
1338 #undef JSON_HEDLEY_DEPRECATED
1339#endif
1340#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1341 #undef JSON_HEDLEY_DEPRECATED_FOR
1342#endif
1343#if \
1344 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1345 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1346 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1347 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1348#elif \
1349 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1350 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1351 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1352 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1353 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1354 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1355 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1356 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1357 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1358 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1359 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1360 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1361 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1362 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1363#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1364 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1365 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1366#elif \
1367 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1368 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1369 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1370 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1371 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1372 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1373 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1374 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1375 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1376 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1377 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1378 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1379 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1380 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1381 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1382 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1383 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1384 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1385#elif \
1386 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1387 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1388 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1389 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1390 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1391#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1392 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1393 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1394#else
1395 #define JSON_HEDLEY_DEPRECATED(since)
1396 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1397#endif
1398
1399#if defined(JSON_HEDLEY_UNAVAILABLE)
1400 #undef JSON_HEDLEY_UNAVAILABLE
1401#endif
1402#if \
1403 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1404 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1405 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1406 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1407 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1408#else
1409 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1410#endif
1411
1412#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1413 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1414#endif
1415#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1416 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1417#endif
1418#if \
1419 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1420 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1421 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1422 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1423 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1424 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1425 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1426 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1427 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1428 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1429 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1430 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1431 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1432 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1433 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1434 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1435 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1436 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1437 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1438#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1439 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1440 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1441#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1442 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1443 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1444#elif defined(_Check_return_) /* SAL */
1445 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1446 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1447#else
1448 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1449 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1450#endif
1451
1452#if defined(JSON_HEDLEY_SENTINEL)
1453 #undef JSON_HEDLEY_SENTINEL
1454#endif
1455#if \
1456 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1457 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1458 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1459 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1460 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1461 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1462#else
1463 #define JSON_HEDLEY_SENTINEL(position)
1464#endif
1465
1466#if defined(JSON_HEDLEY_NO_RETURN)
1467 #undef JSON_HEDLEY_NO_RETURN
1468#endif
1469#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1470 #define JSON_HEDLEY_NO_RETURN __noreturn
1471#elif \
1472 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1473 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1474 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1475#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1476 #define JSON_HEDLEY_NO_RETURN _Noreturn
1477#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1478 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1479#elif \
1480 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1481 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1482 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1483 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1484 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1485 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1486 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1487 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1488 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1489 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1490 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1491 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1492 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1493 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1494 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1495 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1496 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1497 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1498#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1499 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1500#elif \
1501 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1502 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1503 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1504#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1505 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1506#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1507 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1508#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1509 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1510#else
1511 #define JSON_HEDLEY_NO_RETURN
1512#endif
1513
1514#if defined(JSON_HEDLEY_NO_ESCAPE)
1515 #undef JSON_HEDLEY_NO_ESCAPE
1516#endif
1517#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1518 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1519#else
1520 #define JSON_HEDLEY_NO_ESCAPE
1521#endif
1522
1523#if defined(JSON_HEDLEY_UNREACHABLE)
1524 #undef JSON_HEDLEY_UNREACHABLE
1525#endif
1526#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1527 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1528#endif
1529#if defined(JSON_HEDLEY_ASSUME)
1530 #undef JSON_HEDLEY_ASSUME
1531#endif
1532#if \
1533 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1534 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1535 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1536 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1537#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1538 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1539#elif \
1540 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1541 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1542 #if defined(__cplusplus)
1543 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1544 #else
1545 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1546 #endif
1547#endif
1548#if \
1549 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1550 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1551 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1552 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1553 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1554 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1555 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1556 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1557#elif defined(JSON_HEDLEY_ASSUME)
1558 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1559#endif
1560#if !defined(JSON_HEDLEY_ASSUME)
1561 #if defined(JSON_HEDLEY_UNREACHABLE)
1562 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1563 #else
1564 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1565 #endif
1566#endif
1567#if defined(JSON_HEDLEY_UNREACHABLE)
1568 #if \
1569 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1570 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1571 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1572 #else
1573 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1574 #endif
1575#else
1576 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1577#endif
1578#if !defined(JSON_HEDLEY_UNREACHABLE)
1579 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1580#endif
1581
1582JSON_HEDLEY_DIAGNOSTIC_PUSH
1583#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1584 #pragma clang diagnostic ignored "-Wpedantic"
1585#endif
1586#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1587 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1588#endif
1589#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1590 #if defined(__clang__)
1591 #pragma clang diagnostic ignored "-Wvariadic-macros"
1592 #elif defined(JSON_HEDLEY_GCC_VERSION)
1593 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1594 #endif
1595#endif
1596#if defined(JSON_HEDLEY_NON_NULL)
1597 #undef JSON_HEDLEY_NON_NULL
1598#endif
1599#if \
1600 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1601 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1602 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1603 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1604 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1605#else
1606 #define JSON_HEDLEY_NON_NULL(...)
1607#endif
1608JSON_HEDLEY_DIAGNOSTIC_POP
1609
1610#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1611 #undef JSON_HEDLEY_PRINTF_FORMAT
1612#endif
1613#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1614 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1615#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1616 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1617#elif \
1618 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1619 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1620 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1621 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1622 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1623 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1624 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1625 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1626 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1627 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1628 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1629 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1630 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1631 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1632 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1633 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1634 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1635 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1636#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1637 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1638#else
1639 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1640#endif
1641
1642#if defined(JSON_HEDLEY_CONSTEXPR)
1643 #undef JSON_HEDLEY_CONSTEXPR
1644#endif
1645#if defined(__cplusplus)
1646 #if __cplusplus >= 201103L
1647 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1648 #endif
1649#endif
1650#if !defined(JSON_HEDLEY_CONSTEXPR)
1651 #define JSON_HEDLEY_CONSTEXPR
1652#endif
1653
1654#if defined(JSON_HEDLEY_PREDICT)
1655 #undef JSON_HEDLEY_PREDICT
1656#endif
1657#if defined(JSON_HEDLEY_LIKELY)
1658 #undef JSON_HEDLEY_LIKELY
1659#endif
1660#if defined(JSON_HEDLEY_UNLIKELY)
1661 #undef JSON_HEDLEY_UNLIKELY
1662#endif
1663#if defined(JSON_HEDLEY_UNPREDICTABLE)
1664 #undef JSON_HEDLEY_UNPREDICTABLE
1665#endif
1666#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1667 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1668#endif
1669#if \
1670 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1671 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1672 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1673# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1674# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1675# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1676# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1677# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1678#elif \
1679 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1680 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1681 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1682 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1683 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1684 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1685 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1686 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1687 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1688 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1689 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1690 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1691 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1692 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1693 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1694 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1695# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1696 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1697# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1698 (__extension__ ({ \
1699 double hedley_probability_ = (probability); \
1700 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1701 }))
1702# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1703 (__extension__ ({ \
1704 double hedley_probability_ = (probability); \
1705 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1706 }))
1707# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1708# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1709#else
1710# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1711# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1712# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1713# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1714# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1715#endif
1716#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1717 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1718#endif
1719
1720#if defined(JSON_HEDLEY_MALLOC)
1721 #undef JSON_HEDLEY_MALLOC
1722#endif
1723#if \
1724 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1725 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1726 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1727 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1728 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1729 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1730 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1731 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1732 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1733 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1734 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1735 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1736 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1737 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1738 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1739 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1740 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1741 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1742 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1743#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1744 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1745#elif \
1746 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1747 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1748 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1749#else
1750 #define JSON_HEDLEY_MALLOC
1751#endif
1752
1753#if defined(JSON_HEDLEY_PURE)
1754 #undef JSON_HEDLEY_PURE
1755#endif
1756#if \
1757 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1758 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1759 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1760 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1761 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1762 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1763 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1764 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1765 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1766 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1767 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1768 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1769 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1770 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1771 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1772 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1773 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1774 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1775 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1776# define JSON_HEDLEY_PURE __attribute__((__pure__))
1777#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1778# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1779#elif defined(__cplusplus) && \
1780 ( \
1781 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1782 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1783 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1784 )
1785# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1786#else
1787# define JSON_HEDLEY_PURE
1788#endif
1789
1790#if defined(JSON_HEDLEY_CONST)
1791 #undef JSON_HEDLEY_CONST
1792#endif
1793#if \
1794 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1795 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1796 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1797 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1798 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1799 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1800 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1801 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1802 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1803 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1804 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1805 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1806 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1807 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1808 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1809 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1810 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1811 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1812 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1813 #define JSON_HEDLEY_CONST __attribute__((__const__))
1814#elif \
1815 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1816 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1817#else
1818 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1819#endif
1820
1821#if defined(JSON_HEDLEY_RESTRICT)
1822 #undef JSON_HEDLEY_RESTRICT
1823#endif
1824#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1825 #define JSON_HEDLEY_RESTRICT restrict
1826#elif \
1827 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1828 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1829 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1830 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1831 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1832 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1833 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1834 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1835 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1836 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1837 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1838 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1839 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1840 defined(__clang__) || \
1841 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1842 #define JSON_HEDLEY_RESTRICT __restrict
1843#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1844 #define JSON_HEDLEY_RESTRICT _Restrict
1845#else
1846 #define JSON_HEDLEY_RESTRICT
1847#endif
1848
1849#if defined(JSON_HEDLEY_INLINE)
1850 #undef JSON_HEDLEY_INLINE
1851#endif
1852#if \
1853 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1854 (defined(__cplusplus) && (__cplusplus >= 199711L))
1855 #define JSON_HEDLEY_INLINE inline
1856#elif \
1857 defined(JSON_HEDLEY_GCC_VERSION) || \
1858 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1859 #define JSON_HEDLEY_INLINE __inline__
1860#elif \
1861 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1862 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1863 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1864 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1865 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1866 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1867 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1868 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1869 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1870 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1871 #define JSON_HEDLEY_INLINE __inline
1872#else
1873 #define JSON_HEDLEY_INLINE
1874#endif
1875
1876#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1877 #undef JSON_HEDLEY_ALWAYS_INLINE
1878#endif
1879#if \
1880 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1881 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1882 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1883 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1884 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1885 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1886 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1887 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1888 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1889 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1890 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1891 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1892 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1893 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1894 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1895 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1896 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1897 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1898 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1899# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1900#elif \
1901 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1902 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1903# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1904#elif defined(__cplusplus) && \
1905 ( \
1906 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1907 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1908 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1909 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1910 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1911 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1912 )
1913# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1914#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1915# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1916#else
1917# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1918#endif
1919
1920#if defined(JSON_HEDLEY_NEVER_INLINE)
1921 #undef JSON_HEDLEY_NEVER_INLINE
1922#endif
1923#if \
1924 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1925 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1926 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1927 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1928 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1929 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1930 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1931 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1932 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1933 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1934 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1935 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1936 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1937 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1938 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1939 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1940 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1941 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1942 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1943 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1944#elif \
1945 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1946 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1947 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1948#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1949 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1950#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1951 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1952#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1953 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1954#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1955 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1956#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1957 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1958#else
1959 #define JSON_HEDLEY_NEVER_INLINE
1960#endif
1961
1962#if defined(JSON_HEDLEY_PRIVATE)
1963 #undef JSON_HEDLEY_PRIVATE
1964#endif
1965#if defined(JSON_HEDLEY_PUBLIC)
1966 #undef JSON_HEDLEY_PUBLIC
1967#endif
1968#if defined(JSON_HEDLEY_IMPORT)
1969 #undef JSON_HEDLEY_IMPORT
1970#endif
1971#if defined(_WIN32) || defined(__CYGWIN__)
1972# define JSON_HEDLEY_PRIVATE
1973# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1974# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1975#else
1976# if \
1977 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1978 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1979 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1980 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1981 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1982 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1983 ( \
1984 defined(__TI_EABI__) && \
1985 ( \
1986 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1987 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1988 ) \
1989 ) || \
1990 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1991# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1992# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1993# else
1994# define JSON_HEDLEY_PRIVATE
1995# define JSON_HEDLEY_PUBLIC
1996# endif
1997# define JSON_HEDLEY_IMPORT extern
1998#endif
1999
2000#if defined(JSON_HEDLEY_NO_THROW)
2001 #undef JSON_HEDLEY_NO_THROW
2002#endif
2003#if \
2004 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2005 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2006 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2007 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2008 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2009#elif \
2010 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2011 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2012 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2013 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2014#else
2015 #define JSON_HEDLEY_NO_THROW
2016#endif
2017
2018#if defined(JSON_HEDLEY_FALL_THROUGH)
2019 #undef JSON_HEDLEY_FALL_THROUGH
2020#endif
2021#if \
2022 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2023 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2024 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2025 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2026#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2027 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2028#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2029 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2030#elif defined(__fallthrough) /* SAL */
2031 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2032#else
2033 #define JSON_HEDLEY_FALL_THROUGH
2034#endif
2035
2036#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2037 #undef JSON_HEDLEY_RETURNS_NON_NULL
2038#endif
2039#if \
2040 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2041 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2042 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2043 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2044#elif defined(_Ret_notnull_) /* SAL */
2045 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2046#else
2047 #define JSON_HEDLEY_RETURNS_NON_NULL
2048#endif
2049
2050#if defined(JSON_HEDLEY_ARRAY_PARAM)
2051 #undef JSON_HEDLEY_ARRAY_PARAM
2052#endif
2053#if \
2054 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2055 !defined(__STDC_NO_VLA__) && \
2056 !defined(__cplusplus) && \
2057 !defined(JSON_HEDLEY_PGI_VERSION) && \
2058 !defined(JSON_HEDLEY_TINYC_VERSION)
2059 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2060#else
2061 #define JSON_HEDLEY_ARRAY_PARAM(name)
2062#endif
2063
2064#if defined(JSON_HEDLEY_IS_CONSTANT)
2065 #undef JSON_HEDLEY_IS_CONSTANT
2066#endif
2067#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2068 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2069#endif
2070/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2071 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2072#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2073 #undef JSON_HEDLEY_IS_CONSTEXPR_
2074#endif
2075#if \
2076 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2077 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2078 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2079 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2080 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2081 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2082 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2083 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2084 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2085 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2086 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2087#endif
2088#if !defined(__cplusplus)
2089# if \
2090 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2091 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2092 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2093 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2094 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2095 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2096 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2097#if defined(__INTPTR_TYPE__)
2098 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2099#else
2100 #include <stdint.h>
2101 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2102#endif
2103# elif \
2104 ( \
2105 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2106 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2107 !defined(JSON_HEDLEY_PGI_VERSION) && \
2108 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2109 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2110 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2111 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2112 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2113 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2114#if defined(__INTPTR_TYPE__)
2115 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2116#else
2117 #include <stdint.h>
2118 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2119#endif
2120# elif \
2121 defined(JSON_HEDLEY_GCC_VERSION) || \
2122 defined(JSON_HEDLEY_INTEL_VERSION) || \
2123 defined(JSON_HEDLEY_TINYC_VERSION) || \
2124 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2125 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2126 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2127 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2128 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2129 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2130 defined(__clang__)
2131# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2132 sizeof(void) != \
2133 sizeof(*( \
2134 1 ? \
2135 ((void*) ((expr) * 0L) ) : \
2136((struct { char v[sizeof(void) * 2]; } *) 1) \
2137 ) \
2138 ) \
2139 )
2140# endif
2141#endif
2142#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2143 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2144 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2145 #endif
2146 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2147#else
2148 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2149 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2150 #endif
2151 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2152#endif
2153
2154#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2155 #undef JSON_HEDLEY_BEGIN_C_DECLS
2156#endif
2157#if defined(JSON_HEDLEY_END_C_DECLS)
2158 #undef JSON_HEDLEY_END_C_DECLS
2159#endif
2160#if defined(JSON_HEDLEY_C_DECL)
2161 #undef JSON_HEDLEY_C_DECL
2162#endif
2163#if defined(__cplusplus)
2164 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2165 #define JSON_HEDLEY_END_C_DECLS }
2166 #define JSON_HEDLEY_C_DECL extern "C"
2167#else
2168 #define JSON_HEDLEY_BEGIN_C_DECLS
2169 #define JSON_HEDLEY_END_C_DECLS
2170 #define JSON_HEDLEY_C_DECL
2171#endif
2172
2173#if defined(JSON_HEDLEY_STATIC_ASSERT)
2174 #undef JSON_HEDLEY_STATIC_ASSERT
2175#endif
2176#if \
2177 !defined(__cplusplus) && ( \
2178 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2179 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2180 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2181 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2182 defined(_Static_assert) \
2183 )
2184# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2185#elif \
2186 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2187 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2188 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2189# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2190#else
2191# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2192#endif
2193
2194#if defined(JSON_HEDLEY_NULL)
2195 #undef JSON_HEDLEY_NULL
2196#endif
2197#if defined(__cplusplus)
2198 #if __cplusplus >= 201103L
2199 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2200 #elif defined(NULL)
2201 #define JSON_HEDLEY_NULL NULL
2202 #else
2203 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2204 #endif
2205#elif defined(NULL)
2206 #define JSON_HEDLEY_NULL NULL
2207#else
2208 #define JSON_HEDLEY_NULL ((void*) 0)
2209#endif
2210
2211#if defined(JSON_HEDLEY_MESSAGE)
2212 #undef JSON_HEDLEY_MESSAGE
2213#endif
2214#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2215# define JSON_HEDLEY_MESSAGE(msg) \
2216 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2217 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2218 JSON_HEDLEY_PRAGMA(message msg) \
2219 JSON_HEDLEY_DIAGNOSTIC_POP
2220#elif \
2221 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2222 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2223# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2224#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2225# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2226#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2227# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2228#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2229# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2230#else
2231# define JSON_HEDLEY_MESSAGE(msg)
2232#endif
2233
2234#if defined(JSON_HEDLEY_WARNING)
2235 #undef JSON_HEDLEY_WARNING
2236#endif
2237#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2238# define JSON_HEDLEY_WARNING(msg) \
2239 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2240 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2241 JSON_HEDLEY_PRAGMA(clang warning msg) \
2242 JSON_HEDLEY_DIAGNOSTIC_POP
2243#elif \
2244 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2245 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2246 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2247# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2248#elif \
2249 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2250 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2251# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2252#else
2253# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2254#endif
2255
2256#if defined(JSON_HEDLEY_REQUIRE)
2257 #undef JSON_HEDLEY_REQUIRE
2258#endif
2259#if defined(JSON_HEDLEY_REQUIRE_MSG)
2260 #undef JSON_HEDLEY_REQUIRE_MSG
2261#endif
2262#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2263# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2264# define JSON_HEDLEY_REQUIRE(expr) \
2265 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2266 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2267 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2268 JSON_HEDLEY_DIAGNOSTIC_POP
2269# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2270 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2271 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2272 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2273 JSON_HEDLEY_DIAGNOSTIC_POP
2274# else
2275# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2276# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2277# endif
2278#else
2279# define JSON_HEDLEY_REQUIRE(expr)
2280# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2281#endif
2282
2283#if defined(JSON_HEDLEY_FLAGS)
2284 #undef JSON_HEDLEY_FLAGS
2285#endif
2286#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2287 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2288#else
2289 #define JSON_HEDLEY_FLAGS
2290#endif
2291
2292#if defined(JSON_HEDLEY_FLAGS_CAST)
2293 #undef JSON_HEDLEY_FLAGS_CAST
2294#endif
2295#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2296# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2297 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2298 _Pragma("warning(disable:188)") \
2299 ((T) (expr)); \
2300 JSON_HEDLEY_DIAGNOSTIC_POP \
2301 }))
2302#else
2303# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2304#endif
2305
2306#if defined(JSON_HEDLEY_EMPTY_BASES)
2307 #undef JSON_HEDLEY_EMPTY_BASES
2308#endif
2309#if \
2310 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2311 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2312 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2313#else
2314 #define JSON_HEDLEY_EMPTY_BASES
2315#endif
2316
2317/* Remaining macros are deprecated. */
2318
2319#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2320 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2321#endif
2322#if defined(__clang__)
2323 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2324#else
2325 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2326#endif
2327
2328#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2329 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2330#endif
2331#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2332
2333#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2334 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2335#endif
2336#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2337
2338#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2339 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2340#endif
2341#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2342
2343#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2344 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2345#endif
2346#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2347
2348#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2349 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2350#endif
2351#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2352
2353#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2354 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2355#endif
2356#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2357
2358#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2359 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2360#endif
2361#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2362
2363#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2364
2365
2366// This file contains all internal macro definitions (except those affecting ABI)
2367// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2368
2369// #include <nlohmann/detail/abi_macros.hpp>
2370
2371
2372// exclude unsupported compilers
2373#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2374 #if defined(__clang__)
2375 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2376 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2377 #endif
2378 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2379 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2380 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2381 #endif
2382 #endif
2383#endif
2384
2385// C++ language standard detection
2386// if the user manually specified the used c++ version this is skipped
2387#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2388 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2389 #define JSON_HAS_CPP_20
2390 #define JSON_HAS_CPP_17
2391 #define JSON_HAS_CPP_14
2392 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2393 #define JSON_HAS_CPP_17
2394 #define JSON_HAS_CPP_14
2395 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2396 #define JSON_HAS_CPP_14
2397 #endif
2398 // the cpp 11 flag is always specified because it is the minimal required version
2399 #define JSON_HAS_CPP_11
2400#endif
2401
2402#ifdef __has_include
2403 #if __has_include(<version>)
2404 #include <version>
2405 #endif
2406#endif
2407
2408#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2409 #ifdef JSON_HAS_CPP_17
2410 #if defined(__cpp_lib_filesystem)
2411 #define JSON_HAS_FILESYSTEM 1
2412 #elif defined(__cpp_lib_experimental_filesystem)
2413 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2414 #elif !defined(__has_include)
2415 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2416 #elif __has_include(<filesystem>)
2417 #define JSON_HAS_FILESYSTEM 1
2418 #elif __has_include(<experimental/filesystem>)
2419 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2420 #endif
2421
2422 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2423 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2424 #undef JSON_HAS_FILESYSTEM
2425 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2426 #endif
2427
2428 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2429 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2430 #undef JSON_HAS_FILESYSTEM
2431 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2432 #endif
2433
2434 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2435 #if defined(__clang_major__) && __clang_major__ < 7
2436 #undef JSON_HAS_FILESYSTEM
2437 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2438 #endif
2439
2440 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2441 #if defined(_MSC_VER) && _MSC_VER < 1914
2442 #undef JSON_HAS_FILESYSTEM
2443 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2444 #endif
2445
2446 // no filesystem support before iOS 13
2447 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2448 #undef JSON_HAS_FILESYSTEM
2449 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2450 #endif
2451
2452 // no filesystem support before macOS Catalina
2453 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2454 #undef JSON_HAS_FILESYSTEM
2455 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2456 #endif
2457 #endif
2458#endif
2459
2460#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2461 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2462#endif
2463
2464#ifndef JSON_HAS_FILESYSTEM
2465 #define JSON_HAS_FILESYSTEM 0
2466#endif
2467
2468#ifndef JSON_HAS_THREE_WAY_COMPARISON
2469 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2470 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2471 #define JSON_HAS_THREE_WAY_COMPARISON 1
2472 #else
2473 #define JSON_HAS_THREE_WAY_COMPARISON 0
2474 #endif
2475#endif
2476
2477#ifndef JSON_HAS_RANGES
2478 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2479 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2480 #define JSON_HAS_RANGES 0
2481 #elif defined(__cpp_lib_ranges)
2482 #define JSON_HAS_RANGES 1
2483 #else
2484 #define JSON_HAS_RANGES 0
2485 #endif
2486#endif
2487
2488#ifndef JSON_HAS_STATIC_RTTI
2489 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2490 #define JSON_HAS_STATIC_RTTI 1
2491 #else
2492 #define JSON_HAS_STATIC_RTTI 0
2493 #endif
2494#endif
2495
2496#ifdef JSON_HAS_CPP_17
2497 #define JSON_INLINE_VARIABLE inline
2498#else
2499 #define JSON_INLINE_VARIABLE
2500#endif
2501
2502#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2503 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2504#else
2505 #define JSON_NO_UNIQUE_ADDRESS
2506#endif
2507
2508// disable documentation warnings on clang
2509#if defined(__clang__)
2510 #pragma clang diagnostic push
2511 #pragma clang diagnostic ignored "-Wdocumentation"
2512 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2513#endif
2514
2515// allow disabling exceptions
2516#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2517 #define JSON_THROW(exception) throw exception
2518 #define JSON_TRY try
2519 #define JSON_CATCH(exception) catch(exception)
2520 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2521#else
2522 #include <cstdlib>
2523 #define JSON_THROW(exception) std::abort()
2524 #define JSON_TRY if(true)
2525 #define JSON_CATCH(exception) if(false)
2526 #define JSON_INTERNAL_CATCH(exception) if(false)
2527#endif
2528
2529// override exception macros
2530#if defined(JSON_THROW_USER)
2531 #undef JSON_THROW
2532 #define JSON_THROW JSON_THROW_USER
2533#endif
2534#if defined(JSON_TRY_USER)
2535 #undef JSON_TRY
2536 #define JSON_TRY JSON_TRY_USER
2537#endif
2538#if defined(JSON_CATCH_USER)
2539 #undef JSON_CATCH
2540 #define JSON_CATCH JSON_CATCH_USER
2541 #undef JSON_INTERNAL_CATCH
2542 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2543#endif
2544#if defined(JSON_INTERNAL_CATCH_USER)
2545 #undef JSON_INTERNAL_CATCH
2546 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2547#endif
2548
2549// allow overriding assert
2550#if !defined(JSON_ASSERT)
2551 #include <cassert> // assert
2552 #define JSON_ASSERT(x) assert(x)
2553#endif
2554
2555// allow to access some private functions (needed by the test suite)
2556#if defined(JSON_TESTS_PRIVATE)
2557 #define JSON_PRIVATE_UNLESS_TESTED public
2558#else
2559 #define JSON_PRIVATE_UNLESS_TESTED private
2560#endif
2561
2567#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2568 template<typename BasicJsonType> \
2569 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2570 { \
2571 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2572 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2573 auto it = std::find_if(std::begin(m), std::end(m), \
2574 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2575 { \
2576 return ej_pair.first == e; \
2577 }); \
2578 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2579 } \
2580 template<typename BasicJsonType> \
2581 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2582 { \
2583 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2584 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2585 auto it = std::find_if(std::begin(m), std::end(m), \
2586 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2587 { \
2588 return ej_pair.second == j; \
2589 }); \
2590 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2591 }
2592
2593// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2594// may be removed in the future once the class is split.
2595
2596#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2597 template<template<typename, typename, typename...> class ObjectType, \
2598 template<typename, typename...> class ArrayType, \
2599 class StringType, class BooleanType, class NumberIntegerType, \
2600 class NumberUnsignedType, class NumberFloatType, \
2601 template<typename> class AllocatorType, \
2602 template<typename, typename = void> class JSONSerializer, \
2603 class BinaryType, \
2604 class CustomBaseClass>
2605
2606#define NLOHMANN_BASIC_JSON_TPL \
2607 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2608 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2609 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2610
2611// Macros to simplify conversion from/to types
2612
2613#define NLOHMANN_JSON_EXPAND( x ) x
2614#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
2615#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2616 NLOHMANN_JSON_PASTE64, \
2617 NLOHMANN_JSON_PASTE63, \
2618 NLOHMANN_JSON_PASTE62, \
2619 NLOHMANN_JSON_PASTE61, \
2620 NLOHMANN_JSON_PASTE60, \
2621 NLOHMANN_JSON_PASTE59, \
2622 NLOHMANN_JSON_PASTE58, \
2623 NLOHMANN_JSON_PASTE57, \
2624 NLOHMANN_JSON_PASTE56, \
2625 NLOHMANN_JSON_PASTE55, \
2626 NLOHMANN_JSON_PASTE54, \
2627 NLOHMANN_JSON_PASTE53, \
2628 NLOHMANN_JSON_PASTE52, \
2629 NLOHMANN_JSON_PASTE51, \
2630 NLOHMANN_JSON_PASTE50, \
2631 NLOHMANN_JSON_PASTE49, \
2632 NLOHMANN_JSON_PASTE48, \
2633 NLOHMANN_JSON_PASTE47, \
2634 NLOHMANN_JSON_PASTE46, \
2635 NLOHMANN_JSON_PASTE45, \
2636 NLOHMANN_JSON_PASTE44, \
2637 NLOHMANN_JSON_PASTE43, \
2638 NLOHMANN_JSON_PASTE42, \
2639 NLOHMANN_JSON_PASTE41, \
2640 NLOHMANN_JSON_PASTE40, \
2641 NLOHMANN_JSON_PASTE39, \
2642 NLOHMANN_JSON_PASTE38, \
2643 NLOHMANN_JSON_PASTE37, \
2644 NLOHMANN_JSON_PASTE36, \
2645 NLOHMANN_JSON_PASTE35, \
2646 NLOHMANN_JSON_PASTE34, \
2647 NLOHMANN_JSON_PASTE33, \
2648 NLOHMANN_JSON_PASTE32, \
2649 NLOHMANN_JSON_PASTE31, \
2650 NLOHMANN_JSON_PASTE30, \
2651 NLOHMANN_JSON_PASTE29, \
2652 NLOHMANN_JSON_PASTE28, \
2653 NLOHMANN_JSON_PASTE27, \
2654 NLOHMANN_JSON_PASTE26, \
2655 NLOHMANN_JSON_PASTE25, \
2656 NLOHMANN_JSON_PASTE24, \
2657 NLOHMANN_JSON_PASTE23, \
2658 NLOHMANN_JSON_PASTE22, \
2659 NLOHMANN_JSON_PASTE21, \
2660 NLOHMANN_JSON_PASTE20, \
2661 NLOHMANN_JSON_PASTE19, \
2662 NLOHMANN_JSON_PASTE18, \
2663 NLOHMANN_JSON_PASTE17, \
2664 NLOHMANN_JSON_PASTE16, \
2665 NLOHMANN_JSON_PASTE15, \
2666 NLOHMANN_JSON_PASTE14, \
2667 NLOHMANN_JSON_PASTE13, \
2668 NLOHMANN_JSON_PASTE12, \
2669 NLOHMANN_JSON_PASTE11, \
2670 NLOHMANN_JSON_PASTE10, \
2671 NLOHMANN_JSON_PASTE9, \
2672 NLOHMANN_JSON_PASTE8, \
2673 NLOHMANN_JSON_PASTE7, \
2674 NLOHMANN_JSON_PASTE6, \
2675 NLOHMANN_JSON_PASTE5, \
2676 NLOHMANN_JSON_PASTE4, \
2677 NLOHMANN_JSON_PASTE3, \
2678 NLOHMANN_JSON_PASTE2, \
2679 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2680#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2681#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2682#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2683#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2684#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2685#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)
2686#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)
2687#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)
2688#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)
2689#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)
2690#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)
2691#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)
2692#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)
2693#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)
2694#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)
2695#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)
2696#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)
2697#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)
2698#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)
2699#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)
2700#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)
2701#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)
2702#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)
2703#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)
2704#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)
2705#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)
2706#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)
2707#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)
2708#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)
2709#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)
2710#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)
2711#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)
2712#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)
2713#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)
2714#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)
2715#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)
2716#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)
2717#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)
2718#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)
2719#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)
2720#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)
2721#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)
2722#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)
2723#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)
2724#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)
2725#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)
2726#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)
2727#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)
2728#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)
2729#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)
2730#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)
2731#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)
2732#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)
2733#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)
2734#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)
2735#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)
2736#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)
2737#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)
2738#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)
2739#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)
2740#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)
2741#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)
2742#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)
2743
2744#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2745#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2746#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2747
2753#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2754 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__)) } \
2755 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__)) }
2756
2757#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2758 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__)) } \
2759 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__)) }
2760
2761#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(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
2769#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2770 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__)) } \
2771 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__)) }
2772
2773#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2774 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__)) }
2775
2776#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2777 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__)) } \
2778 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__)) }
2779
2780// inspired from https://stackoverflow.com/a/26745591
2781// allows to call any std function as if (e.g. with begin):
2782// using std::begin; begin(x);
2783//
2784// it allows using the detected idiom to retrieve the return type
2785// of such an expression
2786#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2787 namespace detail { \
2788 using std::std_name; \
2789 \
2790 template<typename... T> \
2791 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2792 } \
2793 \
2794 namespace detail2 { \
2795 struct std_name##_tag \
2796 { \
2797 }; \
2798 \
2799 template<typename... T> \
2800 std_name##_tag std_name(T&&...); \
2801 \
2802 template<typename... T> \
2803 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2804 \
2805 template<typename... T> \
2806 struct would_call_std_##std_name \
2807 { \
2808 static constexpr auto const value = ::nlohmann::detail:: \
2809 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2810 }; \
2811 } /* namespace detail2 */ \
2812 \
2813 template<typename... T> \
2814 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2815 { \
2816 }
2817
2818#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2819 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2820#endif
2821
2822#if JSON_USE_IMPLICIT_CONVERSIONS
2823 #define JSON_EXPLICIT
2824#else
2825 #define JSON_EXPLICIT explicit
2826#endif
2827
2828#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2829 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2830#endif
2831
2832#ifndef JSON_USE_GLOBAL_UDLS
2833 #define JSON_USE_GLOBAL_UDLS 1
2834#endif
2835
2836#if JSON_HAS_THREE_WAY_COMPARISON
2837 #include <compare> // partial_ordering
2838#endif
2839
2840NLOHMANN_JSON_NAMESPACE_BEGIN
2841namespace detail
2842{
2843
2845// JSON type enumeration //
2847
2872enum class value_t : std::uint8_t
2873{
2874 null,
2875 object,
2876 array,
2877 string,
2878 boolean,
2881 number_float,
2882 binary,
2883 discarded
2884};
2885
2899#if JSON_HAS_THREE_WAY_COMPARISON
2900 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
2901#else
2902 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2903#endif
2904{
2905 static constexpr std::array<std::uint8_t, 9> order = {{
2906 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
2907 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
2908 6 /* binary */
2909 }
2910 };
2911
2912 const auto l_index = static_cast<std::size_t>(lhs);
2913 const auto r_index = static_cast<std::size_t>(rhs);
2914#if JSON_HAS_THREE_WAY_COMPARISON
2915 if (l_index < order.size() && r_index < order.size())
2916 {
2917 return order[l_index] <=> order[r_index]; // *NOPAD*
2918 }
2919 return std::partial_ordering::unordered;
2920#else
2921 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
2922#endif
2923}
2924
2925// GCC selects the built-in operator< over an operator rewritten from
2926// a user-defined spaceship operator
2927// Clang, MSVC, and ICC select the rewritten candidate
2928// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
2929#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
2930inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2931{
2932 return std::is_lt(lhs <=> rhs); // *NOPAD*
2933}
2934#endif
2935
2936} // namespace detail
2937NLOHMANN_JSON_NAMESPACE_END
2938
2939// #include <nlohmann/detail/string_escape.hpp>
2940// __ _____ _____ _____
2941// __| | __| | | | JSON for Modern C++
2942// | | |__ | | | | | | version 3.11.3
2943// |_____|_____|_____|_|___| https://github.com/nlohmann/json
2944//
2945// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
2946// SPDX-License-Identifier: MIT
2947
2948
2949
2950// #include <nlohmann/detail/abi_macros.hpp>
2951
2952
2953NLOHMANN_JSON_NAMESPACE_BEGIN
2954namespace detail
2955{
2956
2970template<typename StringType>
2971inline void replace_substring(StringType& s, const StringType& f,
2972 const StringType& t)
2973{
2974 JSON_ASSERT(!f.empty());
2975 for (auto pos = s.find(f); // find first occurrence of f
2976 pos != StringType::npos; // make sure f was found
2977 s.replace(pos, f.size(), t), // replace with t, and
2978 pos = s.find(f, pos + t.size())) // find next occurrence of f
2979 {}
2980}
2981
2989template<typename StringType>
2990inline StringType escape(StringType s)
2991{
2992 replace_substring(s, StringType{"~"}, StringType{"~0"});
2993 replace_substring(s, StringType{"/"}, StringType{"~1"});
2994 return s;
2995}
2996
3004template<typename StringType>
3005static void unescape(StringType& s)
3006{
3007 replace_substring(s, StringType{"~1"}, StringType{"/"});
3008 replace_substring(s, StringType{"~0"}, StringType{"~"});
3009}
3010
3011} // namespace detail
3012NLOHMANN_JSON_NAMESPACE_END
3013
3014// #include <nlohmann/detail/input/position_t.hpp>
3015// __ _____ _____ _____
3016// __| | __| | | | JSON for Modern C++
3017// | | |__ | | | | | | version 3.11.3
3018// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3019//
3020// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3021// SPDX-License-Identifier: MIT
3022
3023
3024
3025#include <cstddef> // size_t
3026
3027// #include <nlohmann/detail/abi_macros.hpp>
3028
3029
3030NLOHMANN_JSON_NAMESPACE_BEGIN
3031namespace detail
3032{
3033
3035struct position_t
3036{
3038 std::size_t chars_read_total = 0;
3042 std::size_t lines_read = 0;
3043
3045 constexpr operator size_t() const
3046 {
3047 return chars_read_total;
3048 }
3049};
3050
3051} // namespace detail
3052NLOHMANN_JSON_NAMESPACE_END
3053
3054// #include <nlohmann/detail/macro_scope.hpp>
3055
3056// #include <nlohmann/detail/meta/cpp_future.hpp>
3057// __ _____ _____ _____
3058// __| | __| | | | JSON for Modern C++
3059// | | |__ | | | | | | version 3.11.3
3060// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3061//
3062// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3063// SPDX-FileCopyrightText: 2018 The Abseil Authors
3064// SPDX-License-Identifier: MIT
3065
3066
3067
3068#include <array> // array
3069#include <cstddef> // size_t
3070#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3071#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3072
3073// #include <nlohmann/detail/macro_scope.hpp>
3074
3075
3076NLOHMANN_JSON_NAMESPACE_BEGIN
3077namespace detail
3078{
3079
3080template<typename T>
3081using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3082
3083#ifdef JSON_HAS_CPP_14
3084
3085// the following utilities are natively available in C++14
3086using std::enable_if_t;
3087using std::index_sequence;
3088using std::make_index_sequence;
3089using std::index_sequence_for;
3090
3091#else
3092
3093// alias templates to reduce boilerplate
3094template<bool B, typename T = void>
3095using enable_if_t = typename std::enable_if<B, T>::type;
3096
3097// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3098// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3099
3101
3102// integer_sequence
3103//
3104// Class template representing a compile-time integer sequence. An instantiation
3105// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3106// type through its template arguments (which is a common need when
3107// working with C++11 variadic templates). `absl::integer_sequence` is designed
3108// to be a drop-in replacement for C++14's `std::integer_sequence`.
3109//
3110// Example:
3111//
3112// template< class T, T... Ints >
3113// void user_function(integer_sequence<T, Ints...>);
3114//
3115// int main()
3116// {
3117// // user_function's `T` will be deduced to `int` and `Ints...`
3118// // will be deduced to `0, 1, 2, 3, 4`.
3119// user_function(make_integer_sequence<int, 5>());
3120// }
3121template <typename T, T... Ints>
3122struct integer_sequence
3123{
3124 using value_type = T;
3125 static constexpr std::size_t size() noexcept
3126 {
3127 return sizeof...(Ints);
3128 }
3129};
3130
3131// index_sequence
3132//
3133// A helper template for an `integer_sequence` of `size_t`,
3134// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3135// `std::index_sequence`.
3136template <size_t... Ints>
3137using index_sequence = integer_sequence<size_t, Ints...>;
3138
3139namespace utility_internal
3140{
3141
3142template <typename Seq, size_t SeqSize, size_t Rem>
3143struct Extend;
3144
3145// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3146template <typename T, T... Ints, size_t SeqSize>
3147struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3148{
3149 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3150};
3151
3152template <typename T, T... Ints, size_t SeqSize>
3153struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3154{
3155 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3156};
3157
3158// Recursion helper for 'make_integer_sequence<T, N>'.
3159// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3160template <typename T, size_t N>
3161struct Gen
3162{
3163 using type =
3164 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3165};
3166
3167template <typename T>
3168struct Gen<T, 0>
3169{
3170 using type = integer_sequence<T>;
3171};
3172
3173} // namespace utility_internal
3174
3175// Compile-time sequences of integers
3176
3177// make_integer_sequence
3178//
3179// This template alias is equivalent to
3180// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3181// replacement for C++14's `std::make_integer_sequence`.
3182template <typename T, T N>
3183using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3184
3185// make_index_sequence
3186//
3187// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3188// and is designed to be a drop-in replacement for C++14's
3189// `std::make_index_sequence`.
3190template <size_t N>
3191using make_index_sequence = make_integer_sequence<size_t, N>;
3192
3193// index_sequence_for
3194//
3195// Converts a typename pack into an index sequence of the same length, and
3196// is designed to be a drop-in replacement for C++14's
3197// `std::index_sequence_for()`
3198template <typename... Ts>
3199using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3200
3202
3203#endif
3204
3205// dispatch utility (taken from ranges-v3)
3206template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3207template<> struct priority_tag<0> {};
3208
3209// taken from ranges-v3
3210template<typename T>
3211struct static_const
3212{
3213 static JSON_INLINE_VARIABLE constexpr T value{};
3214};
3215
3216#ifndef JSON_HAS_CPP_17
3217 template<typename T>
3218 constexpr T static_const<T>::value;
3219#endif
3220
3221template<typename T, typename... Args>
3222inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3223{
3224 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3225}
3226
3227} // namespace detail
3228NLOHMANN_JSON_NAMESPACE_END
3229
3230// #include <nlohmann/detail/meta/type_traits.hpp>
3231// __ _____ _____ _____
3232// __| | __| | | | JSON for Modern C++
3233// | | |__ | | | | | | version 3.11.3
3234// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3235//
3236// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3237// SPDX-License-Identifier: MIT
3238
3239
3240
3241#include <limits> // numeric_limits
3242#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3243#include <utility> // declval
3244#include <tuple> // tuple
3245#include <string> // char_traits
3246
3247// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3248// __ _____ _____ _____
3249// __| | __| | | | JSON for Modern C++
3250// | | |__ | | | | | | version 3.11.3
3251// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3252//
3253// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3254// SPDX-License-Identifier: MIT
3255
3256
3257
3258#include <iterator> // random_access_iterator_tag
3259
3260// #include <nlohmann/detail/abi_macros.hpp>
3261
3262// #include <nlohmann/detail/meta/void_t.hpp>
3263
3264// #include <nlohmann/detail/meta/cpp_future.hpp>
3265
3266
3267NLOHMANN_JSON_NAMESPACE_BEGIN
3268namespace detail
3269{
3270
3271template<typename It, typename = void>
3272struct iterator_types {};
3273
3274template<typename It>
3275struct iterator_types <
3276 It,
3277 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3278 typename It::reference, typename It::iterator_category >>
3279{
3280 using difference_type = typename It::difference_type;
3281 using value_type = typename It::value_type;
3282 using pointer = typename It::pointer;
3283 using reference = typename It::reference;
3284 using iterator_category = typename It::iterator_category;
3285};
3286
3287// This is required as some compilers implement std::iterator_traits in a way that
3288// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3289template<typename T, typename = void>
3290struct iterator_traits
3291{
3292};
3293
3294template<typename T>
3295struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3296 : iterator_types<T>
3297{
3298};
3299
3300template<typename T>
3301struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
3302{
3303 using iterator_category = std::random_access_iterator_tag;
3304 using value_type = T;
3305 using difference_type = ptrdiff_t;
3306 using pointer = T*;
3307 using reference = T&;
3308};
3309
3310} // namespace detail
3311NLOHMANN_JSON_NAMESPACE_END
3312
3313// #include <nlohmann/detail/macro_scope.hpp>
3314
3315// #include <nlohmann/detail/meta/call_std/begin.hpp>
3316// __ _____ _____ _____
3317// __| | __| | | | JSON for Modern C++
3318// | | |__ | | | | | | version 3.11.3
3319// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3320//
3321// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3322// SPDX-License-Identifier: MIT
3323
3324
3325
3326// #include <nlohmann/detail/macro_scope.hpp>
3327
3328
3329NLOHMANN_JSON_NAMESPACE_BEGIN
3330
3331NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3332
3333NLOHMANN_JSON_NAMESPACE_END
3334
3335// #include <nlohmann/detail/meta/call_std/end.hpp>
3336// __ _____ _____ _____
3337// __| | __| | | | JSON for Modern C++
3338// | | |__ | | | | | | version 3.11.3
3339// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3340//
3341// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3342// SPDX-License-Identifier: MIT
3343
3344
3345
3346// #include <nlohmann/detail/macro_scope.hpp>
3347
3348
3349NLOHMANN_JSON_NAMESPACE_BEGIN
3350
3351NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3352
3353NLOHMANN_JSON_NAMESPACE_END
3354
3355// #include <nlohmann/detail/meta/cpp_future.hpp>
3356
3357// #include <nlohmann/detail/meta/detected.hpp>
3358
3359// #include <nlohmann/json_fwd.hpp>
3360// __ _____ _____ _____
3361// __| | __| | | | JSON for Modern C++
3362// | | |__ | | | | | | version 3.11.3
3363// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3364//
3365// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3366// SPDX-License-Identifier: MIT
3367
3368#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3369 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3370
3371 #include <cstdint> // int64_t, uint64_t
3372 #include <map> // map
3373 #include <memory> // allocator
3374 #include <string> // string
3375 #include <vector> // vector
3376
3377 // #include <nlohmann/detail/abi_macros.hpp>
3378
3379
3385 NLOHMANN_JSON_NAMESPACE_BEGIN
3386
3394 template<typename T = void, typename SFINAE = void>
3395 struct adl_serializer;
3396
3399 template<template<typename U, typename V, typename... Args> class ObjectType =
3400 std::map,
3401 template<typename U, typename... Args> class ArrayType = std::vector,
3402 class StringType = std::string, class BooleanType = bool,
3403 class NumberIntegerType = std::int64_t,
3404 class NumberUnsignedType = std::uint64_t,
3405 class NumberFloatType = double,
3406 template<typename U> class AllocatorType = std::allocator,
3407 template<typename T, typename SFINAE = void> class JSONSerializer =
3409 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3410 class CustomBaseClass = void>
3411 class basic_json;
3412
3415 template<typename RefStringType>
3416 class json_pointer;
3417
3422 using json = basic_json<>;
3423
3426 template<class Key, class T, class IgnoredLess, class Allocator>
3427 struct ordered_map;
3428
3432
3433 NLOHMANN_JSON_NAMESPACE_END
3434
3435#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3436
3437
3438NLOHMANN_JSON_NAMESPACE_BEGIN
3447namespace detail
3448{
3449
3451// helpers //
3453
3454// Note to maintainers:
3455//
3456// Every trait in this file expects a non CV-qualified type.
3457// The only exceptions are in the 'aliases for detected' section
3458// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3459//
3460// In this case, T has to be properly CV-qualified to constraint the function arguments
3461// (e.g. to_json(BasicJsonType&, const T&))
3462
3463template<typename> struct is_basic_json : std::false_type {};
3464
3465NLOHMANN_BASIC_JSON_TPL_DECLARATION
3466struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3467
3468// used by exceptions create() member functions
3469// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3470// false_type otherwise
3471template<typename BasicJsonContext>
3472struct is_basic_json_context :
3473 std::integral_constant < bool,
3474 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3475 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3476{};
3477
3479// json_ref helpers //
3481
3482template<typename>
3483class json_ref;
3484
3485template<typename>
3486struct is_json_ref : std::false_type {};
3487
3488template<typename T>
3489struct is_json_ref<json_ref<T>> : std::true_type {};
3490
3492// aliases for detected //
3494
3495template<typename T>
3496using mapped_type_t = typename T::mapped_type;
3497
3498template<typename T>
3499using key_type_t = typename T::key_type;
3500
3501template<typename T>
3502using value_type_t = typename T::value_type;
3503
3504template<typename T>
3505using difference_type_t = typename T::difference_type;
3506
3507template<typename T>
3508using pointer_t = typename T::pointer;
3509
3510template<typename T>
3511using reference_t = typename T::reference;
3512
3513template<typename T>
3514using iterator_category_t = typename T::iterator_category;
3515
3516template<typename T, typename... Args>
3517using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3518
3519template<typename T, typename... Args>
3520using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3521
3522template<typename T, typename U>
3523using get_template_function = decltype(std::declval<T>().template get<U>());
3524
3525// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3526template<typename BasicJsonType, typename T, typename = void>
3527struct has_from_json : std::false_type {};
3528
3529// trait checking if j.get<T> is valid
3530// use this trait instead of std::is_constructible or std::is_convertible,
3531// both rely on, or make use of implicit conversions, and thus fail when T
3532// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3533template <typename BasicJsonType, typename T>
3534struct is_getable
3535{
3536 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3537};
3538
3539template<typename BasicJsonType, typename T>
3540struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3541{
3542 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3543
3544 static constexpr bool value =
3545 is_detected_exact<void, from_json_function, serializer,
3546 const BasicJsonType&, T&>::value;
3547};
3548
3549// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3550// this overload is used for non-default-constructible user-defined-types
3551template<typename BasicJsonType, typename T, typename = void>
3552struct has_non_default_from_json : std::false_type {};
3553
3554template<typename BasicJsonType, typename T>
3555struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3556{
3557 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3558
3559 static constexpr bool value =
3560 is_detected_exact<T, from_json_function, serializer,
3561 const BasicJsonType&>::value;
3562};
3563
3564// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3565// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3566template<typename BasicJsonType, typename T, typename = void>
3567struct has_to_json : std::false_type {};
3568
3569template<typename BasicJsonType, typename T>
3570struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3571{
3572 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3573
3574 static constexpr bool value =
3575 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3576 T>::value;
3577};
3578
3579template<typename T>
3580using detect_key_compare = typename T::key_compare;
3581
3582template<typename T>
3583struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3584
3585// obtains the actual object key comparator
3586template<typename BasicJsonType>
3587struct actual_object_comparator
3588{
3589 using object_t = typename BasicJsonType::object_t;
3590 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3591 using type = typename std::conditional < has_key_compare<object_t>::value,
3592 typename object_t::key_compare, object_comparator_t>::type;
3593};
3594
3595template<typename BasicJsonType>
3596using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
3597
3599// char_traits //
3601
3602// Primary template of char_traits calls std char_traits
3603template<typename T>
3604struct char_traits : std::char_traits<T>
3605{};
3606
3607// Explicitly define char traits for unsigned char since it is not standard
3608template<>
3609struct char_traits<unsigned char> : std::char_traits<char>
3610{
3611 using char_type = unsigned char;
3612 using int_type = uint64_t;
3613
3614 // Redefine to_int_type function
3615 static int_type to_int_type(char_type c) noexcept
3616 {
3617 return static_cast<int_type>(c);
3618 }
3619
3620 static char_type to_char_type(int_type i) noexcept
3621 {
3622 return static_cast<char_type>(i);
3623 }
3624
3625 static constexpr int_type eof() noexcept
3626 {
3627 return static_cast<int_type>(EOF);
3628 }
3629};
3630
3631// Explicitly define char traits for signed char since it is not standard
3632template<>
3633struct char_traits<signed char> : std::char_traits<char>
3634{
3635 using char_type = signed char;
3636 using int_type = uint64_t;
3637
3638 // Redefine to_int_type function
3639 static int_type to_int_type(char_type c) noexcept
3640 {
3641 return static_cast<int_type>(c);
3642 }
3643
3644 static char_type to_char_type(int_type i) noexcept
3645 {
3646 return static_cast<char_type>(i);
3647 }
3648
3649 static constexpr int_type eof() noexcept
3650 {
3651 return static_cast<int_type>(EOF);
3652 }
3653};
3654
3656// is_ functions //
3658
3659// https://en.cppreference.com/w/cpp/types/conjunction
3660template<class...> struct conjunction : std::true_type { };
3661template<class B> struct conjunction<B> : B { };
3662template<class B, class... Bn>
3663struct conjunction<B, Bn...>
3664: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3665
3666// https://en.cppreference.com/w/cpp/types/negation
3667template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3668
3669// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3670// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3671// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3672template <typename T>
3673struct is_default_constructible : std::is_default_constructible<T> {};
3674
3675template <typename T1, typename T2>
3676struct is_default_constructible<std::pair<T1, T2>>
3677 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3678
3679template <typename T1, typename T2>
3680struct is_default_constructible<const std::pair<T1, T2>>
3681 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3682
3683template <typename... Ts>
3684struct is_default_constructible<std::tuple<Ts...>>
3685 : conjunction<is_default_constructible<Ts>...> {};
3686
3687template <typename... Ts>
3688struct is_default_constructible<const std::tuple<Ts...>>
3689 : conjunction<is_default_constructible<Ts>...> {};
3690
3691template <typename T, typename... Args>
3692struct is_constructible : std::is_constructible<T, Args...> {};
3693
3694template <typename T1, typename T2>
3695struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3696
3697template <typename T1, typename T2>
3698struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3699
3700template <typename... Ts>
3701struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3702
3703template <typename... Ts>
3704struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3705
3706template<typename T, typename = void>
3707struct is_iterator_traits : std::false_type {};
3708
3709template<typename T>
3710struct is_iterator_traits<iterator_traits<T>>
3711{
3712 private:
3713 using traits = iterator_traits<T>;
3714
3715 public:
3716 static constexpr auto value =
3717 is_detected<value_type_t, traits>::value &&
3718 is_detected<difference_type_t, traits>::value &&
3719 is_detected<pointer_t, traits>::value &&
3720 is_detected<iterator_category_t, traits>::value &&
3721 is_detected<reference_t, traits>::value;
3722};
3723
3724template<typename T>
3725struct is_range
3726{
3727 private:
3728 using t_ref = typename std::add_lvalue_reference<T>::type;
3729
3730 using iterator = detected_t<result_of_begin, t_ref>;
3731 using sentinel = detected_t<result_of_end, t_ref>;
3732
3733 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3734 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3735 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3736 static constexpr auto is_iterator_begin =
3737 is_iterator_traits<iterator_traits<iterator>>::value;
3738
3739 public:
3740 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3741};
3742
3743template<typename R>
3744using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3745
3746template<typename T>
3747using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3748
3749// The following implementation of is_complete_type is taken from
3750// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3751// and is written by Xiang Fan who agreed to using it in this library.
3752
3753template<typename T, typename = void>
3754struct is_complete_type : std::false_type {};
3755
3756template<typename T>
3757struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3758
3759template<typename BasicJsonType, typename CompatibleObjectType,
3760 typename = void>
3761struct is_compatible_object_type_impl : std::false_type {};
3762
3763template<typename BasicJsonType, typename CompatibleObjectType>
3764struct is_compatible_object_type_impl <
3765 BasicJsonType, CompatibleObjectType,
3766 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3767 is_detected<key_type_t, CompatibleObjectType>::value >>
3768{
3769 using object_t = typename BasicJsonType::object_t;
3770
3771 // macOS's is_constructible does not play well with nonesuch...
3772 static constexpr bool value =
3773 is_constructible<typename object_t::key_type,
3774 typename CompatibleObjectType::key_type>::value &&
3775 is_constructible<typename object_t::mapped_type,
3776 typename CompatibleObjectType::mapped_type>::value;
3777};
3778
3779template<typename BasicJsonType, typename CompatibleObjectType>
3780struct is_compatible_object_type
3781 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3782
3783template<typename BasicJsonType, typename ConstructibleObjectType,
3784 typename = void>
3785struct is_constructible_object_type_impl : std::false_type {};
3786
3787template<typename BasicJsonType, typename ConstructibleObjectType>
3788struct is_constructible_object_type_impl <
3789 BasicJsonType, ConstructibleObjectType,
3790 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3791 is_detected<key_type_t, ConstructibleObjectType>::value >>
3792{
3793 using object_t = typename BasicJsonType::object_t;
3794
3795 static constexpr bool value =
3796 (is_default_constructible<ConstructibleObjectType>::value &&
3797 (std::is_move_assignable<ConstructibleObjectType>::value ||
3798 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3799 (is_constructible<typename ConstructibleObjectType::key_type,
3800 typename object_t::key_type>::value &&
3801 std::is_same <
3802 typename object_t::mapped_type,
3803 typename ConstructibleObjectType::mapped_type >::value)) ||
3804 (has_from_json<BasicJsonType,
3805 typename ConstructibleObjectType::mapped_type>::value ||
3806 has_non_default_from_json <
3807 BasicJsonType,
3808 typename ConstructibleObjectType::mapped_type >::value);
3809};
3810
3811template<typename BasicJsonType, typename ConstructibleObjectType>
3812struct is_constructible_object_type
3813 : is_constructible_object_type_impl<BasicJsonType,
3814 ConstructibleObjectType> {};
3815
3816template<typename BasicJsonType, typename CompatibleStringType>
3817struct is_compatible_string_type
3818{
3819 static constexpr auto value =
3820 is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
3821};
3822
3823template<typename BasicJsonType, typename ConstructibleStringType>
3824struct is_constructible_string_type
3825{
3826 // launder type through decltype() to fix compilation failure on ICPC
3827#ifdef __INTEL_COMPILER
3828 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3829#else
3830 using laundered_type = ConstructibleStringType;
3831#endif
3832
3833 static constexpr auto value =
3834 conjunction <
3835 is_constructible<laundered_type, typename BasicJsonType::string_t>,
3836 is_detected_exact<typename BasicJsonType::string_t::value_type,
3837 value_type_t, laundered_type >>::value;
3838};
3839
3840template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3841struct is_compatible_array_type_impl : std::false_type {};
3842
3843template<typename BasicJsonType, typename CompatibleArrayType>
3844struct is_compatible_array_type_impl <
3845 BasicJsonType, CompatibleArrayType,
3846 enable_if_t <
3847 is_detected<iterator_t, CompatibleArrayType>::value&&
3848 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3849// special case for types like std::filesystem::path whose iterator's value_type are themselves
3850// c.f. https://github.com/nlohmann/json/pull/3073
3851 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3852{
3853 static constexpr bool value =
3854 is_constructible<BasicJsonType,
3855 range_value_t<CompatibleArrayType>>::value;
3856};
3857
3858template<typename BasicJsonType, typename CompatibleArrayType>
3859struct is_compatible_array_type
3860 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3861
3862template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3863struct is_constructible_array_type_impl : std::false_type {};
3864
3865template<typename BasicJsonType, typename ConstructibleArrayType>
3866struct is_constructible_array_type_impl <
3867 BasicJsonType, ConstructibleArrayType,
3868 enable_if_t<std::is_same<ConstructibleArrayType,
3869 typename BasicJsonType::value_type>::value >>
3870 : std::true_type {};
3871
3872template<typename BasicJsonType, typename ConstructibleArrayType>
3873struct is_constructible_array_type_impl <
3874 BasicJsonType, ConstructibleArrayType,
3875 enable_if_t < !std::is_same<ConstructibleArrayType,
3876 typename BasicJsonType::value_type>::value&&
3877 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3878 is_default_constructible<ConstructibleArrayType>::value&&
3879(std::is_move_assignable<ConstructibleArrayType>::value ||
3880 std::is_copy_assignable<ConstructibleArrayType>::value)&&
3881is_detected<iterator_t, ConstructibleArrayType>::value&&
3882is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3883is_detected<range_value_t, ConstructibleArrayType>::value&&
3884// special case for types like std::filesystem::path whose iterator's value_type are themselves
3885// c.f. https://github.com/nlohmann/json/pull/3073
3886!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3887 is_complete_type <
3888 detected_t<range_value_t, ConstructibleArrayType >>::value >>
3889{
3890 using value_type = range_value_t<ConstructibleArrayType>;
3891
3892 static constexpr bool value =
3893 std::is_same<value_type,
3894 typename BasicJsonType::array_t::value_type>::value ||
3895 has_from_json<BasicJsonType,
3896 value_type>::value ||
3897 has_non_default_from_json <
3898 BasicJsonType,
3899 value_type >::value;
3900};
3901
3902template<typename BasicJsonType, typename ConstructibleArrayType>
3903struct is_constructible_array_type
3904 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3905
3906template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3907 typename = void>
3908struct is_compatible_integer_type_impl : std::false_type {};
3909
3910template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3911struct is_compatible_integer_type_impl <
3912 RealIntegerType, CompatibleNumberIntegerType,
3913 enable_if_t < std::is_integral<RealIntegerType>::value&&
3914 std::is_integral<CompatibleNumberIntegerType>::value&&
3915 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3916{
3917 // is there an assert somewhere on overflows?
3918 using RealLimits = std::numeric_limits<RealIntegerType>;
3919 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3920
3921 static constexpr auto value =
3922 is_constructible<RealIntegerType,
3923 CompatibleNumberIntegerType>::value &&
3924 CompatibleLimits::is_integer &&
3925 RealLimits::is_signed == CompatibleLimits::is_signed;
3926};
3927
3928template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3929struct is_compatible_integer_type
3930 : is_compatible_integer_type_impl<RealIntegerType,
3931 CompatibleNumberIntegerType> {};
3932
3933template<typename BasicJsonType, typename CompatibleType, typename = void>
3934struct is_compatible_type_impl: std::false_type {};
3935
3936template<typename BasicJsonType, typename CompatibleType>
3937struct is_compatible_type_impl <
3938 BasicJsonType, CompatibleType,
3939 enable_if_t<is_complete_type<CompatibleType>::value >>
3940{
3941 static constexpr bool value =
3942 has_to_json<BasicJsonType, CompatibleType>::value;
3943};
3944
3945template<typename BasicJsonType, typename CompatibleType>
3946struct is_compatible_type
3947 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3948
3949template<typename T1, typename T2>
3950struct is_constructible_tuple : std::false_type {};
3951
3952template<typename T1, typename... Args>
3953struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3954
3955template<typename BasicJsonType, typename T>
3956struct is_json_iterator_of : std::false_type {};
3957
3958template<typename BasicJsonType>
3959struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
3960
3961template<typename BasicJsonType>
3962struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
3963{};
3964
3965// checks if a given type T is a template specialization of Primary
3966template<template <typename...> class Primary, typename T>
3967struct is_specialization_of : std::false_type {};
3968
3969template<template <typename...> class Primary, typename... Args>
3970struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
3971
3972template<typename T>
3973using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
3974
3975// checks if A and B are comparable using Compare functor
3976template<typename Compare, typename A, typename B, typename = void>
3977struct is_comparable : std::false_type {};
3978
3979template<typename Compare, typename A, typename B>
3980struct is_comparable<Compare, A, B, void_t<
3981decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
3982decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
3983>> : std::true_type {};
3984
3985template<typename T>
3986using detect_is_transparent = typename T::is_transparent;
3987
3988// type trait to check if KeyType can be used as object key (without a BasicJsonType)
3989// see is_usable_as_basic_json_key_type below
3990template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
3991 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
3992using is_usable_as_key_type = typename std::conditional <
3993 is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
3994 && !(ExcludeObjectKeyType && std::is_same<KeyType,
3995 ObjectKeyType>::value)
3996 && (!RequireTransparentComparator
3997 || is_detected <detect_is_transparent, Comparator>::value)
3998 && !is_json_pointer<KeyType>::value,
3999 std::true_type,
4000 std::false_type >::type;
4001
4002// type trait to check if KeyType can be used as object key
4003// true if:
4004// - KeyType is comparable with BasicJsonType::object_t::key_type
4005// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4006// - the comparator is transparent or RequireTransparentComparator is false
4007// - KeyType is not a JSON iterator or json_pointer
4008template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4009 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4010using is_usable_as_basic_json_key_type = typename std::conditional <
4011 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4012 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4013 RequireTransparentComparator, ExcludeObjectKeyType>::value
4014 && !is_json_iterator_of<BasicJsonType, KeyType>::value,
4015 std::true_type,
4016 std::false_type >::type;
4017
4018template<typename ObjectType, typename KeyType>
4019using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4020
4021// type trait to check if object_t has an erase() member functions accepting KeyType
4022template<typename BasicJsonType, typename KeyType>
4023using has_erase_with_key_type = typename std::conditional <
4024 is_detected <
4025 detect_erase_with_key_type,
4026 typename BasicJsonType::object_t, KeyType >::value,
4027 std::true_type,
4028 std::false_type >::type;
4029
4030// a naive helper to check if a type is an ordered_map (exploits the fact that
4031// ordered_map inherits capacity() from std::vector)
4032template <typename T>
4033struct is_ordered_map
4034{
4035 using one = char;
4036
4037 struct two
4038 {
4039 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4040 };
4041
4042 template <typename C> static one test( decltype(&C::capacity) ) ;
4043 template <typename C> static two test(...);
4044
4045 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4046};
4047
4048// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4049template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4050T conditional_static_cast(U value)
4051{
4052 return static_cast<T>(value);
4053}
4054
4055template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4056T conditional_static_cast(U value)
4057{
4058 return value;
4059}
4060
4061template<typename... Types>
4062using all_integral = conjunction<std::is_integral<Types>...>;
4063
4064template<typename... Types>
4065using all_signed = conjunction<std::is_signed<Types>...>;
4066
4067template<typename... Types>
4068using all_unsigned = conjunction<std::is_unsigned<Types>...>;
4069
4070// there's a disjunction trait in another PR; replace when merged
4071template<typename... Types>
4072using same_sign = std::integral_constant < bool,
4073 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4074
4075template<typename OfType, typename T>
4076using never_out_of_range = std::integral_constant < bool,
4077 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4078 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4079
4080template<typename OfType, typename T,
4081 bool OfTypeSigned = std::is_signed<OfType>::value,
4082 bool TSigned = std::is_signed<T>::value>
4083struct value_in_range_of_impl2;
4084
4085template<typename OfType, typename T>
4086struct value_in_range_of_impl2<OfType, T, false, false>
4087{
4088 static constexpr bool test(T val)
4089 {
4090 using CommonType = typename std::common_type<OfType, T>::type;
4091 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4092 }
4093};
4094
4095template<typename OfType, typename T>
4096struct value_in_range_of_impl2<OfType, T, true, false>
4097{
4098 static constexpr bool test(T val)
4099 {
4100 using CommonType = typename std::common_type<OfType, T>::type;
4101 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4102 }
4103};
4104
4105template<typename OfType, typename T>
4106struct value_in_range_of_impl2<OfType, T, false, true>
4107{
4108 static constexpr bool test(T val)
4109 {
4110 using CommonType = typename std::common_type<OfType, T>::type;
4111 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4112 }
4113};
4114
4115template<typename OfType, typename T>
4116struct value_in_range_of_impl2<OfType, T, true, true>
4117{
4118 static constexpr bool test(T val)
4119 {
4120 using CommonType = typename std::common_type<OfType, T>::type;
4121 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4122 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4123 }
4124};
4125
4126template<typename OfType, typename T,
4127 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4128 typename = detail::enable_if_t<all_integral<OfType, T>::value>>
4129struct value_in_range_of_impl1;
4130
4131template<typename OfType, typename T>
4132struct value_in_range_of_impl1<OfType, T, false>
4133{
4134 static constexpr bool test(T val)
4135 {
4136 return value_in_range_of_impl2<OfType, T>::test(val);
4137 }
4138};
4139
4140template<typename OfType, typename T>
4141struct value_in_range_of_impl1<OfType, T, true>
4142{
4143 static constexpr bool test(T /*val*/)
4144 {
4145 return true;
4146 }
4147};
4148
4149template<typename OfType, typename T>
4150inline constexpr bool value_in_range_of(T val)
4151{
4152 return value_in_range_of_impl1<OfType, T>::test(val);
4153}
4154
4155template<bool Value>
4156using bool_constant = std::integral_constant<bool, Value>;
4157
4159// is_c_string
4161
4162namespace impl
4163{
4164
4165template<typename T>
4166inline constexpr bool is_c_string()
4167{
4168 using TUnExt = typename std::remove_extent<T>::type;
4169 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4170 using TUnPtr = typename std::remove_pointer<T>::type;
4171 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4172 return
4173 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4174 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4175}
4176
4177} // namespace impl
4178
4179// checks whether T is a [cv] char */[cv] char[] C string
4180template<typename T>
4181struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4182
4183template<typename T>
4184using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
4185
4187// is_transparent
4189
4190namespace impl
4191{
4192
4193template<typename T>
4194inline constexpr bool is_transparent()
4195{
4196 return is_detected<detect_is_transparent, T>::value;
4197}
4198
4199} // namespace impl
4200
4201// checks whether T has a member named is_transparent
4202template<typename T>
4203struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4204
4206
4207} // namespace detail
4208NLOHMANN_JSON_NAMESPACE_END
4209
4210// #include <nlohmann/detail/string_concat.hpp>
4211// __ _____ _____ _____
4212// __| | __| | | | JSON for Modern C++
4213// | | |__ | | | | | | version 3.11.3
4214// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4215//
4216// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4217// SPDX-License-Identifier: MIT
4218
4219
4220
4221#include <cstring> // strlen
4222#include <string> // string
4223#include <utility> // forward
4224
4225// #include <nlohmann/detail/meta/cpp_future.hpp>
4226
4227// #include <nlohmann/detail/meta/detected.hpp>
4228
4229
4230NLOHMANN_JSON_NAMESPACE_BEGIN
4231namespace detail
4232{
4233
4234inline std::size_t concat_length()
4235{
4236 return 0;
4237}
4238
4239template<typename... Args>
4240inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4241
4242template<typename StringType, typename... Args>
4243inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4244
4245template<typename... Args>
4246inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4247{
4248 return 1 + concat_length(rest...);
4249}
4250
4251template<typename... Args>
4252inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4253{
4254 // cppcheck-suppress ignoredReturnValue
4255 return ::strlen(cstr) + concat_length(rest...);
4256}
4257
4258template<typename StringType, typename... Args>
4259inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4260{
4261 return str.size() + concat_length(rest...);
4262}
4263
4264template<typename OutStringType>
4265inline void concat_into(OutStringType& /*out*/)
4266{}
4267
4268template<typename StringType, typename Arg>
4269using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4270
4271template<typename StringType, typename Arg>
4272using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
4273
4274template<typename StringType, typename Arg>
4275using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4276
4277template<typename StringType, typename Arg>
4278using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
4279
4280template<typename StringType, typename Arg>
4281using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4282
4283template<typename StringType, typename Arg>
4284using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
4285
4286template<typename StringType, typename Arg>
4287using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4288
4289template<typename StringType, typename Arg>
4290using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
4291
4292template < typename OutStringType, typename Arg, typename... Args,
4293 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4294 && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
4295inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4296
4297template < typename OutStringType, typename Arg, typename... Args,
4298 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4299 && !detect_string_can_append_op<OutStringType, Arg>::value
4300 && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
4301inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4302
4303template < typename OutStringType, typename Arg, typename... Args,
4304 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4305 && !detect_string_can_append_op<OutStringType, Arg>::value
4306 && !detect_string_can_append_iter<OutStringType, Arg>::value
4307 && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
4308inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4309
4310template<typename OutStringType, typename Arg, typename... Args,
4311 enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
4312inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4313{
4314 out.append(std::forward<Arg>(arg));
4315 concat_into(out, std::forward<Args>(rest)...);
4316}
4317
4318template < typename OutStringType, typename Arg, typename... Args,
4319 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4320 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4321inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4322{
4323 out += std::forward<Arg>(arg);
4324 concat_into(out, std::forward<Args>(rest)...);
4325}
4326
4327template < typename OutStringType, typename Arg, typename... Args,
4328 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4329 && !detect_string_can_append_op<OutStringType, Arg>::value
4330 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4331inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4332{
4333 out.append(arg.begin(), arg.end());
4334 concat_into(out, std::forward<Args>(rest)...);
4335}
4336
4337template < typename OutStringType, typename Arg, typename... Args,
4338 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4339 && !detect_string_can_append_op<OutStringType, Arg>::value
4340 && !detect_string_can_append_iter<OutStringType, Arg>::value
4341 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4342inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4343{
4344 out.append(arg.data(), arg.size());
4345 concat_into(out, std::forward<Args>(rest)...);
4346}
4347
4348template<typename OutStringType = std::string, typename... Args>
4349inline OutStringType concat(Args && ... args)
4350{
4351 OutStringType str;
4352 str.reserve(concat_length(args...));
4353 concat_into(str, std::forward<Args>(args)...);
4354 return str;
4355}
4356
4357} // namespace detail
4358NLOHMANN_JSON_NAMESPACE_END
4359
4360
4361NLOHMANN_JSON_NAMESPACE_BEGIN
4362namespace detail
4363{
4364
4366// exceptions //
4368
4371class exception : public std::exception
4372{
4373 public:
4375 const char* what() const noexcept override
4376 {
4377 return m.what();
4378 }
4379
4381 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4382
4383 protected:
4384 JSON_HEDLEY_NON_NULL(3)
4385 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4386
4387 static std::string name(const std::string& ename, int id_)
4388 {
4389 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4390 }
4391
4392 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4393 {
4394 return "";
4395 }
4396
4397 template<typename BasicJsonType>
4398 static std::string diagnostics(const BasicJsonType* leaf_element)
4399 {
4400#if JSON_DIAGNOSTICS
4401 std::vector<std::string> tokens;
4402 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4403 {
4404 switch (current->m_parent->type())
4405 {
4406 case value_t::array:
4407 {
4408 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4409 {
4410 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4411 {
4412 tokens.emplace_back(std::to_string(i));
4413 break;
4414 }
4415 }
4416 break;
4417 }
4418
4419 case value_t::object:
4420 {
4421 for (const auto& element : *current->m_parent->m_data.m_value.object)
4422 {
4423 if (&element.second == current)
4424 {
4425 tokens.emplace_back(element.first.c_str());
4426 break;
4427 }
4428 }
4429 break;
4430 }
4431
4432 case value_t::null: // LCOV_EXCL_LINE
4433 case value_t::string: // LCOV_EXCL_LINE
4434 case value_t::boolean: // LCOV_EXCL_LINE
4435 case value_t::number_integer: // LCOV_EXCL_LINE
4436 case value_t::number_unsigned: // LCOV_EXCL_LINE
4437 case value_t::number_float: // LCOV_EXCL_LINE
4438 case value_t::binary: // LCOV_EXCL_LINE
4439 case value_t::discarded: // LCOV_EXCL_LINE
4440 default: // LCOV_EXCL_LINE
4441 break; // LCOV_EXCL_LINE
4442 }
4443 }
4444
4445 if (tokens.empty())
4446 {
4447 return "";
4448 }
4449
4450 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4451 [](const std::string & a, const std::string & b)
4452 {
4453 return concat(a, '/', detail::escape(b));
4454 });
4455 return concat('(', str, ") ");
4456#else
4457 static_cast<void>(leaf_element);
4458 return "";
4459#endif
4460 }
4461
4462 private:
4464 std::runtime_error m;
4465};
4466
4469class parse_error : public exception
4470{
4471 public:
4481 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4482 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4483 {
4484 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4485 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4486 return {id_, pos.chars_read_total, w.c_str()};
4487 }
4488
4489 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4490 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4491 {
4492 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4493 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4494 ": ", exception::diagnostics(context), what_arg);
4495 return {id_, byte_, w.c_str()};
4496 }
4497
4507 const std::size_t byte;
4508
4509 private:
4510 parse_error(int id_, std::size_t byte_, const char* what_arg)
4511 : exception(id_, what_arg), byte(byte_) {}
4512
4513 static std::string position_string(const position_t& pos)
4514 {
4515 return concat(" at line ", std::to_string(pos.lines_read + 1),
4516 ", column ", std::to_string(pos.chars_read_current_line));
4517 }
4518};
4519
4522class invalid_iterator : public exception
4523{
4524 public:
4525 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4526 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4527 {
4528 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4529 return {id_, w.c_str()};
4530 }
4531
4532 private:
4533 JSON_HEDLEY_NON_NULL(3)
4534 invalid_iterator(int id_, const char* what_arg)
4535 : exception(id_, what_arg) {}
4536};
4537
4540class type_error : public exception
4541{
4542 public:
4543 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4544 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4545 {
4546 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4547 return {id_, w.c_str()};
4548 }
4549
4550 private:
4551 JSON_HEDLEY_NON_NULL(3)
4552 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4553};
4554
4557class out_of_range : public exception
4558{
4559 public:
4560 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4561 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4562 {
4563 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4564 return {id_, w.c_str()};
4565 }
4566
4567 private:
4568 JSON_HEDLEY_NON_NULL(3)
4569 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4570};
4571
4574class other_error : public exception
4575{
4576 public:
4577 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4578 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4579 {
4580 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4581 return {id_, w.c_str()};
4582 }
4583
4584 private:
4585 JSON_HEDLEY_NON_NULL(3)
4586 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4587};
4588
4589} // namespace detail
4590NLOHMANN_JSON_NAMESPACE_END
4591
4592// #include <nlohmann/detail/macro_scope.hpp>
4593
4594// #include <nlohmann/detail/meta/cpp_future.hpp>
4595
4596// #include <nlohmann/detail/meta/identity_tag.hpp>
4597// __ _____ _____ _____
4598// __| | __| | | | JSON for Modern C++
4599// | | |__ | | | | | | version 3.11.3
4600// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4601//
4602// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4603// SPDX-License-Identifier: MIT
4604
4605
4606
4607// #include <nlohmann/detail/abi_macros.hpp>
4608
4609
4610NLOHMANN_JSON_NAMESPACE_BEGIN
4611namespace detail
4612{
4613
4614// dispatching helper struct
4615template <class T> struct identity_tag {};
4616
4617} // namespace detail
4618NLOHMANN_JSON_NAMESPACE_END
4619
4620// #include <nlohmann/detail/meta/std_fs.hpp>
4621// __ _____ _____ _____
4622// __| | __| | | | JSON for Modern C++
4623// | | |__ | | | | | | version 3.11.3
4624// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4625//
4626// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4627// SPDX-License-Identifier: MIT
4628
4629
4630
4631// #include <nlohmann/detail/macro_scope.hpp>
4632
4633
4634#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4635#include <experimental/filesystem>
4636NLOHMANN_JSON_NAMESPACE_BEGIN
4637namespace detail
4638{
4639namespace std_fs = std::experimental::filesystem;
4640} // namespace detail
4641NLOHMANN_JSON_NAMESPACE_END
4642#elif JSON_HAS_FILESYSTEM
4643#include <filesystem>
4644NLOHMANN_JSON_NAMESPACE_BEGIN
4645namespace detail
4646{
4647namespace std_fs = std::filesystem;
4648} // namespace detail
4649NLOHMANN_JSON_NAMESPACE_END
4650#endif
4651
4652// #include <nlohmann/detail/meta/type_traits.hpp>
4653
4654// #include <nlohmann/detail/string_concat.hpp>
4655
4656// #include <nlohmann/detail/value_t.hpp>
4657
4658
4659NLOHMANN_JSON_NAMESPACE_BEGIN
4660namespace detail
4661{
4662
4663template<typename BasicJsonType>
4664inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4665{
4666 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4667 {
4668 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4669 }
4670 n = nullptr;
4671}
4672
4673// overloads for basic_json template parameters
4674template < typename BasicJsonType, typename ArithmeticType,
4675 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4676 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4677 int > = 0 >
4678void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4679{
4680 switch (static_cast<value_t>(j))
4681 {
4683 {
4684 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4685 break;
4686 }
4688 {
4689 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4690 break;
4691 }
4693 {
4694 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4695 break;
4696 }
4697
4698 case value_t::null:
4699 case value_t::object:
4700 case value_t::array:
4701 case value_t::string:
4702 case value_t::boolean:
4703 case value_t::binary:
4704 case value_t::discarded:
4705 default:
4706 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4707 }
4708}
4709
4710template<typename BasicJsonType>
4711inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4712{
4713 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4714 {
4715 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4716 }
4717 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4718}
4719
4720template<typename BasicJsonType>
4721inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4722{
4723 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4724 {
4725 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4726 }
4727 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4728}
4729
4730template <
4731 typename BasicJsonType, typename StringType,
4732 enable_if_t <
4733 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4734 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4735 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4736 && !is_json_ref<StringType>::value, int > = 0 >
4737inline void from_json(const BasicJsonType& j, StringType& s)
4738{
4739 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4740 {
4741 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4742 }
4743
4744 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4745}
4746
4747template<typename BasicJsonType>
4748inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4749{
4750 get_arithmetic_value(j, val);
4751}
4752
4753template<typename BasicJsonType>
4754inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4755{
4756 get_arithmetic_value(j, val);
4757}
4758
4759template<typename BasicJsonType>
4760inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4761{
4762 get_arithmetic_value(j, val);
4763}
4764
4765#if !JSON_DISABLE_ENUM_SERIALIZATION
4766template<typename BasicJsonType, typename EnumType,
4767 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4768inline void from_json(const BasicJsonType& j, EnumType& e)
4769{
4770 typename std::underlying_type<EnumType>::type val;
4771 get_arithmetic_value(j, val);
4772 e = static_cast<EnumType>(val);
4773}
4774#endif // JSON_DISABLE_ENUM_SERIALIZATION
4775
4776// forward_list doesn't have an insert method
4777template<typename BasicJsonType, typename T, typename Allocator,
4778 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4779inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4780{
4781 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4782 {
4783 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4784 }
4785 l.clear();
4786 std::transform(j.rbegin(), j.rend(),
4787 std::front_inserter(l), [](const BasicJsonType & i)
4788 {
4789 return i.template get<T>();
4790 });
4791}
4792
4793// valarray doesn't have an insert method
4794template<typename BasicJsonType, typename T,
4795 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4796inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4797{
4798 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4799 {
4800 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4801 }
4802 l.resize(j.size());
4803 std::transform(j.begin(), j.end(), std::begin(l),
4804 [](const BasicJsonType & elem)
4805 {
4806 return elem.template get<T>();
4807 });
4808}
4809
4810template<typename BasicJsonType, typename T, std::size_t N>
4811auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4812-> decltype(j.template get<T>(), void())
4813{
4814 for (std::size_t i = 0; i < N; ++i)
4815 {
4816 arr[i] = j.at(i).template get<T>();
4817 }
4818}
4819
4820template<typename BasicJsonType>
4821inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
4822{
4823 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4824}
4825
4826template<typename BasicJsonType, typename T, std::size_t N>
4827auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
4828 priority_tag<2> /*unused*/)
4829-> decltype(j.template get<T>(), void())
4830{
4831 for (std::size_t i = 0; i < N; ++i)
4832 {
4833 arr[i] = j.at(i).template get<T>();
4834 }
4835}
4836
4837template<typename BasicJsonType, typename ConstructibleArrayType,
4838 enable_if_t<
4839 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4840 int> = 0>
4841auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4842-> decltype(
4843 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4844 j.template get<typename ConstructibleArrayType::value_type>(),
4845 void())
4846{
4847 using std::end;
4848
4849 ConstructibleArrayType ret;
4850 ret.reserve(j.size());
4851 std::transform(j.begin(), j.end(),
4852 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4853 {
4854 // get<BasicJsonType>() returns *this, this won't call a from_json
4855 // method when value_type is BasicJsonType
4856 return i.template get<typename ConstructibleArrayType::value_type>();
4857 });
4858 arr = std::move(ret);
4859}
4860
4861template<typename BasicJsonType, typename ConstructibleArrayType,
4862 enable_if_t<
4863 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4864 int> = 0>
4865inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4866 priority_tag<0> /*unused*/)
4867{
4868 using std::end;
4869
4870 ConstructibleArrayType ret;
4871 std::transform(
4872 j.begin(), j.end(), std::inserter(ret, end(ret)),
4873 [](const BasicJsonType & i)
4874 {
4875 // get<BasicJsonType>() returns *this, this won't call a from_json
4876 // method when value_type is BasicJsonType
4877 return i.template get<typename ConstructibleArrayType::value_type>();
4878 });
4879 arr = std::move(ret);
4880}
4881
4882template < typename BasicJsonType, typename ConstructibleArrayType,
4883 enable_if_t <
4884 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4885 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4886 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4887 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4888 !is_basic_json<ConstructibleArrayType>::value,
4889 int > = 0 >
4890auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4891-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4892j.template get<typename ConstructibleArrayType::value_type>(),
4893void())
4894{
4895 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4896 {
4897 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4898 }
4899
4900 from_json_array_impl(j, arr, priority_tag<3> {});
4901}
4902
4903template < typename BasicJsonType, typename T, std::size_t... Idx >
4904std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4905 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4906{
4907 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4908}
4909
4910template < typename BasicJsonType, typename T, std::size_t N >
4911auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4912-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4913{
4914 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4915 {
4916 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4917 }
4918
4919 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4920}
4921
4922template<typename BasicJsonType>
4923inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4924{
4925 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4926 {
4927 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
4928 }
4929
4930 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4931}
4932
4933template<typename BasicJsonType, typename ConstructibleObjectType,
4934 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
4935inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4936{
4937 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4938 {
4939 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
4940 }
4941
4942 ConstructibleObjectType ret;
4943 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4944 using value_type = typename ConstructibleObjectType::value_type;
4945 std::transform(
4946 inner_object->begin(), inner_object->end(),
4947 std::inserter(ret, ret.begin()),
4948 [](typename BasicJsonType::object_t::value_type const & p)
4949 {
4950 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4951 });
4952 obj = std::move(ret);
4953}
4954
4955// overload for arithmetic types, not chosen for basic_json template arguments
4956// (BooleanType, etc..); note: Is it really necessary to provide explicit
4957// overloads for boolean_t etc. in case of a custom BooleanType which is not
4958// an arithmetic type?
4959template < typename BasicJsonType, typename ArithmeticType,
4960 enable_if_t <
4961 std::is_arithmetic<ArithmeticType>::value&&
4962 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
4963 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
4964 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
4965 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4966 int > = 0 >
4967inline void from_json(const BasicJsonType& j, ArithmeticType& val)
4968{
4969 switch (static_cast<value_t>(j))
4970 {
4972 {
4973 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4974 break;
4975 }
4977 {
4978 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4979 break;
4980 }
4982 {
4983 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4984 break;
4985 }
4986 case value_t::boolean:
4987 {
4988 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
4989 break;
4990 }
4991
4992 case value_t::null:
4993 case value_t::object:
4994 case value_t::array:
4995 case value_t::string:
4996 case value_t::binary:
4997 case value_t::discarded:
4998 default:
4999 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5000 }
5001}
5002
5003template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5004std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5005{
5006 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5007}
5008
5009template < typename BasicJsonType, class A1, class A2 >
5010std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5011{
5012 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5013 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5014}
5015
5016template<typename BasicJsonType, typename A1, typename A2>
5017inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5018{
5019 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5020}
5021
5022template<typename BasicJsonType, typename... Args>
5023std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5024{
5025 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5026}
5027
5028template<typename BasicJsonType, typename... Args>
5029inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5030{
5031 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5032}
5033
5034template<typename BasicJsonType, typename TupleRelated>
5035auto from_json(BasicJsonType&& j, TupleRelated&& t)
5036-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5037{
5038 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5039 {
5040 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5041 }
5042
5043 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5044}
5045
5046template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5047 typename = enable_if_t < !std::is_constructible <
5048 typename BasicJsonType::string_t, Key >::value >>
5049inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5050{
5051 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5052 {
5053 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5054 }
5055 m.clear();
5056 for (const auto& p : j)
5057 {
5058 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5059 {
5060 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5061 }
5062 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5063 }
5064}
5065
5066template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5067 typename = enable_if_t < !std::is_constructible <
5068 typename BasicJsonType::string_t, Key >::value >>
5069inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5070{
5071 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5072 {
5073 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5074 }
5075 m.clear();
5076 for (const auto& p : j)
5077 {
5078 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5079 {
5080 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5081 }
5082 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5083 }
5084}
5085
5086#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5087template<typename BasicJsonType>
5088inline void from_json(const BasicJsonType& j, std_fs::path& p)
5089{
5090 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5091 {
5092 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5093 }
5094 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5095}
5096#endif
5097
5098struct from_json_fn
5099{
5100 template<typename BasicJsonType, typename T>
5101 auto operator()(const BasicJsonType& j, T&& val) const
5102 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5103 -> decltype(from_json(j, std::forward<T>(val)))
5104 {
5105 return from_json(j, std::forward<T>(val));
5106 }
5107};
5108
5109} // namespace detail
5110
5111#ifndef JSON_HAS_CPP_17
5115namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5116{
5117#endif
5118JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5120#ifndef JSON_HAS_CPP_17
5121} // namespace
5122#endif
5123
5124NLOHMANN_JSON_NAMESPACE_END
5125
5126// #include <nlohmann/detail/conversions/to_json.hpp>
5127// __ _____ _____ _____
5128// __| | __| | | | JSON for Modern C++
5129// | | |__ | | | | | | version 3.11.3
5130// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5131//
5132// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5133// SPDX-License-Identifier: MIT
5134
5135
5136
5137#include <algorithm> // copy
5138#include <iterator> // begin, end
5139#include <string> // string
5140#include <tuple> // tuple, get
5141#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5142#include <utility> // move, forward, declval, pair
5143#include <valarray> // valarray
5144#include <vector> // vector
5145
5146// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5147// __ _____ _____ _____
5148// __| | __| | | | JSON for Modern C++
5149// | | |__ | | | | | | version 3.11.3
5150// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5151//
5152// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5153// SPDX-License-Identifier: MIT
5154
5155
5156
5157#include <cstddef> // size_t
5158#include <iterator> // input_iterator_tag
5159#include <string> // string, to_string
5160#include <tuple> // tuple_size, get, tuple_element
5161#include <utility> // move
5162
5163#if JSON_HAS_RANGES
5164 #include <ranges> // enable_borrowed_range
5165#endif
5166
5167// #include <nlohmann/detail/abi_macros.hpp>
5168
5169// #include <nlohmann/detail/meta/type_traits.hpp>
5170
5171// #include <nlohmann/detail/value_t.hpp>
5172
5173
5174NLOHMANN_JSON_NAMESPACE_BEGIN
5175namespace detail
5176{
5177
5178template<typename string_type>
5179void int_to_string( string_type& target, std::size_t value )
5180{
5181 // For ADL
5182 using std::to_string;
5183 target = to_string(value);
5184}
5185template<typename IteratorType> class iteration_proxy_value
5186{
5187 public:
5188 using difference_type = std::ptrdiff_t;
5189 using value_type = iteration_proxy_value;
5190 using pointer = value_type *;
5191 using reference = value_type &;
5192 using iterator_category = std::input_iterator_tag;
5193 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5194
5195 private:
5197 IteratorType anchor{};
5199 std::size_t array_index = 0;
5201 mutable std::size_t array_index_last = 0;
5203 mutable string_type array_index_str = "0";
5205 string_type empty_str{};
5206
5207 public:
5208 explicit iteration_proxy_value() = default;
5209 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5210 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5211 && std::is_nothrow_default_constructible<string_type>::value)
5212 : anchor(std::move(it))
5213 , array_index(array_index_)
5214 {}
5215
5216 iteration_proxy_value(iteration_proxy_value const&) = default;
5217 iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
5218 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5219 iteration_proxy_value(iteration_proxy_value&&)
5220 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5221 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5222 iteration_proxy_value& operator=(iteration_proxy_value&&)
5223 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5224 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5225 ~iteration_proxy_value() = default;
5226
5228 const iteration_proxy_value& operator*() const
5229 {
5230 return *this;
5231 }
5232
5235 {
5236 ++anchor;
5237 ++array_index;
5238
5239 return *this;
5240 }
5241
5242 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5243 {
5244 auto tmp = iteration_proxy_value(anchor, array_index);
5245 ++anchor;
5246 ++array_index;
5247 return tmp;
5248 }
5249
5252 {
5253 return anchor == o.anchor;
5254 }
5255
5258 {
5259 return anchor != o.anchor;
5260 }
5261
5263 const string_type& key() const
5264 {
5265 JSON_ASSERT(anchor.m_object != nullptr);
5266
5267 switch (anchor.m_object->type())
5268 {
5269 // use integer array index as key
5270 case value_t::array:
5271 {
5272 if (array_index != array_index_last)
5273 {
5274 int_to_string( array_index_str, array_index );
5275 array_index_last = array_index;
5276 }
5277 return array_index_str;
5278 }
5279
5280 // use key from the object
5281 case value_t::object:
5282 return anchor.key();
5283
5284 // use an empty key for all primitive types
5285 case value_t::null:
5286 case value_t::string:
5287 case value_t::boolean:
5291 case value_t::binary:
5292 case value_t::discarded:
5293 default:
5294 return empty_str;
5295 }
5296 }
5297
5299 typename IteratorType::reference value() const
5300 {
5301 return anchor.value();
5302 }
5303};
5304
5306template<typename IteratorType> class iteration_proxy
5307{
5308 private:
5310 typename IteratorType::pointer container = nullptr;
5311
5312 public:
5313 explicit iteration_proxy() = default;
5314
5316 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5317 : container(&cont) {}
5318
5319 iteration_proxy(iteration_proxy const&) = default;
5320 iteration_proxy& operator=(iteration_proxy const&) = default;
5321 iteration_proxy(iteration_proxy&&) noexcept = default;
5322 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5323 ~iteration_proxy() = default;
5324
5326 iteration_proxy_value<IteratorType> begin() const noexcept
5327 {
5328 return iteration_proxy_value<IteratorType>(container->begin());
5329 }
5330
5333 {
5334 return iteration_proxy_value<IteratorType>(container->end());
5335 }
5336};
5337
5338// Structured Bindings Support
5339// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5340// And see https://github.com/nlohmann/json/pull/1391
5341template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5342auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5343{
5344 return i.key();
5345}
5346// Structured Bindings Support
5347// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5348// And see https://github.com/nlohmann/json/pull/1391
5349template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5350auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5351{
5352 return i.value();
5353}
5354
5355} // namespace detail
5356NLOHMANN_JSON_NAMESPACE_END
5357
5358// The Addition to the STD Namespace is required to add
5359// Structured Bindings Support to the iteration_proxy_value class
5360// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5361// And see https://github.com/nlohmann/json/pull/1391
5362namespace std
5363{
5364
5365#if defined(__clang__)
5366 // Fix: https://github.com/nlohmann/json/issues/1401
5367 #pragma clang diagnostic push
5368 #pragma clang diagnostic ignored "-Wmismatched-tags"
5369#endif
5370template<typename IteratorType>
5371class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5372 : public std::integral_constant<std::size_t, 2> {};
5373
5374template<std::size_t N, typename IteratorType>
5375class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5376{
5377 public:
5378 using type = decltype(
5379 get<N>(std::declval <
5380 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5381};
5382#if defined(__clang__)
5383 #pragma clang diagnostic pop
5384#endif
5385
5386} // namespace std
5387
5388#if JSON_HAS_RANGES
5389 template <typename IteratorType>
5390 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5391#endif
5392
5393// #include <nlohmann/detail/macro_scope.hpp>
5394
5395// #include <nlohmann/detail/meta/cpp_future.hpp>
5396
5397// #include <nlohmann/detail/meta/std_fs.hpp>
5398
5399// #include <nlohmann/detail/meta/type_traits.hpp>
5400
5401// #include <nlohmann/detail/value_t.hpp>
5402
5403
5404NLOHMANN_JSON_NAMESPACE_BEGIN
5405namespace detail
5406{
5407
5409// constructors //
5411
5412/*
5413 * Note all external_constructor<>::construct functions need to call
5414 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5415 * allocated value (e.g., a string). See bug issue
5416 * https://github.com/nlohmann/json/issues/2865 for more information.
5417 */
5418
5419template<value_t> struct external_constructor;
5420
5421template<>
5422struct external_constructor<value_t::boolean>
5423{
5424 template<typename BasicJsonType>
5425 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5426 {
5427 j.m_data.m_value.destroy(j.m_data.m_type);
5428 j.m_data.m_type = value_t::boolean;
5429 j.m_data.m_value = b;
5430 j.assert_invariant();
5431 }
5432};
5433
5434template<>
5435struct external_constructor<value_t::string>
5436{
5437 template<typename BasicJsonType>
5438 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5439 {
5440 j.m_data.m_value.destroy(j.m_data.m_type);
5441 j.m_data.m_type = value_t::string;
5442 j.m_data.m_value = s;
5443 j.assert_invariant();
5444 }
5445
5446 template<typename BasicJsonType>
5447 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5448 {
5449 j.m_data.m_value.destroy(j.m_data.m_type);
5450 j.m_data.m_type = value_t::string;
5451 j.m_data.m_value = std::move(s);
5452 j.assert_invariant();
5453 }
5454
5455 template < typename BasicJsonType, typename CompatibleStringType,
5456 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5457 int > = 0 >
5458 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5459 {
5460 j.m_data.m_value.destroy(j.m_data.m_type);
5461 j.m_data.m_type = value_t::string;
5462 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5463 j.assert_invariant();
5464 }
5465};
5466
5467template<>
5468struct external_constructor<value_t::binary>
5469{
5470 template<typename BasicJsonType>
5471 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5472 {
5473 j.m_data.m_value.destroy(j.m_data.m_type);
5474 j.m_data.m_type = value_t::binary;
5475 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5476 j.assert_invariant();
5477 }
5478
5479 template<typename BasicJsonType>
5480 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5481 {
5482 j.m_data.m_value.destroy(j.m_data.m_type);
5483 j.m_data.m_type = value_t::binary;
5484 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5485 j.assert_invariant();
5486 }
5487};
5488
5489template<>
5490struct external_constructor<value_t::number_float>
5491{
5492 template<typename BasicJsonType>
5493 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5494 {
5495 j.m_data.m_value.destroy(j.m_data.m_type);
5496 j.m_data.m_type = value_t::number_float;
5497 j.m_data.m_value = val;
5498 j.assert_invariant();
5499 }
5500};
5501
5502template<>
5503struct external_constructor<value_t::number_unsigned>
5504{
5505 template<typename BasicJsonType>
5506 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5507 {
5508 j.m_data.m_value.destroy(j.m_data.m_type);
5509 j.m_data.m_type = value_t::number_unsigned;
5510 j.m_data.m_value = val;
5511 j.assert_invariant();
5512 }
5513};
5514
5515template<>
5516struct external_constructor<value_t::number_integer>
5517{
5518 template<typename BasicJsonType>
5519 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5520 {
5521 j.m_data.m_value.destroy(j.m_data.m_type);
5522 j.m_data.m_type = value_t::number_integer;
5523 j.m_data.m_value = val;
5524 j.assert_invariant();
5525 }
5526};
5527
5528template<>
5529struct external_constructor<value_t::array>
5530{
5531 template<typename BasicJsonType>
5532 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5533 {
5534 j.m_data.m_value.destroy(j.m_data.m_type);
5535 j.m_data.m_type = value_t::array;
5536 j.m_data.m_value = arr;
5537 j.set_parents();
5538 j.assert_invariant();
5539 }
5540
5541 template<typename BasicJsonType>
5542 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5543 {
5544 j.m_data.m_value.destroy(j.m_data.m_type);
5545 j.m_data.m_type = value_t::array;
5546 j.m_data.m_value = std::move(arr);
5547 j.set_parents();
5548 j.assert_invariant();
5549 }
5550
5551 template < typename BasicJsonType, typename CompatibleArrayType,
5552 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5553 int > = 0 >
5554 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5555 {
5556 using std::begin;
5557 using std::end;
5558
5559 j.m_data.m_value.destroy(j.m_data.m_type);
5560 j.m_data.m_type = value_t::array;
5561 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5562 j.set_parents();
5563 j.assert_invariant();
5564 }
5565
5566 template<typename BasicJsonType>
5567 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5568 {
5569 j.m_data.m_value.destroy(j.m_data.m_type);
5570 j.m_data.m_type = value_t::array;
5571 j.m_data.m_value = value_t::array;
5572 j.m_data.m_value.array->reserve(arr.size());
5573 for (const bool x : arr)
5574 {
5575 j.m_data.m_value.array->push_back(x);
5576 j.set_parent(j.m_data.m_value.array->back());
5577 }
5578 j.assert_invariant();
5579 }
5580
5581 template<typename BasicJsonType, typename T,
5582 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5583 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5584 {
5585 j.m_data.m_value.destroy(j.m_data.m_type);
5586 j.m_data.m_type = value_t::array;
5587 j.m_data.m_value = value_t::array;
5588 j.m_data.m_value.array->resize(arr.size());
5589 if (arr.size() > 0)
5590 {
5591 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5592 }
5593 j.set_parents();
5594 j.assert_invariant();
5595 }
5596};
5597
5598template<>
5599struct external_constructor<value_t::object>
5600{
5601 template<typename BasicJsonType>
5602 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5603 {
5604 j.m_data.m_value.destroy(j.m_data.m_type);
5605 j.m_data.m_type = value_t::object;
5606 j.m_data.m_value = obj;
5607 j.set_parents();
5608 j.assert_invariant();
5609 }
5610
5611 template<typename BasicJsonType>
5612 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5613 {
5614 j.m_data.m_value.destroy(j.m_data.m_type);
5615 j.m_data.m_type = value_t::object;
5616 j.m_data.m_value = std::move(obj);
5617 j.set_parents();
5618 j.assert_invariant();
5619 }
5620
5621 template < typename BasicJsonType, typename CompatibleObjectType,
5622 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5623 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5624 {
5625 using std::begin;
5626 using std::end;
5627
5628 j.m_data.m_value.destroy(j.m_data.m_type);
5629 j.m_data.m_type = value_t::object;
5630 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5631 j.set_parents();
5632 j.assert_invariant();
5633 }
5634};
5635
5637// to_json //
5639
5640template<typename BasicJsonType, typename T,
5641 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5642inline void to_json(BasicJsonType& j, T b) noexcept
5643{
5644 external_constructor<value_t::boolean>::construct(j, b);
5645}
5646
5647template < typename BasicJsonType, typename BoolRef,
5648 enable_if_t <
5649 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5650 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5651 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5652 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5653 typename BasicJsonType::boolean_t >::value))
5654 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5655inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5656{
5657 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5658}
5659
5660template<typename BasicJsonType, typename CompatibleString,
5661 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5662inline void to_json(BasicJsonType& j, const CompatibleString& s)
5663{
5664 external_constructor<value_t::string>::construct(j, s);
5665}
5666
5667template<typename BasicJsonType>
5668inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5669{
5670 external_constructor<value_t::string>::construct(j, std::move(s));
5671}
5672
5673template<typename BasicJsonType, typename FloatType,
5674 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5675inline void to_json(BasicJsonType& j, FloatType val) noexcept
5676{
5677 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5678}
5679
5680template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5681 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5682inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5683{
5684 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5685}
5686
5687template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5688 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5689inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5690{
5691 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5692}
5693
5694#if !JSON_DISABLE_ENUM_SERIALIZATION
5695template<typename BasicJsonType, typename EnumType,
5696 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5697inline void to_json(BasicJsonType& j, EnumType e) noexcept
5698{
5699 using underlying_type = typename std::underlying_type<EnumType>::type;
5700 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
5701 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
5702}
5703#endif // JSON_DISABLE_ENUM_SERIALIZATION
5704
5705template<typename BasicJsonType>
5706inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5707{
5708 external_constructor<value_t::array>::construct(j, e);
5709}
5710
5711template < typename BasicJsonType, typename CompatibleArrayType,
5712 enable_if_t < is_compatible_array_type<BasicJsonType,
5713 CompatibleArrayType>::value&&
5714 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
5715 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
5716 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
5717 !is_basic_json<CompatibleArrayType>::value,
5718 int > = 0 >
5719inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
5720{
5721 external_constructor<value_t::array>::construct(j, arr);
5722}
5723
5724template<typename BasicJsonType>
5725inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
5726{
5727 external_constructor<value_t::binary>::construct(j, bin);
5728}
5729
5730template<typename BasicJsonType, typename T,
5731 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5732inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
5733{
5734 external_constructor<value_t::array>::construct(j, std::move(arr));
5735}
5736
5737template<typename BasicJsonType>
5738inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5739{
5740 external_constructor<value_t::array>::construct(j, std::move(arr));
5741}
5742
5743template < typename BasicJsonType, typename CompatibleObjectType,
5744 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
5745inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
5746{
5747 external_constructor<value_t::object>::construct(j, obj);
5748}
5749
5750template<typename BasicJsonType>
5751inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5752{
5753 external_constructor<value_t::object>::construct(j, std::move(obj));
5754}
5755
5756template <
5757 typename BasicJsonType, typename T, std::size_t N,
5758 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
5759 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5760 int > = 0 >
5761inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5762{
5763 external_constructor<value_t::array>::construct(j, arr);
5764}
5765
5766template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
5767inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
5768{
5769 j = { p.first, p.second };
5770}
5771
5772// for https://github.com/nlohmann/json/pull/1134
5773template<typename BasicJsonType, typename T,
5774 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
5775inline void to_json(BasicJsonType& j, const T& b)
5776{
5777 j = { {b.key(), b.value()} };
5778}
5779
5780template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
5781inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
5782{
5783 j = { std::get<Idx>(t)... };
5784}
5785
5786template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
5787inline void to_json(BasicJsonType& j, const T& t)
5788{
5789 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5790}
5791
5792#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5793template<typename BasicJsonType>
5794inline void to_json(BasicJsonType& j, const std_fs::path& p)
5795{
5796 j = p.string();
5797}
5798#endif
5799
5800struct to_json_fn
5801{
5802 template<typename BasicJsonType, typename T>
5803 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
5804 -> decltype(to_json(j, std::forward<T>(val)), void())
5805 {
5806 return to_json(j, std::forward<T>(val));
5807 }
5808};
5809} // namespace detail
5810
5811#ifndef JSON_HAS_CPP_17
5815namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5816{
5817#endif
5818JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
5820#ifndef JSON_HAS_CPP_17
5821} // namespace
5822#endif
5823
5824NLOHMANN_JSON_NAMESPACE_END
5825
5826// #include <nlohmann/detail/meta/identity_tag.hpp>
5827
5828
5829NLOHMANN_JSON_NAMESPACE_BEGIN
5830
5832template<typename ValueType, typename>
5833struct adl_serializer
5834{
5837 template<typename BasicJsonType, typename TargetType = ValueType>
5838 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
5839 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5840 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
5841 {
5842 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5843 }
5844
5847 template<typename BasicJsonType, typename TargetType = ValueType>
5848 static auto from_json(BasicJsonType && j) noexcept(
5849 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
5850 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
5851 {
5852 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
5853 }
5854
5857 template<typename BasicJsonType, typename TargetType = ValueType>
5858 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
5859 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5860 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
5861 {
5862 ::nlohmann::to_json(j, std::forward<TargetType>(val));
5863 }
5864};
5865
5866NLOHMANN_JSON_NAMESPACE_END
5867
5868// #include <nlohmann/byte_container_with_subtype.hpp>
5869// __ _____ _____ _____
5870// __| | __| | | | JSON for Modern C++
5871// | | |__ | | | | | | version 3.11.3
5872// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5873//
5874// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5875// SPDX-License-Identifier: MIT
5876
5877
5878
5879#include <cstdint> // uint8_t, uint64_t
5880#include <tuple> // tie
5881#include <utility> // move
5882
5883// #include <nlohmann/detail/abi_macros.hpp>
5884
5885
5886NLOHMANN_JSON_NAMESPACE_BEGIN
5887
5890template<typename BinaryType>
5891class byte_container_with_subtype : public BinaryType
5892{
5893 public:
5894 using container_type = BinaryType;
5895 using subtype_type = std::uint64_t;
5896
5898 byte_container_with_subtype() noexcept(noexcept(container_type()))
5899 : container_type()
5900 {}
5901
5903 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
5904 : container_type(b)
5905 {}
5906
5908 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
5909 : container_type(std::move(b))
5910 {}
5911
5913 byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
5914 : container_type(b)
5915 , m_subtype(subtype_)
5916 , m_has_subtype(true)
5917 {}
5918
5920 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
5921 : container_type(std::move(b))
5922 , m_subtype(subtype_)
5923 , m_has_subtype(true)
5924 {}
5925
5926 bool operator==(const byte_container_with_subtype& rhs) const
5927 {
5928 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5929 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5930 }
5931
5932 bool operator!=(const byte_container_with_subtype& rhs) const
5933 {
5934 return !(rhs == *this);
5935 }
5936
5939 void set_subtype(subtype_type subtype_) noexcept
5940 {
5941 m_subtype = subtype_;
5942 m_has_subtype = true;
5943 }
5944
5947 constexpr subtype_type subtype() const noexcept
5948 {
5949 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5950 }
5951
5954 constexpr bool has_subtype() const noexcept
5955 {
5956 return m_has_subtype;
5957 }
5958
5961 void clear_subtype() noexcept
5962 {
5963 m_subtype = 0;
5964 m_has_subtype = false;
5965 }
5966
5967 private:
5968 subtype_type m_subtype = 0;
5969 bool m_has_subtype = false;
5970};
5971
5972NLOHMANN_JSON_NAMESPACE_END
5973
5974// #include <nlohmann/detail/conversions/from_json.hpp>
5975
5976// #include <nlohmann/detail/conversions/to_json.hpp>
5977
5978// #include <nlohmann/detail/exceptions.hpp>
5979
5980// #include <nlohmann/detail/hash.hpp>
5981// __ _____ _____ _____
5982// __| | __| | | | JSON for Modern C++
5983// | | |__ | | | | | | version 3.11.3
5984// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5985//
5986// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5987// SPDX-License-Identifier: MIT
5988
5989
5990
5991#include <cstdint> // uint8_t
5992#include <cstddef> // size_t
5993#include <functional> // hash
5994
5995// #include <nlohmann/detail/abi_macros.hpp>
5996
5997// #include <nlohmann/detail/value_t.hpp>
5998
5999
6000NLOHMANN_JSON_NAMESPACE_BEGIN
6001namespace detail
6002{
6003
6004// boost::hash_combine
6005inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6006{
6007 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6008 return seed;
6009}
6010
6022template<typename BasicJsonType>
6023std::size_t hash(const BasicJsonType& j)
6024{
6025 using string_t = typename BasicJsonType::string_t;
6026 using number_integer_t = typename BasicJsonType::number_integer_t;
6027 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6028 using number_float_t = typename BasicJsonType::number_float_t;
6029
6030 const auto type = static_cast<std::size_t>(j.type());
6031 switch (j.type())
6032 {
6033 case BasicJsonType::value_t::null:
6034 case BasicJsonType::value_t::discarded:
6035 {
6036 return combine(type, 0);
6037 }
6038
6039 case BasicJsonType::value_t::object:
6040 {
6041 auto seed = combine(type, j.size());
6042 for (const auto& element : j.items())
6043 {
6044 const auto h = std::hash<string_t> {}(element.key());
6045 seed = combine(seed, h);
6046 seed = combine(seed, hash(element.value()));
6047 }
6048 return seed;
6049 }
6050
6051 case BasicJsonType::value_t::array:
6052 {
6053 auto seed = combine(type, j.size());
6054 for (const auto& element : j)
6055 {
6056 seed = combine(seed, hash(element));
6057 }
6058 return seed;
6059 }
6060
6061 case BasicJsonType::value_t::string:
6062 {
6063 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6064 return combine(type, h);
6065 }
6066
6067 case BasicJsonType::value_t::boolean:
6068 {
6069 const auto h = std::hash<bool> {}(j.template get<bool>());
6070 return combine(type, h);
6071 }
6072
6073 case BasicJsonType::value_t::number_integer:
6074 {
6075 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6076 return combine(type, h);
6077 }
6078
6079 case BasicJsonType::value_t::number_unsigned:
6080 {
6081 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6082 return combine(type, h);
6083 }
6084
6085 case BasicJsonType::value_t::number_float:
6086 {
6087 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6088 return combine(type, h);
6089 }
6090
6091 case BasicJsonType::value_t::binary:
6092 {
6093 auto seed = combine(type, j.get_binary().size());
6094 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6095 seed = combine(seed, h);
6096 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6097 for (const auto byte : j.get_binary())
6098 {
6099 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6100 }
6101 return seed;
6102 }
6103
6104 default: // LCOV_EXCL_LINE
6105 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6106 return 0; // LCOV_EXCL_LINE
6107 }
6108}
6109
6110} // namespace detail
6111NLOHMANN_JSON_NAMESPACE_END
6112
6113// #include <nlohmann/detail/input/binary_reader.hpp>
6114// __ _____ _____ _____
6115// __| | __| | | | JSON for Modern C++
6116// | | |__ | | | | | | version 3.11.3
6117// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6118//
6119// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6120// SPDX-License-Identifier: MIT
6121
6122
6123
6124#include <algorithm> // generate_n
6125#include <array> // array
6126#include <cmath> // ldexp
6127#include <cstddef> // size_t
6128#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6129#include <cstdio> // snprintf
6130#include <cstring> // memcpy
6131#include <iterator> // back_inserter
6132#include <limits> // numeric_limits
6133#include <string> // char_traits, string
6134#include <utility> // make_pair, move
6135#include <vector> // vector
6136
6137// #include <nlohmann/detail/exceptions.hpp>
6138
6139// #include <nlohmann/detail/input/input_adapters.hpp>
6140// __ _____ _____ _____
6141// __| | __| | | | JSON for Modern C++
6142// | | |__ | | | | | | version 3.11.3
6143// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6144//
6145// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6146// SPDX-License-Identifier: MIT
6147
6148
6149
6150#include <array> // array
6151#include <cstddef> // size_t
6152#include <cstring> // strlen
6153#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6154#include <memory> // shared_ptr, make_shared, addressof
6155#include <numeric> // accumulate
6156#include <string> // string, char_traits
6157#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6158#include <utility> // pair, declval
6159
6160#ifndef JSON_NO_IO
6161 #include <cstdio> // FILE *
6162 #include <istream> // istream
6163#endif // JSON_NO_IO
6164
6165// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6166
6167// #include <nlohmann/detail/macro_scope.hpp>
6168
6169// #include <nlohmann/detail/meta/type_traits.hpp>
6170
6171
6172NLOHMANN_JSON_NAMESPACE_BEGIN
6173namespace detail
6174{
6175
6177enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
6178
6180// input adapters //
6182
6183#ifndef JSON_NO_IO
6188class file_input_adapter
6189{
6190 public:
6191 using char_type = char;
6192
6193 JSON_HEDLEY_NON_NULL(2)
6194 explicit file_input_adapter(std::FILE* f) noexcept
6195 : m_file(f)
6196 {
6197 JSON_ASSERT(m_file != nullptr);
6198 }
6199
6200 // make class move-only
6201 file_input_adapter(const file_input_adapter&) = delete;
6202 file_input_adapter(file_input_adapter&&) noexcept = default;
6203 file_input_adapter& operator=(const file_input_adapter&) = delete;
6204 file_input_adapter& operator=(file_input_adapter&&) = delete;
6205 ~file_input_adapter() = default;
6206
6207 std::char_traits<char>::int_type get_character() noexcept
6208 {
6209 return std::fgetc(m_file);
6210 }
6211
6212 private:
6214 std::FILE* m_file;
6215};
6216
6226class input_stream_adapter
6227{
6228 public:
6229 using char_type = char;
6230
6231 ~input_stream_adapter()
6232 {
6233 // clear stream flags; we use underlying streambuf I/O, do not
6234 // maintain ifstream flags, except eof
6235 if (is != nullptr)
6236 {
6237 is->clear(is->rdstate() & std::ios::eofbit);
6238 }
6239 }
6240
6241 explicit input_stream_adapter(std::istream& i)
6242 : is(&i), sb(i.rdbuf())
6243 {}
6244
6245 // delete because of pointer members
6246 input_stream_adapter(const input_stream_adapter&) = delete;
6247 input_stream_adapter& operator=(input_stream_adapter&) = delete;
6248 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
6249
6250 input_stream_adapter(input_stream_adapter&& rhs) noexcept
6251 : is(rhs.is), sb(rhs.sb)
6252 {
6253 rhs.is = nullptr;
6254 rhs.sb = nullptr;
6255 }
6256
6257 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6258 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6259 // end up as the same value, e.g. 0xFFFFFFFF.
6260 std::char_traits<char>::int_type get_character()
6261 {
6262 auto res = sb->sbumpc();
6263 // set eof manually, as we don't use the istream interface.
6264 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6265 {
6266 is->clear(is->rdstate() | std::ios::eofbit);
6267 }
6268 return res;
6269 }
6270
6271 private:
6273 std::istream* is = nullptr;
6274 std::streambuf* sb = nullptr;
6275};
6276#endif // JSON_NO_IO
6277
6278// General-purpose iterator-based adapter. It might not be as fast as
6279// theoretically possible for some containers, but it is extremely versatile.
6280template<typename IteratorType>
6281class iterator_input_adapter
6282{
6283 public:
6284 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6285
6286 iterator_input_adapter(IteratorType first, IteratorType last)
6287 : current(std::move(first)), end(std::move(last))
6288 {}
6289
6290 typename char_traits<char_type>::int_type get_character()
6291 {
6292 if (JSON_HEDLEY_LIKELY(current != end))
6293 {
6294 auto result = char_traits<char_type>::to_int_type(*current);
6295 std::advance(current, 1);
6296 return result;
6297 }
6298
6299 return char_traits<char_type>::eof();
6300 }
6301
6302 private:
6303 IteratorType current;
6304 IteratorType end;
6305
6306 template<typename BaseInputAdapter, size_t T>
6307 friend struct wide_string_input_helper;
6308
6309 bool empty() const
6310 {
6311 return current == end;
6312 }
6313};
6314
6315template<typename BaseInputAdapter, size_t T>
6316struct wide_string_input_helper;
6317
6318template<typename BaseInputAdapter>
6319struct wide_string_input_helper<BaseInputAdapter, 4>
6320{
6321 // UTF-32
6322 static void fill_buffer(BaseInputAdapter& input,
6323 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6324 size_t& utf8_bytes_index,
6325 size_t& utf8_bytes_filled)
6326 {
6327 utf8_bytes_index = 0;
6328
6329 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6330 {
6331 utf8_bytes[0] = std::char_traits<char>::eof();
6332 utf8_bytes_filled = 1;
6333 }
6334 else
6335 {
6336 // get the current character
6337 const auto wc = input.get_character();
6338
6339 // UTF-32 to UTF-8 encoding
6340 if (wc < 0x80)
6341 {
6342 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6343 utf8_bytes_filled = 1;
6344 }
6345 else if (wc <= 0x7FF)
6346 {
6347 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6348 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6349 utf8_bytes_filled = 2;
6350 }
6351 else if (wc <= 0xFFFF)
6352 {
6353 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6354 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6355 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6356 utf8_bytes_filled = 3;
6357 }
6358 else if (wc <= 0x10FFFF)
6359 {
6360 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6361 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6362 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6363 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6364 utf8_bytes_filled = 4;
6365 }
6366 else
6367 {
6368 // unknown character
6369 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6370 utf8_bytes_filled = 1;
6371 }
6372 }
6373 }
6374};
6375
6376template<typename BaseInputAdapter>
6377struct wide_string_input_helper<BaseInputAdapter, 2>
6378{
6379 // UTF-16
6380 static void fill_buffer(BaseInputAdapter& input,
6381 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6382 size_t& utf8_bytes_index,
6383 size_t& utf8_bytes_filled)
6384 {
6385 utf8_bytes_index = 0;
6386
6387 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6388 {
6389 utf8_bytes[0] = std::char_traits<char>::eof();
6390 utf8_bytes_filled = 1;
6391 }
6392 else
6393 {
6394 // get the current character
6395 const auto wc = input.get_character();
6396
6397 // UTF-16 to UTF-8 encoding
6398 if (wc < 0x80)
6399 {
6400 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6401 utf8_bytes_filled = 1;
6402 }
6403 else if (wc <= 0x7FF)
6404 {
6405 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6406 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6407 utf8_bytes_filled = 2;
6408 }
6409 else if (0xD800 > wc || wc >= 0xE000)
6410 {
6411 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6412 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6413 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6414 utf8_bytes_filled = 3;
6415 }
6416 else
6417 {
6418 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6419 {
6420 const auto wc2 = static_cast<unsigned int>(input.get_character());
6421 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6422 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6423 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6424 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6425 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6426 utf8_bytes_filled = 4;
6427 }
6428 else
6429 {
6430 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6431 utf8_bytes_filled = 1;
6432 }
6433 }
6434 }
6435 }
6436};
6437
6438// Wraps another input adapter to convert wide character types into individual bytes.
6439template<typename BaseInputAdapter, typename WideCharType>
6440class wide_string_input_adapter
6441{
6442 public:
6443 using char_type = char;
6444
6445 wide_string_input_adapter(BaseInputAdapter base)
6446 : base_adapter(base) {}
6447
6448 typename std::char_traits<char>::int_type get_character() noexcept
6449 {
6450 // check if buffer needs to be filled
6451 if (utf8_bytes_index == utf8_bytes_filled)
6452 {
6453 fill_buffer<sizeof(WideCharType)>();
6454
6455 JSON_ASSERT(utf8_bytes_filled > 0);
6456 JSON_ASSERT(utf8_bytes_index == 0);
6457 }
6458
6459 // use buffer
6460 JSON_ASSERT(utf8_bytes_filled > 0);
6461 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6462 return utf8_bytes[utf8_bytes_index++];
6463 }
6464
6465 private:
6466 BaseInputAdapter base_adapter;
6467
6468 template<size_t T>
6469 void fill_buffer()
6470 {
6471 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6472 }
6473
6475 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6476
6478 std::size_t utf8_bytes_index = 0;
6480 std::size_t utf8_bytes_filled = 0;
6481};
6482
6483template<typename IteratorType, typename Enable = void>
6484struct iterator_input_adapter_factory
6485{
6486 using iterator_type = IteratorType;
6487 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6488 using adapter_type = iterator_input_adapter<iterator_type>;
6489
6490 static adapter_type create(IteratorType first, IteratorType last)
6491 {
6492 return adapter_type(std::move(first), std::move(last));
6493 }
6494};
6495
6496template<typename T>
6497struct is_iterator_of_multibyte
6498{
6499 using value_type = typename std::iterator_traits<T>::value_type;
6500 enum
6501 {
6502 value = sizeof(value_type) > 1
6503 };
6504};
6505
6506template<typename IteratorType>
6507struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
6508{
6509 using iterator_type = IteratorType;
6510 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6511 using base_adapter_type = iterator_input_adapter<iterator_type>;
6512 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
6513
6514 static adapter_type create(IteratorType first, IteratorType last)
6515 {
6516 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6517 }
6518};
6519
6520// General purpose iterator-based input
6521template<typename IteratorType>
6522typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
6523{
6524 using factory_type = iterator_input_adapter_factory<IteratorType>;
6525 return factory_type::create(first, last);
6526}
6527
6528// Convenience shorthand from container to iterator
6529// Enables ADL on begin(container) and end(container)
6530// Encloses the using declarations in namespace for not to leak them to outside scope
6531
6532namespace container_input_adapter_factory_impl
6533{
6534
6535using std::begin;
6536using std::end;
6537
6538template<typename ContainerType, typename Enable = void>
6539struct container_input_adapter_factory {};
6540
6541template<typename ContainerType>
6542struct container_input_adapter_factory< ContainerType,
6543 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6544 {
6545 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6546
6547 static adapter_type create(const ContainerType& container)
6548{
6549 return input_adapter(begin(container), end(container));
6550}
6551 };
6552
6553} // namespace container_input_adapter_factory_impl
6554
6555template<typename ContainerType>
6556typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
6557{
6558 return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
6559}
6560
6561#ifndef JSON_NO_IO
6562// Special cases with fast paths
6563inline file_input_adapter input_adapter(std::FILE* file)
6564{
6565 return file_input_adapter(file);
6566}
6567
6568inline input_stream_adapter input_adapter(std::istream& stream)
6569{
6570 return input_stream_adapter(stream);
6571}
6572
6573inline input_stream_adapter input_adapter(std::istream&& stream)
6574{
6575 return input_stream_adapter(stream);
6576}
6577#endif // JSON_NO_IO
6578
6579using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6580
6581// Null-delimited strings, and the like.
6582template < typename CharT,
6583 typename std::enable_if <
6584 std::is_pointer<CharT>::value&&
6585 !std::is_array<CharT>::value&&
6586 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6587 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6588 int >::type = 0 >
6589contiguous_bytes_input_adapter input_adapter(CharT b)
6590{
6591 auto length = std::strlen(reinterpret_cast<const char*>(b));
6592 const auto* ptr = reinterpret_cast<const char*>(b);
6593 return input_adapter(ptr, ptr + length);
6594}
6595
6596template<typename T, std::size_t N>
6597auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6598{
6599 return input_adapter(array, array + N);
6600}
6601
6602// This class only handles inputs of input_buffer_adapter type.
6603// It's required so that expressions like {ptr, len} can be implicitly cast
6604// to the correct adapter.
6605class span_input_adapter
6606{
6607 public:
6608 template < typename CharT,
6609 typename std::enable_if <
6610 std::is_pointer<CharT>::value&&
6611 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6612 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6613 int >::type = 0 >
6614 span_input_adapter(CharT b, std::size_t l)
6615 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6616
6617 template<class IteratorType,
6618 typename std::enable_if<
6619 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6620 int>::type = 0>
6621 span_input_adapter(IteratorType first, IteratorType last)
6622 : ia(input_adapter(first, last)) {}
6623
6624 contiguous_bytes_input_adapter&& get()
6625 {
6626 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6627 }
6628
6629 private:
6630 contiguous_bytes_input_adapter ia;
6631};
6632
6633} // namespace detail
6634NLOHMANN_JSON_NAMESPACE_END
6635
6636// #include <nlohmann/detail/input/json_sax.hpp>
6637// __ _____ _____ _____
6638// __| | __| | | | JSON for Modern C++
6639// | | |__ | | | | | | version 3.11.3
6640// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6641//
6642// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6643// SPDX-License-Identifier: MIT
6644
6645
6646
6647#include <cstddef>
6648#include <string> // string
6649#include <utility> // move
6650#include <vector> // vector
6651
6652// #include <nlohmann/detail/exceptions.hpp>
6653
6654// #include <nlohmann/detail/macro_scope.hpp>
6655
6656// #include <nlohmann/detail/string_concat.hpp>
6657
6658
6659NLOHMANN_JSON_NAMESPACE_BEGIN
6660
6669template<typename BasicJsonType>
6671{
6672 using number_integer_t = typename BasicJsonType::number_integer_t;
6673 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6674 using number_float_t = typename BasicJsonType::number_float_t;
6675 using string_t = typename BasicJsonType::string_t;
6676 using binary_t = typename BasicJsonType::binary_t;
6677
6682 virtual bool null() = 0;
6683
6689 virtual bool boolean(bool val) = 0;
6690
6696 virtual bool number_integer(number_integer_t val) = 0;
6697
6703 virtual bool number_unsigned(number_unsigned_t val) = 0;
6704
6711 virtual bool number_float(number_float_t val, const string_t& s) = 0;
6712
6719 virtual bool string(string_t& val) = 0;
6720
6727 virtual bool binary(binary_t& val) = 0;
6728
6735 virtual bool start_object(std::size_t elements) = 0;
6736
6743 virtual bool key(string_t& val) = 0;
6744
6749 virtual bool end_object() = 0;
6750
6757 virtual bool start_array(std::size_t elements) = 0;
6758
6763 virtual bool end_array() = 0;
6764
6772 virtual bool parse_error(std::size_t position,
6773 const std::string& last_token,
6774 const detail::exception& ex) = 0;
6775
6776 json_sax() = default;
6777 json_sax(const json_sax&) = default;
6778 json_sax(json_sax&&) noexcept = default;
6779 json_sax& operator=(const json_sax&) = default;
6780 json_sax& operator=(json_sax&&) noexcept = default;
6781 virtual ~json_sax() = default;
6782};
6783
6784namespace detail
6785{
6799template<typename BasicJsonType>
6800class json_sax_dom_parser
6801{
6802 public:
6803 using number_integer_t = typename BasicJsonType::number_integer_t;
6804 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6805 using number_float_t = typename BasicJsonType::number_float_t;
6806 using string_t = typename BasicJsonType::string_t;
6807 using binary_t = typename BasicJsonType::binary_t;
6808
6814 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
6815 : root(r), allow_exceptions(allow_exceptions_)
6816 {}
6817
6818 // make class move-only
6820 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6821 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
6822 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6823 ~json_sax_dom_parser() = default;
6824
6825 bool null()
6826 {
6827 handle_value(nullptr);
6828 return true;
6829 }
6830
6831 bool boolean(bool val)
6832 {
6833 handle_value(val);
6834 return true;
6835 }
6836
6837 bool number_integer(number_integer_t val)
6838 {
6839 handle_value(val);
6840 return true;
6841 }
6842
6843 bool number_unsigned(number_unsigned_t val)
6844 {
6845 handle_value(val);
6846 return true;
6847 }
6848
6849 bool number_float(number_float_t val, const string_t& /*unused*/)
6850 {
6851 handle_value(val);
6852 return true;
6853 }
6854
6855 bool string(string_t& val)
6856 {
6857 handle_value(val);
6858 return true;
6859 }
6860
6861 bool binary(binary_t& val)
6862 {
6863 handle_value(std::move(val));
6864 return true;
6865 }
6866
6867 bool start_object(std::size_t len)
6868 {
6869 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
6870
6871 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6872 {
6873 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6874 }
6875
6876 return true;
6877 }
6878
6879 bool key(string_t& val)
6880 {
6881 JSON_ASSERT(!ref_stack.empty());
6882 JSON_ASSERT(ref_stack.back()->is_object());
6883
6884 // add null at given key and store the reference for later
6885 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
6886 return true;
6887 }
6888
6889 bool end_object()
6890 {
6891 JSON_ASSERT(!ref_stack.empty());
6892 JSON_ASSERT(ref_stack.back()->is_object());
6893
6894 ref_stack.back()->set_parents();
6895 ref_stack.pop_back();
6896 return true;
6897 }
6898
6899 bool start_array(std::size_t len)
6900 {
6901 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
6902
6903 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6904 {
6905 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
6906 }
6907
6908 return true;
6909 }
6910
6911 bool end_array()
6912 {
6913 JSON_ASSERT(!ref_stack.empty());
6914 JSON_ASSERT(ref_stack.back()->is_array());
6915
6916 ref_stack.back()->set_parents();
6917 ref_stack.pop_back();
6918 return true;
6919 }
6920
6921 template<class Exception>
6922 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6923 const Exception& ex)
6924 {
6925 errored = true;
6926 static_cast<void>(ex);
6927 if (allow_exceptions)
6928 {
6929 JSON_THROW(ex);
6930 }
6931 return false;
6932 }
6933
6934 constexpr bool is_errored() const
6935 {
6936 return errored;
6937 }
6938
6939 private:
6946 template<typename Value>
6947 JSON_HEDLEY_RETURNS_NON_NULL
6948 BasicJsonType* handle_value(Value&& v)
6949 {
6950 if (ref_stack.empty())
6951 {
6952 root = BasicJsonType(std::forward<Value>(v));
6953 return &root;
6954 }
6955
6956 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6957
6958 if (ref_stack.back()->is_array())
6959 {
6960 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
6961 return &(ref_stack.back()->m_data.m_value.array->back());
6962 }
6963
6964 JSON_ASSERT(ref_stack.back()->is_object());
6965 JSON_ASSERT(object_element);
6966 *object_element = BasicJsonType(std::forward<Value>(v));
6967 return object_element;
6968 }
6969
6971 BasicJsonType& root;
6973 std::vector<BasicJsonType*> ref_stack {};
6975 BasicJsonType* object_element = nullptr;
6977 bool errored = false;
6979 const bool allow_exceptions = true;
6980};
6981
6982template<typename BasicJsonType>
6983class json_sax_dom_callback_parser
6984{
6985 public:
6986 using number_integer_t = typename BasicJsonType::number_integer_t;
6987 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6988 using number_float_t = typename BasicJsonType::number_float_t;
6989 using string_t = typename BasicJsonType::string_t;
6990 using binary_t = typename BasicJsonType::binary_t;
6991 using parser_callback_t = typename BasicJsonType::parser_callback_t;
6992 using parse_event_t = typename BasicJsonType::parse_event_t;
6993
6994 json_sax_dom_callback_parser(BasicJsonType& r,
6995 const parser_callback_t cb,
6996 const bool allow_exceptions_ = true)
6997 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
6998 {
6999 keep_stack.push_back(true);
7000 }
7001
7002 // make class move-only
7003 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
7004 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7005 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
7006 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7007 ~json_sax_dom_callback_parser() = default;
7008
7009 bool null()
7010 {
7011 handle_value(nullptr);
7012 return true;
7013 }
7014
7015 bool boolean(bool val)
7016 {
7017 handle_value(val);
7018 return true;
7019 }
7020
7021 bool number_integer(number_integer_t val)
7022 {
7023 handle_value(val);
7024 return true;
7025 }
7026
7027 bool number_unsigned(number_unsigned_t val)
7028 {
7029 handle_value(val);
7030 return true;
7031 }
7032
7033 bool number_float(number_float_t val, const string_t& /*unused*/)
7034 {
7035 handle_value(val);
7036 return true;
7037 }
7038
7039 bool string(string_t& val)
7040 {
7041 handle_value(val);
7042 return true;
7043 }
7044
7045 bool binary(binary_t& val)
7046 {
7047 handle_value(std::move(val));
7048 return true;
7049 }
7050
7051 bool start_object(std::size_t len)
7052 {
7053 // check callback for object start
7054 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
7055 keep_stack.push_back(keep);
7056
7057 auto val = handle_value(BasicJsonType::value_t::object, true);
7058 ref_stack.push_back(val.second);
7059
7060 // check object limit
7061 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7062 {
7063 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
7064 }
7065
7066 return true;
7067 }
7068
7069 bool key(string_t& val)
7070 {
7071 BasicJsonType k = BasicJsonType(val);
7072
7073 // check callback for key
7074 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
7075 key_keep_stack.push_back(keep);
7076
7077 // add discarded value at given key and store the reference for later
7078 if (keep && ref_stack.back())
7079 {
7080 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
7081 }
7082
7083 return true;
7084 }
7085
7086 bool end_object()
7087 {
7088 if (ref_stack.back())
7089 {
7090 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
7091 {
7092 // discard object
7093 *ref_stack.back() = discarded;
7094 }
7095 else
7096 {
7097 ref_stack.back()->set_parents();
7098 }
7099 }
7100
7101 JSON_ASSERT(!ref_stack.empty());
7102 JSON_ASSERT(!keep_stack.empty());
7103 ref_stack.pop_back();
7104 keep_stack.pop_back();
7105
7106 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
7107 {
7108 // remove discarded value
7109 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
7110 {
7111 if (it->is_discarded())
7112 {
7113 ref_stack.back()->erase(it);
7114 break;
7115 }
7116 }
7117 }
7118
7119 return true;
7120 }
7121
7122 bool start_array(std::size_t len)
7123 {
7124 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
7125 keep_stack.push_back(keep);
7126
7127 auto val = handle_value(BasicJsonType::value_t::array, true);
7128 ref_stack.push_back(val.second);
7129
7130 // check array limit
7131 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7132 {
7133 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
7134 }
7135
7136 return true;
7137 }
7138
7139 bool end_array()
7140 {
7141 bool keep = true;
7142
7143 if (ref_stack.back())
7144 {
7145 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
7146 if (keep)
7147 {
7148 ref_stack.back()->set_parents();
7149 }
7150 else
7151 {
7152 // discard array
7153 *ref_stack.back() = discarded;
7154 }
7155 }
7156
7157 JSON_ASSERT(!ref_stack.empty());
7158 JSON_ASSERT(!keep_stack.empty());
7159 ref_stack.pop_back();
7160 keep_stack.pop_back();
7161
7162 // remove discarded value
7163 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
7164 {
7165 ref_stack.back()->m_data.m_value.array->pop_back();
7166 }
7167
7168 return true;
7169 }
7170
7171 template<class Exception>
7172 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7173 const Exception& ex)
7174 {
7175 errored = true;
7176 static_cast<void>(ex);
7177 if (allow_exceptions)
7178 {
7179 JSON_THROW(ex);
7180 }
7181 return false;
7182 }
7183
7184 constexpr bool is_errored() const
7185 {
7186 return errored;
7187 }
7188
7189 private:
7205 template<typename Value>
7206 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
7207 {
7208 JSON_ASSERT(!keep_stack.empty());
7209
7210 // do not handle this value if we know it would be added to a discarded
7211 // container
7212 if (!keep_stack.back())
7213 {
7214 return {false, nullptr};
7215 }
7216
7217 // create value
7218 auto value = BasicJsonType(std::forward<Value>(v));
7219
7220 // check callback
7221 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
7222
7223 // do not handle this value if we just learnt it shall be discarded
7224 if (!keep)
7225 {
7226 return {false, nullptr};
7227 }
7228
7229 if (ref_stack.empty())
7230 {
7231 root = std::move(value);
7232 return {true, & root};
7233 }
7234
7235 // skip this value if we already decided to skip the parent
7236 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
7237 if (!ref_stack.back())
7238 {
7239 return {false, nullptr};
7240 }
7241
7242 // we now only expect arrays and objects
7243 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7244
7245 // array
7246 if (ref_stack.back()->is_array())
7247 {
7248 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
7249 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
7250 }
7251
7252 // object
7253 JSON_ASSERT(ref_stack.back()->is_object());
7254 // check if we should store an element for the current key
7255 JSON_ASSERT(!key_keep_stack.empty());
7256 const bool store_element = key_keep_stack.back();
7257 key_keep_stack.pop_back();
7258
7259 if (!store_element)
7260 {
7261 return {false, nullptr};
7262 }
7263
7264 JSON_ASSERT(object_element);
7265 *object_element = std::move(value);
7266 return {true, object_element};
7267 }
7268
7270 BasicJsonType& root;
7272 std::vector<BasicJsonType*> ref_stack {};
7274 std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
7276 std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
7278 BasicJsonType* object_element = nullptr;
7280 bool errored = false;
7282 const parser_callback_t callback = nullptr;
7284 const bool allow_exceptions = true;
7286 BasicJsonType discarded = BasicJsonType::value_t::discarded;
7287};
7288
7289template<typename BasicJsonType>
7290class json_sax_acceptor
7291{
7292 public:
7293 using number_integer_t = typename BasicJsonType::number_integer_t;
7294 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7295 using number_float_t = typename BasicJsonType::number_float_t;
7296 using string_t = typename BasicJsonType::string_t;
7297 using binary_t = typename BasicJsonType::binary_t;
7298
7299 bool null()
7300 {
7301 return true;
7302 }
7303
7304 bool boolean(bool /*unused*/)
7305 {
7306 return true;
7307 }
7308
7309 bool number_integer(number_integer_t /*unused*/)
7310 {
7311 return true;
7312 }
7313
7314 bool number_unsigned(number_unsigned_t /*unused*/)
7315 {
7316 return true;
7317 }
7318
7319 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
7320 {
7321 return true;
7322 }
7323
7324 bool string(string_t& /*unused*/)
7325 {
7326 return true;
7327 }
7328
7329 bool binary(binary_t& /*unused*/)
7330 {
7331 return true;
7332 }
7333
7334 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7335 {
7336 return true;
7337 }
7338
7339 bool key(string_t& /*unused*/)
7340 {
7341 return true;
7342 }
7343
7344 bool end_object()
7345 {
7346 return true;
7347 }
7348
7349 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7350 {
7351 return true;
7352 }
7353
7354 bool end_array()
7355 {
7356 return true;
7357 }
7358
7359 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
7360 {
7361 return false;
7362 }
7363};
7364
7365} // namespace detail
7366NLOHMANN_JSON_NAMESPACE_END
7367
7368// #include <nlohmann/detail/input/lexer.hpp>
7369// __ _____ _____ _____
7370// __| | __| | | | JSON for Modern C++
7371// | | |__ | | | | | | version 3.11.3
7372// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7373//
7374// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
7375// SPDX-License-Identifier: MIT
7376
7377
7378
7379#include <array> // array
7380#include <clocale> // localeconv
7381#include <cstddef> // size_t
7382#include <cstdio> // snprintf
7383#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7384#include <initializer_list> // initializer_list
7385#include <string> // char_traits, string
7386#include <utility> // move
7387#include <vector> // vector
7388
7389// #include <nlohmann/detail/input/input_adapters.hpp>
7390
7391// #include <nlohmann/detail/input/position_t.hpp>
7392
7393// #include <nlohmann/detail/macro_scope.hpp>
7394
7395// #include <nlohmann/detail/meta/type_traits.hpp>
7396
7397
7398NLOHMANN_JSON_NAMESPACE_BEGIN
7399namespace detail
7400{
7401
7403// lexer //
7405
7406template<typename BasicJsonType>
7407class lexer_base
7408{
7409 public:
7411 enum class token_type
7412 {
7413 uninitialized,
7414 literal_true,
7415 literal_false,
7416 literal_null,
7417 value_string,
7418 value_unsigned,
7419 value_integer,
7420 value_float,
7421 begin_array,
7422 begin_object,
7423 end_array,
7424 end_object,
7425 name_separator,
7426 value_separator,
7427 parse_error,
7428 end_of_input,
7429 literal_or_value
7430 };
7431
7433 JSON_HEDLEY_RETURNS_NON_NULL
7434 JSON_HEDLEY_CONST
7435 static const char* token_type_name(const token_type t) noexcept
7436 {
7437 switch (t)
7438 {
7439 case token_type::uninitialized:
7440 return "<uninitialized>";
7441 case token_type::literal_true:
7442 return "true literal";
7443 case token_type::literal_false:
7444 return "false literal";
7445 case token_type::literal_null:
7446 return "null literal";
7447 case token_type::value_string:
7448 return "string literal";
7449 case token_type::value_unsigned:
7450 case token_type::value_integer:
7451 case token_type::value_float:
7452 return "number literal";
7453 case token_type::begin_array:
7454 return "'['";
7455 case token_type::begin_object:
7456 return "'{'";
7457 case token_type::end_array:
7458 return "']'";
7459 case token_type::end_object:
7460 return "'}'";
7461 case token_type::name_separator:
7462 return "':'";
7463 case token_type::value_separator:
7464 return "','";
7465 case token_type::parse_error:
7466 return "<parse error>";
7467 case token_type::end_of_input:
7468 return "end of input";
7469 case token_type::literal_or_value:
7470 return "'[', '{', or a literal";
7471 // LCOV_EXCL_START
7472 default: // catch non-enum values
7473 return "unknown token";
7474 // LCOV_EXCL_STOP
7475 }
7476 }
7477};
7483template<typename BasicJsonType, typename InputAdapterType>
7484class lexer : public lexer_base<BasicJsonType>
7485{
7486 using number_integer_t = typename BasicJsonType::number_integer_t;
7487 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7488 using number_float_t = typename BasicJsonType::number_float_t;
7489 using string_t = typename BasicJsonType::string_t;
7490 using char_type = typename InputAdapterType::char_type;
7491 using char_int_type = typename char_traits<char_type>::int_type;
7492
7493 public:
7494 using token_type = typename lexer_base<BasicJsonType>::token_type;
7495
7496 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7497 : ia(std::move(adapter))
7498 , ignore_comments(ignore_comments_)
7499 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7500 {}
7501
7502 // delete because of pointer members
7503 lexer(const lexer&) = delete;
7504 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7505 lexer& operator=(lexer&) = delete;
7506 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7507 ~lexer() = default;
7508
7509 private:
7511 // locales
7513
7515 JSON_HEDLEY_PURE
7516 static char get_decimal_point() noexcept
7517 {
7518 const auto* loc = localeconv();
7519 JSON_ASSERT(loc != nullptr);
7520 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7521 }
7522
7524 // scan functions
7526
7542 int get_codepoint()
7543 {
7544 // this function only makes sense after reading `\u`
7545 JSON_ASSERT(current == 'u');
7546 int codepoint = 0;
7547
7548 const auto factors = { 12u, 8u, 4u, 0u };
7549 for (const auto factor : factors)
7550 {
7551 get();
7552
7553 if (current >= '0' && current <= '9')
7554 {
7555 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7556 }
7557 else if (current >= 'A' && current <= 'F')
7558 {
7559 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7560 }
7561 else if (current >= 'a' && current <= 'f')
7562 {
7563 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7564 }
7565 else
7566 {
7567 return -1;
7568 }
7569 }
7570
7571 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7572 return codepoint;
7573 }
7574
7590 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7591 {
7592 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7593 add(current);
7594
7595 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7596 {
7597 get();
7598 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7599 {
7600 add(current);
7601 }
7602 else
7603 {
7604 error_message = "invalid string: ill-formed UTF-8 byte";
7605 return false;
7606 }
7607 }
7608
7609 return true;
7610 }
7611
7627 token_type scan_string()
7628 {
7629 // reset token_buffer (ignore opening quote)
7630 reset();
7631
7632 // we entered the function by reading an open quote
7633 JSON_ASSERT(current == '\"');
7634
7635 while (true)
7636 {
7637 // get next character
7638 switch (get())
7639 {
7640 // end of file while parsing string
7641 case char_traits<char_type>::eof():
7642 {
7643 error_message = "invalid string: missing closing quote";
7645 }
7646
7647 // closing quote
7648 case '\"':
7649 {
7650 return token_type::value_string;
7651 }
7652
7653 // escapes
7654 case '\\':
7655 {
7656 switch (get())
7657 {
7658 // quotation mark
7659 case '\"':
7660 add('\"');
7661 break;
7662 // reverse solidus
7663 case '\\':
7664 add('\\');
7665 break;
7666 // solidus
7667 case '/':
7668 add('/');
7669 break;
7670 // backspace
7671 case 'b':
7672 add('\b');
7673 break;
7674 // form feed
7675 case 'f':
7676 add('\f');
7677 break;
7678 // line feed
7679 case 'n':
7680 add('\n');
7681 break;
7682 // carriage return
7683 case 'r':
7684 add('\r');
7685 break;
7686 // tab
7687 case 't':
7688 add('\t');
7689 break;
7690
7691 // unicode escapes
7692 case 'u':
7693 {
7694 const int codepoint1 = get_codepoint();
7695 int codepoint = codepoint1; // start with codepoint1
7696
7697 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7698 {
7699 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7700 return token_type::parse_error;
7701 }
7702
7703 // check if code point is a high surrogate
7704 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7705 {
7706 // expect next \uxxxx entry
7707 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7708 {
7709 const int codepoint2 = get_codepoint();
7710
7711 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7712 {
7713 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7714 return token_type::parse_error;
7715 }
7716
7717 // check if codepoint2 is a low surrogate
7718 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7719 {
7720 // overwrite codepoint
7721 codepoint = static_cast<int>(
7722 // high surrogate occupies the most significant 22 bits
7723 (static_cast<unsigned int>(codepoint1) << 10u)
7724 // low surrogate occupies the least significant 15 bits
7725 + static_cast<unsigned int>(codepoint2)
7726 // there is still the 0xD800, 0xDC00 and 0x10000 noise
7727 // in the result, so we have to subtract with:
7728 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7729 - 0x35FDC00u);
7730 }
7731 else
7732 {
7733 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7734 return token_type::parse_error;
7735 }
7736 }
7737 else
7738 {
7739 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7740 return token_type::parse_error;
7741 }
7742 }
7743 else
7744 {
7745 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7746 {
7747 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7748 return token_type::parse_error;
7749 }
7750 }
7751
7752 // result of the above calculation yields a proper codepoint
7753 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7754
7755 // translate codepoint into bytes
7756 if (codepoint < 0x80)
7757 {
7758 // 1-byte characters: 0xxxxxxx (ASCII)
7759 add(static_cast<char_int_type>(codepoint));
7760 }
7761 else if (codepoint <= 0x7FF)
7762 {
7763 // 2-byte characters: 110xxxxx 10xxxxxx
7764 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7765 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7766 }
7767 else if (codepoint <= 0xFFFF)
7768 {
7769 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7770 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7771 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7772 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7773 }
7774 else
7775 {
7776 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7777 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7778 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7779 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7780 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7781 }
7782
7783 break;
7784 }
7785
7786 // other characters after escape
7787 default:
7788 error_message = "invalid string: forbidden character after backslash";
7789 return token_type::parse_error;
7790 }
7791
7792 break;
7793 }
7794
7795 // invalid control characters
7796 case 0x00:
7797 {
7798 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7799 return token_type::parse_error;
7800 }
7801
7802 case 0x01:
7803 {
7804 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7805 return token_type::parse_error;
7806 }
7807
7808 case 0x02:
7809 {
7810 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7811 return token_type::parse_error;
7812 }
7813
7814 case 0x03:
7815 {
7816 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7817 return token_type::parse_error;
7818 }
7819
7820 case 0x04:
7821 {
7822 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7823 return token_type::parse_error;
7824 }
7825
7826 case 0x05:
7827 {
7828 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7829 return token_type::parse_error;
7830 }
7831
7832 case 0x06:
7833 {
7834 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7835 return token_type::parse_error;
7836 }
7837
7838 case 0x07:
7839 {
7840 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7841 return token_type::parse_error;
7842 }
7843
7844 case 0x08:
7845 {
7846 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7847 return token_type::parse_error;
7848 }
7849
7850 case 0x09:
7851 {
7852 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7853 return token_type::parse_error;
7854 }
7855
7856 case 0x0A:
7857 {
7858 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7859 return token_type::parse_error;
7860 }
7861
7862 case 0x0B:
7863 {
7864 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7865 return token_type::parse_error;
7866 }
7867
7868 case 0x0C:
7869 {
7870 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7871 return token_type::parse_error;
7872 }
7873
7874 case 0x0D:
7875 {
7876 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7877 return token_type::parse_error;
7878 }
7879
7880 case 0x0E:
7881 {
7882 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7883 return token_type::parse_error;
7884 }
7885
7886 case 0x0F:
7887 {
7888 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7889 return token_type::parse_error;
7890 }
7891
7892 case 0x10:
7893 {
7894 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7895 return token_type::parse_error;
7896 }
7897
7898 case 0x11:
7899 {
7900 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7901 return token_type::parse_error;
7902 }
7903
7904 case 0x12:
7905 {
7906 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7907 return token_type::parse_error;
7908 }
7909
7910 case 0x13:
7911 {
7912 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7913 return token_type::parse_error;
7914 }
7915
7916 case 0x14:
7917 {
7918 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7919 return token_type::parse_error;
7920 }
7921
7922 case 0x15:
7923 {
7924 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7925 return token_type::parse_error;
7926 }
7927
7928 case 0x16:
7929 {
7930 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7931 return token_type::parse_error;
7932 }
7933
7934 case 0x17:
7935 {
7936 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7937 return token_type::parse_error;
7938 }
7939
7940 case 0x18:
7941 {
7942 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7943 return token_type::parse_error;
7944 }
7945
7946 case 0x19:
7947 {
7948 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7949 return token_type::parse_error;
7950 }
7951
7952 case 0x1A:
7953 {
7954 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7955 return token_type::parse_error;
7956 }
7957
7958 case 0x1B:
7959 {
7960 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7961 return token_type::parse_error;
7962 }
7963
7964 case 0x1C:
7965 {
7966 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7967 return token_type::parse_error;
7968 }
7969
7970 case 0x1D:
7971 {
7972 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7973 return token_type::parse_error;
7974 }
7975
7976 case 0x1E:
7977 {
7978 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7979 return token_type::parse_error;
7980 }
7981
7982 case 0x1F:
7983 {
7984 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7985 return token_type::parse_error;
7986 }
7987
7988 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7989 case 0x20:
7990 case 0x21:
7991 case 0x23:
7992 case 0x24:
7993 case 0x25:
7994 case 0x26:
7995 case 0x27:
7996 case 0x28:
7997 case 0x29:
7998 case 0x2A:
7999 case 0x2B:
8000 case 0x2C:
8001 case 0x2D:
8002 case 0x2E:
8003 case 0x2F:
8004 case 0x30:
8005 case 0x31:
8006 case 0x32:
8007 case 0x33:
8008 case 0x34:
8009 case 0x35:
8010 case 0x36:
8011 case 0x37:
8012 case 0x38:
8013 case 0x39:
8014 case 0x3A:
8015 case 0x3B:
8016 case 0x3C:
8017 case 0x3D:
8018 case 0x3E:
8019 case 0x3F:
8020 case 0x40:
8021 case 0x41:
8022 case 0x42:
8023 case 0x43:
8024 case 0x44:
8025 case 0x45:
8026 case 0x46:
8027 case 0x47:
8028 case 0x48:
8029 case 0x49:
8030 case 0x4A:
8031 case 0x4B:
8032 case 0x4C:
8033 case 0x4D:
8034 case 0x4E:
8035 case 0x4F:
8036 case 0x50:
8037 case 0x51:
8038 case 0x52:
8039 case 0x53:
8040 case 0x54:
8041 case 0x55:
8042 case 0x56:
8043 case 0x57:
8044 case 0x58:
8045 case 0x59:
8046 case 0x5A:
8047 case 0x5B:
8048 case 0x5D:
8049 case 0x5E:
8050 case 0x5F:
8051 case 0x60:
8052 case 0x61:
8053 case 0x62:
8054 case 0x63:
8055 case 0x64:
8056 case 0x65:
8057 case 0x66:
8058 case 0x67:
8059 case 0x68:
8060 case 0x69:
8061 case 0x6A:
8062 case 0x6B:
8063 case 0x6C:
8064 case 0x6D:
8065 case 0x6E:
8066 case 0x6F:
8067 case 0x70:
8068 case 0x71:
8069 case 0x72:
8070 case 0x73:
8071 case 0x74:
8072 case 0x75:
8073 case 0x76:
8074 case 0x77:
8075 case 0x78:
8076 case 0x79:
8077 case 0x7A:
8078 case 0x7B:
8079 case 0x7C:
8080 case 0x7D:
8081 case 0x7E:
8082 case 0x7F:
8083 {
8084 add(current);
8085 break;
8086 }
8087
8088 // U+0080..U+07FF: bytes C2..DF 80..BF
8089 case 0xC2:
8090 case 0xC3:
8091 case 0xC4:
8092 case 0xC5:
8093 case 0xC6:
8094 case 0xC7:
8095 case 0xC8:
8096 case 0xC9:
8097 case 0xCA:
8098 case 0xCB:
8099 case 0xCC:
8100 case 0xCD:
8101 case 0xCE:
8102 case 0xCF:
8103 case 0xD0:
8104 case 0xD1:
8105 case 0xD2:
8106 case 0xD3:
8107 case 0xD4:
8108 case 0xD5:
8109 case 0xD6:
8110 case 0xD7:
8111 case 0xD8:
8112 case 0xD9:
8113 case 0xDA:
8114 case 0xDB:
8115 case 0xDC:
8116 case 0xDD:
8117 case 0xDE:
8118 case 0xDF:
8119 {
8120 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
8121 {
8122 return token_type::parse_error;
8123 }
8124 break;
8125 }
8126
8127 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
8128 case 0xE0:
8129 {
8130 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
8131 {
8132 return token_type::parse_error;
8133 }
8134 break;
8135 }
8136
8137 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
8138 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
8139 case 0xE1:
8140 case 0xE2:
8141 case 0xE3:
8142 case 0xE4:
8143 case 0xE5:
8144 case 0xE6:
8145 case 0xE7:
8146 case 0xE8:
8147 case 0xE9:
8148 case 0xEA:
8149 case 0xEB:
8150 case 0xEC:
8151 case 0xEE:
8152 case 0xEF:
8153 {
8154 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
8155 {
8156 return token_type::parse_error;
8157 }
8158 break;
8159 }
8160
8161 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
8162 case 0xED:
8163 {
8164 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
8165 {
8166 return token_type::parse_error;
8167 }
8168 break;
8169 }
8170
8171 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
8172 case 0xF0:
8173 {
8174 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8175 {
8176 return token_type::parse_error;
8177 }
8178 break;
8179 }
8180
8181 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
8182 case 0xF1:
8183 case 0xF2:
8184 case 0xF3:
8185 {
8186 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8187 {
8188 return token_type::parse_error;
8189 }
8190 break;
8191 }
8192
8193 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
8194 case 0xF4:
8195 {
8196 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
8197 {
8198 return token_type::parse_error;
8199 }
8200 break;
8201 }
8202
8203 // remaining bytes (80..C1 and F5..FF) are ill-formed
8204 default:
8205 {
8206 error_message = "invalid string: ill-formed UTF-8 byte";
8207 return token_type::parse_error;
8208 }
8209 }
8210 }
8211 }
8212
8217 bool scan_comment()
8218 {
8219 switch (get())
8220 {
8221 // single-line comments skip input until a newline or EOF is read
8222 case '/':
8223 {
8224 while (true)
8225 {
8226 switch (get())
8227 {
8228 case '\n':
8229 case '\r':
8230 case char_traits<char_type>::eof():
8231 case '\0':
8232 return true;
8233
8234 default:
8235 break;
8236 }
8237 }
8238 }
8239
8240 // multi-line comments skip input until */ is read
8241 case '*':
8242 {
8243 while (true)
8244 {
8245 switch (get())
8246 {
8247 case char_traits<char_type>::eof():
8248 case '\0':
8249 {
8250 error_message = "invalid comment; missing closing '*/'";
8251 return false;
8252 }
8253
8254 case '*':
8255 {
8256 switch (get())
8257 {
8258 case '/':
8259 return true;
8260
8261 default:
8262 {
8263 unget();
8264 continue;
8265 }
8266 }
8267 }
8268
8269 default:
8270 continue;
8271 }
8272 }
8273 }
8274
8275 // unexpected character after reading '/'
8276 default:
8277 {
8278 error_message = "invalid comment; expecting '/' or '*' after '/'";
8279 return false;
8280 }
8281 }
8282 }
8283
8284 JSON_HEDLEY_NON_NULL(2)
8285 static void strtof(float& f, const char* str, char** endptr) noexcept
8286 {
8287 f = std::strtof(str, endptr);
8288 }
8289
8290 JSON_HEDLEY_NON_NULL(2)
8291 static void strtof(double& f, const char* str, char** endptr) noexcept
8292 {
8293 f = std::strtod(str, endptr);
8294 }
8295
8296 JSON_HEDLEY_NON_NULL(2)
8297 static void strtof(long double& f, const char* str, char** endptr) noexcept
8298 {
8299 f = std::strtold(str, endptr);
8300 }
8301
8342 token_type scan_number() // lgtm [cpp/use-of-goto]
8343 {
8344 // reset token_buffer to store the number's bytes
8345 reset();
8346
8347 // the type of the parsed number; initially set to unsigned; will be
8348 // changed if minus sign, decimal point or exponent is read
8349 token_type number_type = token_type::value_unsigned;
8350
8351 // state (init): we just found out we need to scan a number
8352 switch (current)
8353 {
8354 case '-':
8355 {
8356 add(current);
8357 goto scan_number_minus;
8358 }
8359
8360 case '0':
8361 {
8362 add(current);
8363 goto scan_number_zero;
8364 }
8365
8366 case '1':
8367 case '2':
8368 case '3':
8369 case '4':
8370 case '5':
8371 case '6':
8372 case '7':
8373 case '8':
8374 case '9':
8375 {
8376 add(current);
8377 goto scan_number_any1;
8378 }
8379
8380 // all other characters are rejected outside scan_number()
8381 default: // LCOV_EXCL_LINE
8382 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8383 }
8384
8385scan_number_minus:
8386 // state: we just parsed a leading minus sign
8387 number_type = token_type::value_integer;
8388 switch (get())
8389 {
8390 case '0':
8391 {
8392 add(current);
8393 goto scan_number_zero;
8394 }
8395
8396 case '1':
8397 case '2':
8398 case '3':
8399 case '4':
8400 case '5':
8401 case '6':
8402 case '7':
8403 case '8':
8404 case '9':
8405 {
8406 add(current);
8407 goto scan_number_any1;
8408 }
8409
8410 default:
8411 {
8412 error_message = "invalid number; expected digit after '-'";
8413 return token_type::parse_error;
8414 }
8415 }
8416
8417scan_number_zero:
8418 // state: we just parse a zero (maybe with a leading minus sign)
8419 switch (get())
8420 {
8421 case '.':
8422 {
8423 add(decimal_point_char);
8424 goto scan_number_decimal1;
8425 }
8426
8427 case 'e':
8428 case 'E':
8429 {
8430 add(current);
8431 goto scan_number_exponent;
8432 }
8433
8434 default:
8435 goto scan_number_done;
8436 }
8437
8438scan_number_any1:
8439 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8440 switch (get())
8441 {
8442 case '0':
8443 case '1':
8444 case '2':
8445 case '3':
8446 case '4':
8447 case '5':
8448 case '6':
8449 case '7':
8450 case '8':
8451 case '9':
8452 {
8453 add(current);
8454 goto scan_number_any1;
8455 }
8456
8457 case '.':
8458 {
8459 add(decimal_point_char);
8460 goto scan_number_decimal1;
8461 }
8462
8463 case 'e':
8464 case 'E':
8465 {
8466 add(current);
8467 goto scan_number_exponent;
8468 }
8469
8470 default:
8471 goto scan_number_done;
8472 }
8473
8474scan_number_decimal1:
8475 // state: we just parsed a decimal point
8476 number_type = token_type::value_float;
8477 switch (get())
8478 {
8479 case '0':
8480 case '1':
8481 case '2':
8482 case '3':
8483 case '4':
8484 case '5':
8485 case '6':
8486 case '7':
8487 case '8':
8488 case '9':
8489 {
8490 add(current);
8491 goto scan_number_decimal2;
8492 }
8493
8494 default:
8495 {
8496 error_message = "invalid number; expected digit after '.'";
8497 return token_type::parse_error;
8498 }
8499 }
8500
8501scan_number_decimal2:
8502 // we just parsed at least one number after a decimal point
8503 switch (get())
8504 {
8505 case '0':
8506 case '1':
8507 case '2':
8508 case '3':
8509 case '4':
8510 case '5':
8511 case '6':
8512 case '7':
8513 case '8':
8514 case '9':
8515 {
8516 add(current);
8517 goto scan_number_decimal2;
8518 }
8519
8520 case 'e':
8521 case 'E':
8522 {
8523 add(current);
8524 goto scan_number_exponent;
8525 }
8526
8527 default:
8528 goto scan_number_done;
8529 }
8530
8531scan_number_exponent:
8532 // we just parsed an exponent
8533 number_type = token_type::value_float;
8534 switch (get())
8535 {
8536 case '+':
8537 case '-':
8538 {
8539 add(current);
8540 goto scan_number_sign;
8541 }
8542
8543 case '0':
8544 case '1':
8545 case '2':
8546 case '3':
8547 case '4':
8548 case '5':
8549 case '6':
8550 case '7':
8551 case '8':
8552 case '9':
8553 {
8554 add(current);
8555 goto scan_number_any2;
8556 }
8557
8558 default:
8559 {
8560 error_message =
8561 "invalid number; expected '+', '-', or digit after exponent";
8562 return token_type::parse_error;
8563 }
8564 }
8565
8566scan_number_sign:
8567 // we just parsed an exponent sign
8568 switch (get())
8569 {
8570 case '0':
8571 case '1':
8572 case '2':
8573 case '3':
8574 case '4':
8575 case '5':
8576 case '6':
8577 case '7':
8578 case '8':
8579 case '9':
8580 {
8581 add(current);
8582 goto scan_number_any2;
8583 }
8584
8585 default:
8586 {
8587 error_message = "invalid number; expected digit after exponent sign";
8588 return token_type::parse_error;
8589 }
8590 }
8591
8592scan_number_any2:
8593 // we just parsed a number after the exponent or exponent sign
8594 switch (get())
8595 {
8596 case '0':
8597 case '1':
8598 case '2':
8599 case '3':
8600 case '4':
8601 case '5':
8602 case '6':
8603 case '7':
8604 case '8':
8605 case '9':
8606 {
8607 add(current);
8608 goto scan_number_any2;
8609 }
8610
8611 default:
8612 goto scan_number_done;
8613 }
8614
8615scan_number_done:
8616 // unget the character after the number (we only read it to know that
8617 // we are done scanning a number)
8618 unget();
8619
8620 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8621 errno = 0;
8622
8623 // try to parse integers first and fall back to floats
8624 if (number_type == token_type::value_unsigned)
8625 {
8626 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8627
8628 // we checked the number format before
8629 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8630
8631 if (errno == 0)
8632 {
8633 value_unsigned = static_cast<number_unsigned_t>(x);
8634 if (value_unsigned == x)
8635 {
8636 return token_type::value_unsigned;
8637 }
8638 }
8639 }
8640 else if (number_type == token_type::value_integer)
8641 {
8642 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8643
8644 // we checked the number format before
8645 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8646
8647 if (errno == 0)
8648 {
8649 value_integer = static_cast<number_integer_t>(x);
8650 if (value_integer == x)
8651 {
8652 return token_type::value_integer;
8653 }
8654 }
8655 }
8656
8657 // this code is reached if we parse a floating-point number or if an
8658 // integer conversion above failed
8659 strtof(value_float, token_buffer.data(), &endptr);
8660
8661 // we checked the number format before
8662 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8663
8664 return token_type::value_float;
8665 }
8666
8672 JSON_HEDLEY_NON_NULL(2)
8673 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8674 token_type return_type)
8675 {
8676 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8677 for (std::size_t i = 1; i < length; ++i)
8678 {
8679 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8680 {
8681 error_message = "invalid literal";
8682 return token_type::parse_error;
8683 }
8684 }
8685 return return_type;
8686 }
8687
8689 // input management
8691
8693 void reset() noexcept
8694 {
8695 token_buffer.clear();
8696 token_string.clear();
8697 token_string.push_back(char_traits<char_type>::to_char_type(current));
8698 }
8699
8700 /*
8701 @brief get next character from the input
8702
8703 This function provides the interface to the used input adapter. It does
8704 not throw in case the input reached EOF, but returns a
8705 `char_traits<char>::eof()` in that case. Stores the scanned characters
8706 for use in error messages.
8707
8708 @return character read from the input
8709 */
8710 char_int_type get()
8711 {
8712 ++position.chars_read_total;
8713 ++position.chars_read_current_line;
8714
8715 if (next_unget)
8716 {
8717 // just reset the next_unget variable and work with current
8718 next_unget = false;
8719 }
8720 else
8721 {
8722 current = ia.get_character();
8723 }
8724
8725 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8726 {
8727 token_string.push_back(char_traits<char_type>::to_char_type(current));
8728 }
8729
8730 if (current == '\n')
8731 {
8732 ++position.lines_read;
8733 position.chars_read_current_line = 0;
8734 }
8735
8736 return current;
8737 }
8738
8747 void unget()
8748 {
8749 next_unget = true;
8750
8751 --position.chars_read_total;
8752
8753 // in case we "unget" a newline, we have to also decrement the lines_read
8754 if (position.chars_read_current_line == 0)
8755 {
8756 if (position.lines_read > 0)
8757 {
8758 --position.lines_read;
8759 }
8760 }
8761 else
8762 {
8763 --position.chars_read_current_line;
8764 }
8765
8766 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8767 {
8768 JSON_ASSERT(!token_string.empty());
8769 token_string.pop_back();
8770 }
8771 }
8772
8774 void add(char_int_type c)
8775 {
8776 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8777 }
8778
8779 public:
8781 // value getters
8783
8785 constexpr number_integer_t get_number_integer() const noexcept
8786 {
8787 return value_integer;
8788 }
8789
8791 constexpr number_unsigned_t get_number_unsigned() const noexcept
8792 {
8793 return value_unsigned;
8794 }
8795
8797 constexpr number_float_t get_number_float() const noexcept
8798 {
8799 return value_float;
8800 }
8801
8803 string_t& get_string()
8804 {
8805 return token_buffer;
8806 }
8807
8809 // diagnostics
8811
8813 constexpr position_t get_position() const noexcept
8814 {
8815 return position;
8816 }
8817
8821 std::string get_token_string() const
8822 {
8823 // escape control characters
8824 std::string result;
8825 for (const auto c : token_string)
8826 {
8827 if (static_cast<unsigned char>(c) <= '\x1F')
8828 {
8829 // escape control characters
8830 std::array<char, 9> cs{{}};
8831 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8832 result += cs.data();
8833 }
8834 else
8835 {
8836 // add character as is
8837 result.push_back(static_cast<std::string::value_type>(c));
8838 }
8839 }
8840
8841 return result;
8842 }
8843
8845 JSON_HEDLEY_RETURNS_NON_NULL
8846 constexpr const char* get_error_message() const noexcept
8847 {
8848 return error_message;
8849 }
8850
8852 // actual scanner
8854
8860 {
8861 if (get() == 0xEF)
8862 {
8863 // check if we completely parse the BOM
8864 return get() == 0xBB && get() == 0xBF;
8865 }
8866
8867 // the first character is not the beginning of the BOM; unget it to
8868 // process is later
8869 unget();
8870 return true;
8871 }
8872
8873 void skip_whitespace()
8874 {
8875 do
8876 {
8877 get();
8878 }
8879 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8880 }
8881
8882 token_type scan()
8883 {
8884 // initially, skip the BOM
8885 if (position.chars_read_total == 0 && !skip_bom())
8886 {
8887 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8888 return token_type::parse_error;
8889 }
8890
8891 // read next character and ignore whitespace
8892 skip_whitespace();
8893
8894 // ignore comments
8895 while (ignore_comments && current == '/')
8896 {
8897 if (!scan_comment())
8898 {
8899 return token_type::parse_error;
8900 }
8901
8902 // skip following whitespace
8903 skip_whitespace();
8904 }
8905
8906 switch (current)
8907 {
8908 // structural characters
8909 case '[':
8910 return token_type::begin_array;
8911 case ']':
8912 return token_type::end_array;
8913 case '{':
8914 return token_type::begin_object;
8915 case '}':
8916 return token_type::end_object;
8917 case ':':
8918 return token_type::name_separator;
8919 case ',':
8920 return token_type::value_separator;
8921
8922 // literals
8923 case 't':
8924 {
8925 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')}};
8926 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8927 }
8928 case 'f':
8929 {
8930 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')}};
8931 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8932 }
8933 case 'n':
8934 {
8935 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')}};
8936 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8937 }
8938
8939 // string
8940 case '\"':
8941 return scan_string();
8942
8943 // number
8944 case '-':
8945 case '0':
8946 case '1':
8947 case '2':
8948 case '3':
8949 case '4':
8950 case '5':
8951 case '6':
8952 case '7':
8953 case '8':
8954 case '9':
8955 return scan_number();
8956
8957 // end of input (the null byte is needed when parsing from
8958 // string literals)
8959 case '\0':
8960 case char_traits<char_type>::eof():
8961 return token_type::end_of_input;
8962
8963 // error
8964 default:
8965 error_message = "invalid literal";
8966 return token_type::parse_error;
8967 }
8968 }
8969
8970 private:
8972 InputAdapterType ia;
8973
8975 const bool ignore_comments = false;
8976
8978 char_int_type current = char_traits<char_type>::eof();
8979
8981 bool next_unget = false;
8982
8984 position_t position {};
8985
8987 std::vector<char_type> token_string {};
8988
8990 string_t token_buffer {};
8991
8993 const char* error_message = "";
8994
8995 // number values
8996 number_integer_t value_integer = 0;
8997 number_unsigned_t value_unsigned = 0;
8998 number_float_t value_float = 0;
8999
9001 const char_int_type decimal_point_char = '.';
9002};
9003
9004} // namespace detail
9005NLOHMANN_JSON_NAMESPACE_END
9006
9007// #include <nlohmann/detail/macro_scope.hpp>
9008
9009// #include <nlohmann/detail/meta/is_sax.hpp>
9010// __ _____ _____ _____
9011// __| | __| | | | JSON for Modern C++
9012// | | |__ | | | | | | version 3.11.3
9013// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9014//
9015// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
9016// SPDX-License-Identifier: MIT
9017
9018
9019
9020#include <cstdint> // size_t
9021#include <utility> // declval
9022#include <string> // string
9023
9024// #include <nlohmann/detail/abi_macros.hpp>
9025
9026// #include <nlohmann/detail/meta/detected.hpp>
9027
9028// #include <nlohmann/detail/meta/type_traits.hpp>
9029
9030
9031NLOHMANN_JSON_NAMESPACE_BEGIN
9032namespace detail
9033{
9034
9035template<typename T>
9036using null_function_t = decltype(std::declval<T&>().null());
9037
9038template<typename T>
9039using boolean_function_t =
9040 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9041
9042template<typename T, typename Integer>
9043using number_integer_function_t =
9044 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9045
9046template<typename T, typename Unsigned>
9047using number_unsigned_function_t =
9048 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9049
9050template<typename T, typename Float, typename String>
9051using number_float_function_t = decltype(std::declval<T&>().number_float(
9052 std::declval<Float>(), std::declval<const String&>()));
9053
9054template<typename T, typename String>
9055using string_function_t =
9056 decltype(std::declval<T&>().string(std::declval<String&>()));
9057
9058template<typename T, typename Binary>
9059using binary_function_t =
9060 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9061
9062template<typename T>
9063using start_object_function_t =
9064 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9065
9066template<typename T, typename String>
9067using key_function_t =
9068 decltype(std::declval<T&>().key(std::declval<String&>()));
9069
9070template<typename T>
9071using end_object_function_t = decltype(std::declval<T&>().end_object());
9072
9073template<typename T>
9074using start_array_function_t =
9075 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9076
9077template<typename T>
9078using end_array_function_t = decltype(std::declval<T&>().end_array());
9079
9080template<typename T, typename Exception>
9081using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9082 std::declval<std::size_t>(), std::declval<const std::string&>(),
9083 std::declval<const Exception&>()));
9084
9085template<typename SAX, typename BasicJsonType>
9086struct is_sax
9087{
9088 private:
9089 static_assert(is_basic_json<BasicJsonType>::value,
9090 "BasicJsonType must be of type basic_json<...>");
9091
9092 using number_integer_t = typename BasicJsonType::number_integer_t;
9093 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9094 using number_float_t = typename BasicJsonType::number_float_t;
9095 using string_t = typename BasicJsonType::string_t;
9096 using binary_t = typename BasicJsonType::binary_t;
9097 using exception_t = typename BasicJsonType::exception;
9098
9099 public:
9100 static constexpr bool value =
9101 is_detected_exact<bool, null_function_t, SAX>::value &&
9102 is_detected_exact<bool, boolean_function_t, SAX>::value &&
9103 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
9104 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
9105 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
9106 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
9107 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
9108 is_detected_exact<bool, start_object_function_t, SAX>::value &&
9109 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
9110 is_detected_exact<bool, end_object_function_t, SAX>::value &&
9111 is_detected_exact<bool, start_array_function_t, SAX>::value &&
9112 is_detected_exact<bool, end_array_function_t, SAX>::value &&
9113 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
9114};
9115
9116template<typename SAX, typename BasicJsonType>
9117struct is_sax_static_asserts
9118{
9119 private:
9120 static_assert(is_basic_json<BasicJsonType>::value,
9121 "BasicJsonType must be of type basic_json<...>");
9122
9123 using number_integer_t = typename BasicJsonType::number_integer_t;
9124 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9125 using number_float_t = typename BasicJsonType::number_float_t;
9126 using string_t = typename BasicJsonType::string_t;
9127 using binary_t = typename BasicJsonType::binary_t;
9128 using exception_t = typename BasicJsonType::exception;
9129
9130 public:
9131 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
9132 "Missing/invalid function: bool null()");
9133 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9134 "Missing/invalid function: bool boolean(bool)");
9135 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9136 "Missing/invalid function: bool boolean(bool)");
9137 static_assert(
9138 is_detected_exact<bool, number_integer_function_t, SAX,
9139 number_integer_t>::value,
9140 "Missing/invalid function: bool number_integer(number_integer_t)");
9141 static_assert(
9142 is_detected_exact<bool, number_unsigned_function_t, SAX,
9143 number_unsigned_t>::value,
9144 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9145 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9146 number_float_t, string_t>::value,
9147 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9148 static_assert(
9149 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
9150 "Missing/invalid function: bool string(string_t&)");
9151 static_assert(
9152 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
9153 "Missing/invalid function: bool binary(binary_t&)");
9154 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
9155 "Missing/invalid function: bool start_object(std::size_t)");
9156 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
9157 "Missing/invalid function: bool key(string_t&)");
9158 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
9159 "Missing/invalid function: bool end_object()");
9160 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
9161 "Missing/invalid function: bool start_array(std::size_t)");
9162 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
9163 "Missing/invalid function: bool end_array()");
9164 static_assert(
9165 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
9166 "Missing/invalid function: bool parse_error(std::size_t, const "
9167 "std::string&, const exception&)");
9168};
9169
9170} // namespace detail
9171NLOHMANN_JSON_NAMESPACE_END
9172
9173// #include <nlohmann/detail/meta/type_traits.hpp>
9174
9175// #include <nlohmann/detail/string_concat.hpp>
9176
9177// #include <nlohmann/detail/value_t.hpp>
9178
9179
9180NLOHMANN_JSON_NAMESPACE_BEGIN
9181namespace detail
9182{
9183
9186{
9187 error,
9188 ignore,
9189 store
9190};
9191
9199static inline bool little_endianness(int num = 1) noexcept
9200{
9201 return *reinterpret_cast<char*>(&num) == 1;
9202}
9203
9205// binary reader //
9207
9211template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
9212class binary_reader
9213{
9214 using number_integer_t = typename BasicJsonType::number_integer_t;
9215 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9216 using number_float_t = typename BasicJsonType::number_float_t;
9217 using string_t = typename BasicJsonType::string_t;
9218 using binary_t = typename BasicJsonType::binary_t;
9219 using json_sax_t = SAX;
9220 using char_type = typename InputAdapterType::char_type;
9221 using char_int_type = typename char_traits<char_type>::int_type;
9222
9223 public:
9229 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9230 {
9232 }
9233
9234 // make class move-only
9235 binary_reader(const binary_reader&) = delete;
9236 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9237 binary_reader& operator=(const binary_reader&) = delete;
9238 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9239 ~binary_reader() = default;
9240
9249 JSON_HEDLEY_NON_NULL(3)
9250 bool sax_parse(const input_format_t format,
9251 json_sax_t* sax_,
9252 const bool strict = true,
9253 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9254 {
9255 sax = sax_;
9256 bool result = false;
9257
9258 switch (format)
9259 {
9260 case input_format_t::bson:
9261 result = parse_bson_internal();
9262 break;
9263
9264 case input_format_t::cbor:
9265 result = parse_cbor_internal(true, tag_handler);
9266 break;
9267
9268 case input_format_t::msgpack:
9269 result = parse_msgpack_internal();
9270 break;
9271
9272 case input_format_t::ubjson:
9273 case input_format_t::bjdata:
9274 result = parse_ubjson_internal();
9275 break;
9276
9277 case input_format_t::json: // LCOV_EXCL_LINE
9278 default: // LCOV_EXCL_LINE
9279 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9280 }
9281
9282 // strict mode: next byte must be EOF
9283 if (result && strict)
9284 {
9285 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9286 {
9287 get_ignore_noop();
9288 }
9289 else
9290 {
9291 get();
9292 }
9293
9294 if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
9295 {
9296 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9297 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9298 }
9299 }
9300
9301 return result;
9302 }
9303
9304 private:
9306 // BSON //
9308
9313 bool parse_bson_internal()
9314 {
9315 std::int32_t document_size{};
9316 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9317
9318 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
9319 {
9320 return false;
9321 }
9322
9323 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9324 {
9325 return false;
9326 }
9327
9328 return sax->end_object();
9329 }
9330
9338 bool get_bson_cstr(string_t& result)
9339 {
9340 auto out = std::back_inserter(result);
9341 while (true)
9342 {
9343 get();
9344 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
9345 {
9346 return false;
9347 }
9348 if (current == 0x00)
9349 {
9350 return true;
9351 }
9352 *out++ = static_cast<typename string_t::value_type>(current);
9353 }
9354 }
9355
9367 template<typename NumberType>
9368 bool get_bson_string(const NumberType len, string_t& result)
9369 {
9370 if (JSON_HEDLEY_UNLIKELY(len < 1))
9371 {
9372 auto last_token = get_token_string();
9373 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9374 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
9375 }
9376
9377 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
9378 }
9379
9389 template<typename NumberType>
9390 bool get_bson_binary(const NumberType len, binary_t& result)
9391 {
9392 if (JSON_HEDLEY_UNLIKELY(len < 0))
9393 {
9394 auto last_token = get_token_string();
9395 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9396 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
9397 }
9398
9399 // All BSON binary values have a subtype
9400 std::uint8_t subtype{};
9401 get_number<std::uint8_t>(input_format_t::bson, subtype);
9402 result.set_subtype(subtype);
9403
9404 return get_binary(input_format_t::bson, len, result);
9405 }
9406
9417 bool parse_bson_element_internal(const char_int_type element_type,
9418 const std::size_t element_type_parse_position)
9419 {
9420 switch (element_type)
9421 {
9422 case 0x01: // double
9423 {
9424 double number{};
9425 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9426 }
9427
9428 case 0x02: // string
9429 {
9430 std::int32_t len{};
9431 string_t value;
9432 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
9433 }
9434
9435 case 0x03: // object
9436 {
9437 return parse_bson_internal();
9438 }
9439
9440 case 0x04: // array
9441 {
9442 return parse_bson_array();
9443 }
9444
9445 case 0x05: // binary
9446 {
9447 std::int32_t len{};
9448 binary_t value;
9449 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9450 }
9451
9452 case 0x08: // boolean
9453 {
9454 return sax->boolean(get() != 0);
9455 }
9456
9457 case 0x0A: // null
9458 {
9459 return sax->null();
9460 }
9461
9462 case 0x10: // int32
9463 {
9464 std::int32_t value{};
9465 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9466 }
9467
9468 case 0x12: // int64
9469 {
9470 std::int64_t value{};
9471 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9472 }
9473
9474 default: // anything else not supported (yet)
9475 {
9476 std::array<char, 3> cr{{}};
9477 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9478 const std::string cr_str{cr.data()};
9479 return sax->parse_error(element_type_parse_position, cr_str,
9480 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
9481 }
9482 }
9483 }
9484
9497 bool parse_bson_element_list(const bool is_array)
9498 {
9499 string_t key;
9500
9501 while (auto element_type = get())
9502 {
9503 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
9504 {
9505 return false;
9506 }
9507
9508 const std::size_t element_type_parse_position = chars_read;
9509 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
9510 {
9511 return false;
9512 }
9513
9514 if (!is_array && !sax->key(key))
9515 {
9516 return false;
9517 }
9518
9519 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
9520 {
9521 return false;
9522 }
9523
9524 // get_bson_cstr only appends
9525 key.clear();
9526 }
9527
9528 return true;
9529 }
9530
9535 bool parse_bson_array()
9536 {
9537 std::int32_t document_size{};
9538 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9539
9540 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
9541 {
9542 return false;
9543 }
9544
9545 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
9546 {
9547 return false;
9548 }
9549
9550 return sax->end_array();
9551 }
9552
9554 // CBOR //
9556
9565 bool parse_cbor_internal(const bool get_char,
9566 const cbor_tag_handler_t tag_handler)
9567 {
9568 switch (get_char ? get() : current)
9569 {
9570 // EOF
9571 case char_traits<char_type>::eof():
9572 return unexpect_eof(input_format_t::cbor, "value");
9573
9574 // Integer 0x00..0x17 (0..23)
9575 case 0x00:
9576 case 0x01:
9577 case 0x02:
9578 case 0x03:
9579 case 0x04:
9580 case 0x05:
9581 case 0x06:
9582 case 0x07:
9583 case 0x08:
9584 case 0x09:
9585 case 0x0A:
9586 case 0x0B:
9587 case 0x0C:
9588 case 0x0D:
9589 case 0x0E:
9590 case 0x0F:
9591 case 0x10:
9592 case 0x11:
9593 case 0x12:
9594 case 0x13:
9595 case 0x14:
9596 case 0x15:
9597 case 0x16:
9598 case 0x17:
9599 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9600
9601 case 0x18: // Unsigned integer (one-byte uint8_t follows)
9602 {
9603 std::uint8_t number{};
9604 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9605 }
9606
9607 case 0x19: // Unsigned integer (two-byte uint16_t follows)
9608 {
9609 std::uint16_t number{};
9610 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9611 }
9612
9613 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9614 {
9615 std::uint32_t number{};
9616 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9617 }
9618
9619 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9620 {
9621 std::uint64_t number{};
9622 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9623 }
9624
9625 // Negative integer -1-0x00..-1-0x17 (-1..-24)
9626 case 0x20:
9627 case 0x21:
9628 case 0x22:
9629 case 0x23:
9630 case 0x24:
9631 case 0x25:
9632 case 0x26:
9633 case 0x27:
9634 case 0x28:
9635 case 0x29:
9636 case 0x2A:
9637 case 0x2B:
9638 case 0x2C:
9639 case 0x2D:
9640 case 0x2E:
9641 case 0x2F:
9642 case 0x30:
9643 case 0x31:
9644 case 0x32:
9645 case 0x33:
9646 case 0x34:
9647 case 0x35:
9648 case 0x36:
9649 case 0x37:
9650 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9651
9652 case 0x38: // Negative integer (one-byte uint8_t follows)
9653 {
9654 std::uint8_t number{};
9655 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9656 }
9657
9658 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9659 {
9660 std::uint16_t number{};
9661 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9662 }
9663
9664 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9665 {
9666 std::uint32_t number{};
9667 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9668 }
9669
9670 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9671 {
9672 std::uint64_t number{};
9673 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
9674 - static_cast<number_integer_t>(number));
9675 }
9676
9677 // Binary data (0x00..0x17 bytes follow)
9678 case 0x40:
9679 case 0x41:
9680 case 0x42:
9681 case 0x43:
9682 case 0x44:
9683 case 0x45:
9684 case 0x46:
9685 case 0x47:
9686 case 0x48:
9687 case 0x49:
9688 case 0x4A:
9689 case 0x4B:
9690 case 0x4C:
9691 case 0x4D:
9692 case 0x4E:
9693 case 0x4F:
9694 case 0x50:
9695 case 0x51:
9696 case 0x52:
9697 case 0x53:
9698 case 0x54:
9699 case 0x55:
9700 case 0x56:
9701 case 0x57:
9702 case 0x58: // Binary data (one-byte uint8_t for n follows)
9703 case 0x59: // Binary data (two-byte uint16_t for n follow)
9704 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9705 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9706 case 0x5F: // Binary data (indefinite length)
9707 {
9708 binary_t b;
9709 return get_cbor_binary(b) && sax->binary(b);
9710 }
9711
9712 // UTF-8 string (0x00..0x17 bytes follow)
9713 case 0x60:
9714 case 0x61:
9715 case 0x62:
9716 case 0x63:
9717 case 0x64:
9718 case 0x65:
9719 case 0x66:
9720 case 0x67:
9721 case 0x68:
9722 case 0x69:
9723 case 0x6A:
9724 case 0x6B:
9725 case 0x6C:
9726 case 0x6D:
9727 case 0x6E:
9728 case 0x6F:
9729 case 0x70:
9730 case 0x71:
9731 case 0x72:
9732 case 0x73:
9733 case 0x74:
9734 case 0x75:
9735 case 0x76:
9736 case 0x77:
9737 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9738 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9739 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9740 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9741 case 0x7F: // UTF-8 string (indefinite length)
9742 {
9743 string_t s;
9744 return get_cbor_string(s) && sax->string(s);
9745 }
9746
9747 // array (0x00..0x17 data items follow)
9748 case 0x80:
9749 case 0x81:
9750 case 0x82:
9751 case 0x83:
9752 case 0x84:
9753 case 0x85:
9754 case 0x86:
9755 case 0x87:
9756 case 0x88:
9757 case 0x89:
9758 case 0x8A:
9759 case 0x8B:
9760 case 0x8C:
9761 case 0x8D:
9762 case 0x8E:
9763 case 0x8F:
9764 case 0x90:
9765 case 0x91:
9766 case 0x92:
9767 case 0x93:
9768 case 0x94:
9769 case 0x95:
9770 case 0x96:
9771 case 0x97:
9772 return get_cbor_array(
9773 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9774
9775 case 0x98: // array (one-byte uint8_t for n follows)
9776 {
9777 std::uint8_t len{};
9778 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9779 }
9780
9781 case 0x99: // array (two-byte uint16_t for n follow)
9782 {
9783 std::uint16_t len{};
9784 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9785 }
9786
9787 case 0x9A: // array (four-byte uint32_t for n follow)
9788 {
9789 std::uint32_t len{};
9790 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9791 }
9792
9793 case 0x9B: // array (eight-byte uint64_t for n follow)
9794 {
9795 std::uint64_t len{};
9796 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9797 }
9798
9799 case 0x9F: // array (indefinite length)
9800 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
9801
9802 // map (0x00..0x17 pairs of data items follow)
9803 case 0xA0:
9804 case 0xA1:
9805 case 0xA2:
9806 case 0xA3:
9807 case 0xA4:
9808 case 0xA5:
9809 case 0xA6:
9810 case 0xA7:
9811 case 0xA8:
9812 case 0xA9:
9813 case 0xAA:
9814 case 0xAB:
9815 case 0xAC:
9816 case 0xAD:
9817 case 0xAE:
9818 case 0xAF:
9819 case 0xB0:
9820 case 0xB1:
9821 case 0xB2:
9822 case 0xB3:
9823 case 0xB4:
9824 case 0xB5:
9825 case 0xB6:
9826 case 0xB7:
9827 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9828
9829 case 0xB8: // map (one-byte uint8_t for n follows)
9830 {
9831 std::uint8_t len{};
9832 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9833 }
9834
9835 case 0xB9: // map (two-byte uint16_t for n follow)
9836 {
9837 std::uint16_t len{};
9838 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9839 }
9840
9841 case 0xBA: // map (four-byte uint32_t for n follow)
9842 {
9843 std::uint32_t len{};
9844 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9845 }
9846
9847 case 0xBB: // map (eight-byte uint64_t for n follow)
9848 {
9849 std::uint64_t len{};
9850 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9851 }
9852
9853 case 0xBF: // map (indefinite length)
9854 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
9855
9856 case 0xC6: // tagged item
9857 case 0xC7:
9858 case 0xC8:
9859 case 0xC9:
9860 case 0xCA:
9861 case 0xCB:
9862 case 0xCC:
9863 case 0xCD:
9864 case 0xCE:
9865 case 0xCF:
9866 case 0xD0:
9867 case 0xD1:
9868 case 0xD2:
9869 case 0xD3:
9870 case 0xD4:
9871 case 0xD8: // tagged item (1 bytes follow)
9872 case 0xD9: // tagged item (2 bytes follow)
9873 case 0xDA: // tagged item (4 bytes follow)
9874 case 0xDB: // tagged item (8 bytes follow)
9875 {
9876 switch (tag_handler)
9877 {
9879 {
9880 auto last_token = get_token_string();
9881 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9882 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9883 }
9884
9886 {
9887 // ignore binary subtype
9888 switch (current)
9889 {
9890 case 0xD8:
9891 {
9892 std::uint8_t subtype_to_ignore{};
9893 get_number(input_format_t::cbor, subtype_to_ignore);
9894 break;
9895 }
9896 case 0xD9:
9897 {
9898 std::uint16_t subtype_to_ignore{};
9899 get_number(input_format_t::cbor, subtype_to_ignore);
9900 break;
9901 }
9902 case 0xDA:
9903 {
9904 std::uint32_t subtype_to_ignore{};
9905 get_number(input_format_t::cbor, subtype_to_ignore);
9906 break;
9907 }
9908 case 0xDB:
9909 {
9910 std::uint64_t subtype_to_ignore{};
9911 get_number(input_format_t::cbor, subtype_to_ignore);
9912 break;
9913 }
9914 default:
9915 break;
9916 }
9917 return parse_cbor_internal(true, tag_handler);
9918 }
9919
9921 {
9922 binary_t b;
9923 // use binary subtype and store in binary container
9924 switch (current)
9925 {
9926 case 0xD8:
9927 {
9928 std::uint8_t subtype{};
9929 get_number(input_format_t::cbor, subtype);
9930 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9931 break;
9932 }
9933 case 0xD9:
9934 {
9935 std::uint16_t subtype{};
9936 get_number(input_format_t::cbor, subtype);
9937 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9938 break;
9939 }
9940 case 0xDA:
9941 {
9942 std::uint32_t subtype{};
9943 get_number(input_format_t::cbor, subtype);
9944 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9945 break;
9946 }
9947 case 0xDB:
9948 {
9949 std::uint64_t subtype{};
9950 get_number(input_format_t::cbor, subtype);
9951 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9952 break;
9953 }
9954 default:
9955 return parse_cbor_internal(true, tag_handler);
9956 }
9957 get();
9958 return get_cbor_binary(b) && sax->binary(b);
9959 }
9960
9961 default: // LCOV_EXCL_LINE
9962 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9963 return false; // LCOV_EXCL_LINE
9964 }
9965 }
9966
9967 case 0xF4: // false
9968 return sax->boolean(false);
9969
9970 case 0xF5: // true
9971 return sax->boolean(true);
9972
9973 case 0xF6: // null
9974 return sax->null();
9975
9976 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
9977 {
9978 const auto byte1_raw = get();
9979 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9980 {
9981 return false;
9982 }
9983 const auto byte2_raw = get();
9984 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9985 {
9986 return false;
9987 }
9988
9989 const auto byte1 = static_cast<unsigned char>(byte1_raw);
9990 const auto byte2 = static_cast<unsigned char>(byte2_raw);
9991
9992 // code from RFC 7049, Appendix D, Figure 3:
9993 // As half-precision floating-point numbers were only added
9994 // to IEEE 754 in 2008, today's programming platforms often
9995 // still only have limited support for them. It is very
9996 // easy to include at least decoding support for them even
9997 // without such support. An example of a small decoder for
9998 // half-precision floating-point numbers in the C language
9999 // is shown in Fig. 3.
10000 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10001 const double val = [&half]
10002 {
10003 const int exp = (half >> 10u) & 0x1Fu;
10004 const unsigned int mant = half & 0x3FFu;
10005 JSON_ASSERT(0 <= exp&& exp <= 32);
10006 JSON_ASSERT(mant <= 1024);
10007 switch (exp)
10008 {
10009 case 0:
10010 return std::ldexp(mant, -24);
10011 case 31:
10012 return (mant == 0)
10013 ? std::numeric_limits<double>::infinity()
10014 : std::numeric_limits<double>::quiet_NaN();
10015 default:
10016 return std::ldexp(mant + 1024, exp - 25);
10017 }
10018 }();
10019 return sax->number_float((half & 0x8000u) != 0
10020 ? static_cast<number_float_t>(-val)
10021 : static_cast<number_float_t>(val), "");
10022 }
10023
10024 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10025 {
10026 float number{};
10027 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10028 }
10029
10030 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10031 {
10032 double number{};
10033 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10034 }
10035
10036 default: // anything else (0xFF is handled inside the other types)
10037 {
10038 auto last_token = get_token_string();
10039 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10040 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10041 }
10042 }
10043 }
10044
10056 bool get_cbor_string(string_t& result)
10057 {
10058 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10059 {
10060 return false;
10061 }
10062
10063 switch (current)
10064 {
10065 // UTF-8 string (0x00..0x17 bytes follow)
10066 case 0x60:
10067 case 0x61:
10068 case 0x62:
10069 case 0x63:
10070 case 0x64:
10071 case 0x65:
10072 case 0x66:
10073 case 0x67:
10074 case 0x68:
10075 case 0x69:
10076 case 0x6A:
10077 case 0x6B:
10078 case 0x6C:
10079 case 0x6D:
10080 case 0x6E:
10081 case 0x6F:
10082 case 0x70:
10083 case 0x71:
10084 case 0x72:
10085 case 0x73:
10086 case 0x74:
10087 case 0x75:
10088 case 0x76:
10089 case 0x77:
10090 {
10091 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10092 }
10093
10094 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10095 {
10096 std::uint8_t len{};
10097 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10098 }
10099
10100 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10101 {
10102 std::uint16_t len{};
10103 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10104 }
10105
10106 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10107 {
10108 std::uint32_t len{};
10109 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10110 }
10111
10112 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10113 {
10114 std::uint64_t len{};
10115 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10116 }
10117
10118 case 0x7F: // UTF-8 string (indefinite length)
10119 {
10120 while (get() != 0xFF)
10121 {
10122 string_t chunk;
10123 if (!get_cbor_string(chunk))
10124 {
10125 return false;
10126 }
10127 result.append(chunk);
10128 }
10129 return true;
10130 }
10131
10132 default:
10133 {
10134 auto last_token = get_token_string();
10135 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10136 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10137 }
10138 }
10139 }
10140
10152 bool get_cbor_binary(binary_t& result)
10153 {
10154 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10155 {
10156 return false;
10157 }
10158
10159 switch (current)
10160 {
10161 // Binary data (0x00..0x17 bytes follow)
10162 case 0x40:
10163 case 0x41:
10164 case 0x42:
10165 case 0x43:
10166 case 0x44:
10167 case 0x45:
10168 case 0x46:
10169 case 0x47:
10170 case 0x48:
10171 case 0x49:
10172 case 0x4A:
10173 case 0x4B:
10174 case 0x4C:
10175 case 0x4D:
10176 case 0x4E:
10177 case 0x4F:
10178 case 0x50:
10179 case 0x51:
10180 case 0x52:
10181 case 0x53:
10182 case 0x54:
10183 case 0x55:
10184 case 0x56:
10185 case 0x57:
10186 {
10187 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10188 }
10189
10190 case 0x58: // Binary data (one-byte uint8_t for n follows)
10191 {
10192 std::uint8_t len{};
10193 return get_number(input_format_t::cbor, len) &&
10194 get_binary(input_format_t::cbor, len, result);
10195 }
10196
10197 case 0x59: // Binary data (two-byte uint16_t for n follow)
10198 {
10199 std::uint16_t len{};
10200 return get_number(input_format_t::cbor, len) &&
10201 get_binary(input_format_t::cbor, len, result);
10202 }
10203
10204 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10205 {
10206 std::uint32_t len{};
10207 return get_number(input_format_t::cbor, len) &&
10208 get_binary(input_format_t::cbor, len, result);
10209 }
10210
10211 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10212 {
10213 std::uint64_t len{};
10214 return get_number(input_format_t::cbor, len) &&
10215 get_binary(input_format_t::cbor, len, result);
10216 }
10217
10218 case 0x5F: // Binary data (indefinite length)
10219 {
10220 while (get() != 0xFF)
10221 {
10222 binary_t chunk;
10223 if (!get_cbor_binary(chunk))
10224 {
10225 return false;
10226 }
10227 result.insert(result.end(), chunk.begin(), chunk.end());
10228 }
10229 return true;
10230 }
10231
10232 default:
10233 {
10234 auto last_token = get_token_string();
10235 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10236 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));
10237 }
10238 }
10239 }
10240
10247 bool get_cbor_array(const std::size_t len,
10248 const cbor_tag_handler_t tag_handler)
10249 {
10250 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10251 {
10252 return false;
10253 }
10254
10255 if (len != static_cast<std::size_t>(-1))
10256 {
10257 for (std::size_t i = 0; i < len; ++i)
10258 {
10259 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10260 {
10261 return false;
10262 }
10263 }
10264 }
10265 else
10266 {
10267 while (get() != 0xFF)
10268 {
10269 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10270 {
10271 return false;
10272 }
10273 }
10274 }
10275
10276 return sax->end_array();
10277 }
10278
10285 bool get_cbor_object(const std::size_t len,
10286 const cbor_tag_handler_t tag_handler)
10287 {
10288 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10289 {
10290 return false;
10291 }
10292
10293 if (len != 0)
10294 {
10295 string_t key;
10296 if (len != static_cast<std::size_t>(-1))
10297 {
10298 for (std::size_t i = 0; i < len; ++i)
10299 {
10300 get();
10301 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10302 {
10303 return false;
10304 }
10305
10306 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10307 {
10308 return false;
10309 }
10310 key.clear();
10311 }
10312 }
10313 else
10314 {
10315 while (get() != 0xFF)
10316 {
10317 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10318 {
10319 return false;
10320 }
10321
10322 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10323 {
10324 return false;
10325 }
10326 key.clear();
10327 }
10328 }
10329 }
10330
10331 return sax->end_object();
10332 }
10333
10335 // MsgPack //
10337
10341 bool parse_msgpack_internal()
10342 {
10343 switch (get())
10344 {
10345 // EOF
10346 case char_traits<char_type>::eof():
10347 return unexpect_eof(input_format_t::msgpack, "value");
10348
10349 // positive fixint
10350 case 0x00:
10351 case 0x01:
10352 case 0x02:
10353 case 0x03:
10354 case 0x04:
10355 case 0x05:
10356 case 0x06:
10357 case 0x07:
10358 case 0x08:
10359 case 0x09:
10360 case 0x0A:
10361 case 0x0B:
10362 case 0x0C:
10363 case 0x0D:
10364 case 0x0E:
10365 case 0x0F:
10366 case 0x10:
10367 case 0x11:
10368 case 0x12:
10369 case 0x13:
10370 case 0x14:
10371 case 0x15:
10372 case 0x16:
10373 case 0x17:
10374 case 0x18:
10375 case 0x19:
10376 case 0x1A:
10377 case 0x1B:
10378 case 0x1C:
10379 case 0x1D:
10380 case 0x1E:
10381 case 0x1F:
10382 case 0x20:
10383 case 0x21:
10384 case 0x22:
10385 case 0x23:
10386 case 0x24:
10387 case 0x25:
10388 case 0x26:
10389 case 0x27:
10390 case 0x28:
10391 case 0x29:
10392 case 0x2A:
10393 case 0x2B:
10394 case 0x2C:
10395 case 0x2D:
10396 case 0x2E:
10397 case 0x2F:
10398 case 0x30:
10399 case 0x31:
10400 case 0x32:
10401 case 0x33:
10402 case 0x34:
10403 case 0x35:
10404 case 0x36:
10405 case 0x37:
10406 case 0x38:
10407 case 0x39:
10408 case 0x3A:
10409 case 0x3B:
10410 case 0x3C:
10411 case 0x3D:
10412 case 0x3E:
10413 case 0x3F:
10414 case 0x40:
10415 case 0x41:
10416 case 0x42:
10417 case 0x43:
10418 case 0x44:
10419 case 0x45:
10420 case 0x46:
10421 case 0x47:
10422 case 0x48:
10423 case 0x49:
10424 case 0x4A:
10425 case 0x4B:
10426 case 0x4C:
10427 case 0x4D:
10428 case 0x4E:
10429 case 0x4F:
10430 case 0x50:
10431 case 0x51:
10432 case 0x52:
10433 case 0x53:
10434 case 0x54:
10435 case 0x55:
10436 case 0x56:
10437 case 0x57:
10438 case 0x58:
10439 case 0x59:
10440 case 0x5A:
10441 case 0x5B:
10442 case 0x5C:
10443 case 0x5D:
10444 case 0x5E:
10445 case 0x5F:
10446 case 0x60:
10447 case 0x61:
10448 case 0x62:
10449 case 0x63:
10450 case 0x64:
10451 case 0x65:
10452 case 0x66:
10453 case 0x67:
10454 case 0x68:
10455 case 0x69:
10456 case 0x6A:
10457 case 0x6B:
10458 case 0x6C:
10459 case 0x6D:
10460 case 0x6E:
10461 case 0x6F:
10462 case 0x70:
10463 case 0x71:
10464 case 0x72:
10465 case 0x73:
10466 case 0x74:
10467 case 0x75:
10468 case 0x76:
10469 case 0x77:
10470 case 0x78:
10471 case 0x79:
10472 case 0x7A:
10473 case 0x7B:
10474 case 0x7C:
10475 case 0x7D:
10476 case 0x7E:
10477 case 0x7F:
10478 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10479
10480 // fixmap
10481 case 0x80:
10482 case 0x81:
10483 case 0x82:
10484 case 0x83:
10485 case 0x84:
10486 case 0x85:
10487 case 0x86:
10488 case 0x87:
10489 case 0x88:
10490 case 0x89:
10491 case 0x8A:
10492 case 0x8B:
10493 case 0x8C:
10494 case 0x8D:
10495 case 0x8E:
10496 case 0x8F:
10497 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10498
10499 // fixarray
10500 case 0x90:
10501 case 0x91:
10502 case 0x92:
10503 case 0x93:
10504 case 0x94:
10505 case 0x95:
10506 case 0x96:
10507 case 0x97:
10508 case 0x98:
10509 case 0x99:
10510 case 0x9A:
10511 case 0x9B:
10512 case 0x9C:
10513 case 0x9D:
10514 case 0x9E:
10515 case 0x9F:
10516 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10517
10518 // fixstr
10519 case 0xA0:
10520 case 0xA1:
10521 case 0xA2:
10522 case 0xA3:
10523 case 0xA4:
10524 case 0xA5:
10525 case 0xA6:
10526 case 0xA7:
10527 case 0xA8:
10528 case 0xA9:
10529 case 0xAA:
10530 case 0xAB:
10531 case 0xAC:
10532 case 0xAD:
10533 case 0xAE:
10534 case 0xAF:
10535 case 0xB0:
10536 case 0xB1:
10537 case 0xB2:
10538 case 0xB3:
10539 case 0xB4:
10540 case 0xB5:
10541 case 0xB6:
10542 case 0xB7:
10543 case 0xB8:
10544 case 0xB9:
10545 case 0xBA:
10546 case 0xBB:
10547 case 0xBC:
10548 case 0xBD:
10549 case 0xBE:
10550 case 0xBF:
10551 case 0xD9: // str 8
10552 case 0xDA: // str 16
10553 case 0xDB: // str 32
10554 {
10555 string_t s;
10556 return get_msgpack_string(s) && sax->string(s);
10557 }
10558
10559 case 0xC0: // nil
10560 return sax->null();
10561
10562 case 0xC2: // false
10563 return sax->boolean(false);
10564
10565 case 0xC3: // true
10566 return sax->boolean(true);
10567
10568 case 0xC4: // bin 8
10569 case 0xC5: // bin 16
10570 case 0xC6: // bin 32
10571 case 0xC7: // ext 8
10572 case 0xC8: // ext 16
10573 case 0xC9: // ext 32
10574 case 0xD4: // fixext 1
10575 case 0xD5: // fixext 2
10576 case 0xD6: // fixext 4
10577 case 0xD7: // fixext 8
10578 case 0xD8: // fixext 16
10579 {
10580 binary_t b;
10581 return get_msgpack_binary(b) && sax->binary(b);
10582 }
10583
10584 case 0xCA: // float 32
10585 {
10586 float number{};
10587 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10588 }
10589
10590 case 0xCB: // float 64
10591 {
10592 double number{};
10593 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10594 }
10595
10596 case 0xCC: // uint 8
10597 {
10598 std::uint8_t number{};
10599 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10600 }
10601
10602 case 0xCD: // uint 16
10603 {
10604 std::uint16_t number{};
10605 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10606 }
10607
10608 case 0xCE: // uint 32
10609 {
10610 std::uint32_t number{};
10611 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10612 }
10613
10614 case 0xCF: // uint 64
10615 {
10616 std::uint64_t number{};
10617 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10618 }
10619
10620 case 0xD0: // int 8
10621 {
10622 std::int8_t number{};
10623 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10624 }
10625
10626 case 0xD1: // int 16
10627 {
10628 std::int16_t number{};
10629 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10630 }
10631
10632 case 0xD2: // int 32
10633 {
10634 std::int32_t number{};
10635 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10636 }
10637
10638 case 0xD3: // int 64
10639 {
10640 std::int64_t number{};
10641 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10642 }
10643
10644 case 0xDC: // array 16
10645 {
10646 std::uint16_t len{};
10647 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
10648 }
10649
10650 case 0xDD: // array 32
10651 {
10652 std::uint32_t len{};
10653 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10654 }
10655
10656 case 0xDE: // map 16
10657 {
10658 std::uint16_t len{};
10659 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
10660 }
10661
10662 case 0xDF: // map 32
10663 {
10664 std::uint32_t len{};
10665 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10666 }
10667
10668 // negative fixint
10669 case 0xE0:
10670 case 0xE1:
10671 case 0xE2:
10672 case 0xE3:
10673 case 0xE4:
10674 case 0xE5:
10675 case 0xE6:
10676 case 0xE7:
10677 case 0xE8:
10678 case 0xE9:
10679 case 0xEA:
10680 case 0xEB:
10681 case 0xEC:
10682 case 0xED:
10683 case 0xEE:
10684 case 0xEF:
10685 case 0xF0:
10686 case 0xF1:
10687 case 0xF2:
10688 case 0xF3:
10689 case 0xF4:
10690 case 0xF5:
10691 case 0xF6:
10692 case 0xF7:
10693 case 0xF8:
10694 case 0xF9:
10695 case 0xFA:
10696 case 0xFB:
10697 case 0xFC:
10698 case 0xFD:
10699 case 0xFE:
10700 case 0xFF:
10701 return sax->number_integer(static_cast<std::int8_t>(current));
10702
10703 default: // anything else
10704 {
10705 auto last_token = get_token_string();
10706 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10707 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
10708 }
10709 }
10710 }
10711
10722 bool get_msgpack_string(string_t& result)
10723 {
10724 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
10725 {
10726 return false;
10727 }
10728
10729 switch (current)
10730 {
10731 // fixstr
10732 case 0xA0:
10733 case 0xA1:
10734 case 0xA2:
10735 case 0xA3:
10736 case 0xA4:
10737 case 0xA5:
10738 case 0xA6:
10739 case 0xA7:
10740 case 0xA8:
10741 case 0xA9:
10742 case 0xAA:
10743 case 0xAB:
10744 case 0xAC:
10745 case 0xAD:
10746 case 0xAE:
10747 case 0xAF:
10748 case 0xB0:
10749 case 0xB1:
10750 case 0xB2:
10751 case 0xB3:
10752 case 0xB4:
10753 case 0xB5:
10754 case 0xB6:
10755 case 0xB7:
10756 case 0xB8:
10757 case 0xB9:
10758 case 0xBA:
10759 case 0xBB:
10760 case 0xBC:
10761 case 0xBD:
10762 case 0xBE:
10763 case 0xBF:
10764 {
10765 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
10766 }
10767
10768 case 0xD9: // str 8
10769 {
10770 std::uint8_t len{};
10771 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10772 }
10773
10774 case 0xDA: // str 16
10775 {
10776 std::uint16_t len{};
10777 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10778 }
10779
10780 case 0xDB: // str 32
10781 {
10782 std::uint32_t len{};
10783 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10784 }
10785
10786 default:
10787 {
10788 auto last_token = get_token_string();
10789 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10790 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
10791 }
10792 }
10793 }
10794
10805 bool get_msgpack_binary(binary_t& result)
10806 {
10807 // helper function to set the subtype
10808 auto assign_and_return_true = [&result](std::int8_t subtype)
10809 {
10810 result.set_subtype(static_cast<std::uint8_t>(subtype));
10811 return true;
10812 };
10813
10814 switch (current)
10815 {
10816 case 0xC4: // bin 8
10817 {
10818 std::uint8_t len{};
10819 return get_number(input_format_t::msgpack, len) &&
10820 get_binary(input_format_t::msgpack, len, result);
10821 }
10822
10823 case 0xC5: // bin 16
10824 {
10825 std::uint16_t len{};
10826 return get_number(input_format_t::msgpack, len) &&
10827 get_binary(input_format_t::msgpack, len, result);
10828 }
10829
10830 case 0xC6: // bin 32
10831 {
10832 std::uint32_t len{};
10833 return get_number(input_format_t::msgpack, len) &&
10834 get_binary(input_format_t::msgpack, len, result);
10835 }
10836
10837 case 0xC7: // ext 8
10838 {
10839 std::uint8_t len{};
10840 std::int8_t subtype{};
10841 return get_number(input_format_t::msgpack, len) &&
10842 get_number(input_format_t::msgpack, subtype) &&
10843 get_binary(input_format_t::msgpack, len, result) &&
10844 assign_and_return_true(subtype);
10845 }
10846
10847 case 0xC8: // ext 16
10848 {
10849 std::uint16_t len{};
10850 std::int8_t subtype{};
10851 return get_number(input_format_t::msgpack, len) &&
10852 get_number(input_format_t::msgpack, subtype) &&
10853 get_binary(input_format_t::msgpack, len, result) &&
10854 assign_and_return_true(subtype);
10855 }
10856
10857 case 0xC9: // ext 32
10858 {
10859 std::uint32_t len{};
10860 std::int8_t subtype{};
10861 return get_number(input_format_t::msgpack, len) &&
10862 get_number(input_format_t::msgpack, subtype) &&
10863 get_binary(input_format_t::msgpack, len, result) &&
10864 assign_and_return_true(subtype);
10865 }
10866
10867 case 0xD4: // fixext 1
10868 {
10869 std::int8_t subtype{};
10870 return get_number(input_format_t::msgpack, subtype) &&
10871 get_binary(input_format_t::msgpack, 1, result) &&
10872 assign_and_return_true(subtype);
10873 }
10874
10875 case 0xD5: // fixext 2
10876 {
10877 std::int8_t subtype{};
10878 return get_number(input_format_t::msgpack, subtype) &&
10879 get_binary(input_format_t::msgpack, 2, result) &&
10880 assign_and_return_true(subtype);
10881 }
10882
10883 case 0xD6: // fixext 4
10884 {
10885 std::int8_t subtype{};
10886 return get_number(input_format_t::msgpack, subtype) &&
10887 get_binary(input_format_t::msgpack, 4, result) &&
10888 assign_and_return_true(subtype);
10889 }
10890
10891 case 0xD7: // fixext 8
10892 {
10893 std::int8_t subtype{};
10894 return get_number(input_format_t::msgpack, subtype) &&
10895 get_binary(input_format_t::msgpack, 8, result) &&
10896 assign_and_return_true(subtype);
10897 }
10898
10899 case 0xD8: // fixext 16
10900 {
10901 std::int8_t subtype{};
10902 return get_number(input_format_t::msgpack, subtype) &&
10903 get_binary(input_format_t::msgpack, 16, result) &&
10904 assign_and_return_true(subtype);
10905 }
10906
10907 default: // LCOV_EXCL_LINE
10908 return false; // LCOV_EXCL_LINE
10909 }
10910 }
10911
10916 bool get_msgpack_array(const std::size_t len)
10917 {
10918 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10919 {
10920 return false;
10921 }
10922
10923 for (std::size_t i = 0; i < len; ++i)
10924 {
10925 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10926 {
10927 return false;
10928 }
10929 }
10930
10931 return sax->end_array();
10932 }
10933
10938 bool get_msgpack_object(const std::size_t len)
10939 {
10940 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10941 {
10942 return false;
10943 }
10944
10945 string_t key;
10946 for (std::size_t i = 0; i < len; ++i)
10947 {
10948 get();
10949 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
10950 {
10951 return false;
10952 }
10953
10954 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10955 {
10956 return false;
10957 }
10958 key.clear();
10959 }
10960
10961 return sax->end_object();
10962 }
10963
10965 // UBJSON //
10967
10975 bool parse_ubjson_internal(const bool get_char = true)
10976 {
10977 return get_ubjson_value(get_char ? get_ignore_noop() : current);
10978 }
10979
10994 bool get_ubjson_string(string_t& result, const bool get_char = true)
10995 {
10996 if (get_char)
10997 {
10998 get(); // TODO(niels): may we ignore N here?
10999 }
11000
11001 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11002 {
11003 return false;
11004 }
11005
11006 switch (current)
11007 {
11008 case 'U':
11009 {
11010 std::uint8_t len{};
11011 return get_number(input_format, len) && get_string(input_format, len, result);
11012 }
11013
11014 case 'i':
11015 {
11016 std::int8_t len{};
11017 return get_number(input_format, len) && get_string(input_format, len, result);
11018 }
11019
11020 case 'I':
11021 {
11022 std::int16_t len{};
11023 return get_number(input_format, len) && get_string(input_format, len, result);
11024 }
11025
11026 case 'l':
11027 {
11028 std::int32_t len{};
11029 return get_number(input_format, len) && get_string(input_format, len, result);
11030 }
11031
11032 case 'L':
11033 {
11034 std::int64_t len{};
11035 return get_number(input_format, len) && get_string(input_format, len, result);
11036 }
11037
11038 case 'u':
11039 {
11040 if (input_format != input_format_t::bjdata)
11041 {
11042 break;
11043 }
11044 std::uint16_t len{};
11045 return get_number(input_format, len) && get_string(input_format, len, result);
11046 }
11047
11048 case 'm':
11049 {
11050 if (input_format != input_format_t::bjdata)
11051 {
11052 break;
11053 }
11054 std::uint32_t len{};
11055 return get_number(input_format, len) && get_string(input_format, len, result);
11056 }
11057
11058 case 'M':
11059 {
11060 if (input_format != input_format_t::bjdata)
11061 {
11062 break;
11063 }
11064 std::uint64_t len{};
11065 return get_number(input_format, len) && get_string(input_format, len, result);
11066 }
11067
11068 default:
11069 break;
11070 }
11071 auto last_token = get_token_string();
11072 std::string message;
11073
11074 if (input_format != input_format_t::bjdata)
11075 {
11076 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11077 }
11078 else
11079 {
11080 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11081 }
11082 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11083 }
11084
11089 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11090 {
11091 std::pair<std::size_t, char_int_type> size_and_type;
11092 size_t dimlen = 0;
11093 bool no_ndarray = true;
11094
11095 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11096 {
11097 return false;
11098 }
11099
11100 if (size_and_type.first != npos)
11101 {
11102 if (size_and_type.second != 0)
11103 {
11104 if (size_and_type.second != 'N')
11105 {
11106 for (std::size_t i = 0; i < size_and_type.first; ++i)
11107 {
11108 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11109 {
11110 return false;
11111 }
11112 dim.push_back(dimlen);
11113 }
11114 }
11115 }
11116 else
11117 {
11118 for (std::size_t i = 0; i < size_and_type.first; ++i)
11119 {
11120 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11121 {
11122 return false;
11123 }
11124 dim.push_back(dimlen);
11125 }
11126 }
11127 }
11128 else
11129 {
11130 while (current != ']')
11131 {
11132 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11133 {
11134 return false;
11135 }
11136 dim.push_back(dimlen);
11137 get_ignore_noop();
11138 }
11139 }
11140 return true;
11141 }
11142
11154 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11155 {
11156 if (prefix == 0)
11157 {
11158 prefix = get_ignore_noop();
11159 }
11160
11161 switch (prefix)
11162 {
11163 case 'U':
11164 {
11165 std::uint8_t number{};
11166 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11167 {
11168 return false;
11169 }
11170 result = static_cast<std::size_t>(number);
11171 return true;
11172 }
11173
11174 case 'i':
11175 {
11176 std::int8_t number{};
11177 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11178 {
11179 return false;
11180 }
11181 if (number < 0)
11182 {
11183 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11184 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11185 }
11186 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11187 return true;
11188 }
11189
11190 case 'I':
11191 {
11192 std::int16_t number{};
11193 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11194 {
11195 return false;
11196 }
11197 if (number < 0)
11198 {
11199 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11200 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11201 }
11202 result = static_cast<std::size_t>(number);
11203 return true;
11204 }
11205
11206 case 'l':
11207 {
11208 std::int32_t number{};
11209 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11210 {
11211 return false;
11212 }
11213 if (number < 0)
11214 {
11215 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11216 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11217 }
11218 result = static_cast<std::size_t>(number);
11219 return true;
11220 }
11221
11222 case 'L':
11223 {
11224 std::int64_t number{};
11225 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11226 {
11227 return false;
11228 }
11229 if (number < 0)
11230 {
11231 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11232 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11233 }
11234 if (!value_in_range_of<std::size_t>(number))
11235 {
11236 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11237 exception_message(input_format, "integer value overflow", "size"), nullptr));
11238 }
11239 result = static_cast<std::size_t>(number);
11240 return true;
11241 }
11242
11243 case 'u':
11244 {
11245 if (input_format != input_format_t::bjdata)
11246 {
11247 break;
11248 }
11249 std::uint16_t number{};
11250 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11251 {
11252 return false;
11253 }
11254 result = static_cast<std::size_t>(number);
11255 return true;
11256 }
11257
11258 case 'm':
11259 {
11260 if (input_format != input_format_t::bjdata)
11261 {
11262 break;
11263 }
11264 std::uint32_t number{};
11265 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11266 {
11267 return false;
11268 }
11269 result = conditional_static_cast<std::size_t>(number);
11270 return true;
11271 }
11272
11273 case 'M':
11274 {
11275 if (input_format != input_format_t::bjdata)
11276 {
11277 break;
11278 }
11279 std::uint64_t number{};
11280 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11281 {
11282 return false;
11283 }
11284 if (!value_in_range_of<std::size_t>(number))
11285 {
11286 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11287 exception_message(input_format, "integer value overflow", "size"), nullptr));
11288 }
11289 result = detail::conditional_static_cast<std::size_t>(number);
11290 return true;
11291 }
11292
11293 case '[':
11294 {
11295 if (input_format != input_format_t::bjdata)
11296 {
11297 break;
11298 }
11299 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11300 {
11301 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));
11302 }
11303 std::vector<size_t> dim;
11304 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11305 {
11306 return false;
11307 }
11308 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11309 {
11310 result = dim.at(dim.size() - 1);
11311 return true;
11312 }
11313 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11314 {
11315 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11316 {
11317 if ( i == 0 )
11318 {
11319 result = 0;
11320 return true;
11321 }
11322 }
11323
11324 string_t key = "_ArraySize_";
11325 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11326 {
11327 return false;
11328 }
11329 result = 1;
11330 for (auto i : dim)
11331 {
11332 result *= i;
11333 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()
11334 {
11335 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));
11336 }
11337 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11338 {
11339 return false;
11340 }
11341 }
11342 is_ndarray = true;
11343 return sax->end_array();
11344 }
11345 result = 0;
11346 return true;
11347 }
11348
11349 default:
11350 break;
11351 }
11352 auto last_token = get_token_string();
11353 std::string message;
11354
11355 if (input_format != input_format_t::bjdata)
11356 {
11357 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11358 }
11359 else
11360 {
11361 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11362 }
11363 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
11364 }
11365
11377 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
11378 {
11379 result.first = npos; // size
11380 result.second = 0; // type
11381 bool is_ndarray = false;
11382
11383 get_ignore_noop();
11384
11385 if (current == '$')
11386 {
11387 result.second = get(); // must not ignore 'N', because 'N' maybe the type
11388 if (input_format == input_format_t::bjdata
11389 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
11390 {
11391 auto last_token = get_token_string();
11392 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11393 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
11394 }
11395
11396 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
11397 {
11398 return false;
11399 }
11400
11401 get_ignore_noop();
11402 if (JSON_HEDLEY_UNLIKELY(current != '#'))
11403 {
11404 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11405 {
11406 return false;
11407 }
11408 auto last_token = get_token_string();
11409 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11410 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
11411 }
11412
11413 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11414 if (input_format == input_format_t::bjdata && is_ndarray)
11415 {
11416 if (inside_ndarray)
11417 {
11418 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11419 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
11420 }
11421 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
11422 }
11423 return is_error;
11424 }
11425
11426 if (current == '#')
11427 {
11428 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11429 if (input_format == input_format_t::bjdata && is_ndarray)
11430 {
11431 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11432 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
11433 }
11434 return is_error;
11435 }
11436
11437 return true;
11438 }
11439
11444 bool get_ubjson_value(const char_int_type prefix)
11445 {
11446 switch (prefix)
11447 {
11448 case char_traits<char_type>::eof(): // EOF
11449 return unexpect_eof(input_format, "value");
11450
11451 case 'T': // true
11452 return sax->boolean(true);
11453 case 'F': // false
11454 return sax->boolean(false);
11455
11456 case 'Z': // null
11457 return sax->null();
11458
11459 case 'U':
11460 {
11461 std::uint8_t number{};
11462 return get_number(input_format, number) && sax->number_unsigned(number);
11463 }
11464
11465 case 'i':
11466 {
11467 std::int8_t number{};
11468 return get_number(input_format, number) && sax->number_integer(number);
11469 }
11470
11471 case 'I':
11472 {
11473 std::int16_t number{};
11474 return get_number(input_format, number) && sax->number_integer(number);
11475 }
11476
11477 case 'l':
11478 {
11479 std::int32_t number{};
11480 return get_number(input_format, number) && sax->number_integer(number);
11481 }
11482
11483 case 'L':
11484 {
11485 std::int64_t number{};
11486 return get_number(input_format, number) && sax->number_integer(number);
11487 }
11488
11489 case 'u':
11490 {
11491 if (input_format != input_format_t::bjdata)
11492 {
11493 break;
11494 }
11495 std::uint16_t number{};
11496 return get_number(input_format, number) && sax->number_unsigned(number);
11497 }
11498
11499 case 'm':
11500 {
11501 if (input_format != input_format_t::bjdata)
11502 {
11503 break;
11504 }
11505 std::uint32_t number{};
11506 return get_number(input_format, number) && sax->number_unsigned(number);
11507 }
11508
11509 case 'M':
11510 {
11511 if (input_format != input_format_t::bjdata)
11512 {
11513 break;
11514 }
11515 std::uint64_t number{};
11516 return get_number(input_format, number) && sax->number_unsigned(number);
11517 }
11518
11519 case 'h':
11520 {
11521 if (input_format != input_format_t::bjdata)
11522 {
11523 break;
11524 }
11525 const auto byte1_raw = get();
11526 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11527 {
11528 return false;
11529 }
11530 const auto byte2_raw = get();
11531 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11532 {
11533 return false;
11534 }
11535
11536 const auto byte1 = static_cast<unsigned char>(byte1_raw);
11537 const auto byte2 = static_cast<unsigned char>(byte2_raw);
11538
11539 // code from RFC 7049, Appendix D, Figure 3:
11540 // As half-precision floating-point numbers were only added
11541 // to IEEE 754 in 2008, today's programming platforms often
11542 // still only have limited support for them. It is very
11543 // easy to include at least decoding support for them even
11544 // without such support. An example of a small decoder for
11545 // half-precision floating-point numbers in the C language
11546 // is shown in Fig. 3.
11547 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11548 const double val = [&half]
11549 {
11550 const int exp = (half >> 10u) & 0x1Fu;
11551 const unsigned int mant = half & 0x3FFu;
11552 JSON_ASSERT(0 <= exp&& exp <= 32);
11553 JSON_ASSERT(mant <= 1024);
11554 switch (exp)
11555 {
11556 case 0:
11557 return std::ldexp(mant, -24);
11558 case 31:
11559 return (mant == 0)
11560 ? std::numeric_limits<double>::infinity()
11561 : std::numeric_limits<double>::quiet_NaN();
11562 default:
11563 return std::ldexp(mant + 1024, exp - 25);
11564 }
11565 }();
11566 return sax->number_float((half & 0x8000u) != 0
11567 ? static_cast<number_float_t>(-val)
11568 : static_cast<number_float_t>(val), "");
11569 }
11570
11571 case 'd':
11572 {
11573 float number{};
11574 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11575 }
11576
11577 case 'D':
11578 {
11579 double number{};
11580 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11581 }
11582
11583 case 'H':
11584 {
11585 return get_ubjson_high_precision_number();
11586 }
11587
11588 case 'C': // char
11589 {
11590 get();
11591 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
11592 {
11593 return false;
11594 }
11595 if (JSON_HEDLEY_UNLIKELY(current > 127))
11596 {
11597 auto last_token = get_token_string();
11598 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11599 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
11600 }
11601 string_t s(1, static_cast<typename string_t::value_type>(current));
11602 return sax->string(s);
11603 }
11604
11605 case 'S': // string
11606 {
11607 string_t s;
11608 return get_ubjson_string(s) && sax->string(s);
11609 }
11610
11611 case '[': // array
11612 return get_ubjson_array();
11613
11614 case '{': // object
11615 return get_ubjson_object();
11616
11617 default: // anything else
11618 break;
11619 }
11620 auto last_token = get_token_string();
11621 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));
11622 }
11623
11627 bool get_ubjson_array()
11628 {
11629 std::pair<std::size_t, char_int_type> size_and_type;
11630 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11631 {
11632 return false;
11633 }
11634
11635 // 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):
11636 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
11637
11638 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11639 {
11640 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
11641 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)
11642 {
11643 return p.first < t;
11644 });
11645 string_t key = "_ArrayType_";
11646 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
11647 {
11648 auto last_token = get_token_string();
11649 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11650 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
11651 }
11652
11653 string_t type = it->second; // sax->string() takes a reference
11654 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
11655 {
11656 return false;
11657 }
11658
11659 if (size_and_type.second == 'C')
11660 {
11661 size_and_type.second = 'U';
11662 }
11663
11664 key = "_ArrayData_";
11665 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
11666 {
11667 return false;
11668 }
11669
11670 for (std::size_t i = 0; i < size_and_type.first; ++i)
11671 {
11672 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11673 {
11674 return false;
11675 }
11676 }
11677
11678 return (sax->end_array() && sax->end_object());
11679 }
11680
11681 if (size_and_type.first != npos)
11682 {
11683 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
11684 {
11685 return false;
11686 }
11687
11688 if (size_and_type.second != 0)
11689 {
11690 if (size_and_type.second != 'N')
11691 {
11692 for (std::size_t i = 0; i < size_and_type.first; ++i)
11693 {
11694 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11695 {
11696 return false;
11697 }
11698 }
11699 }
11700 }
11701 else
11702 {
11703 for (std::size_t i = 0; i < size_and_type.first; ++i)
11704 {
11705 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11706 {
11707 return false;
11708 }
11709 }
11710 }
11711 }
11712 else
11713 {
11714 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
11715 {
11716 return false;
11717 }
11718
11719 while (current != ']')
11720 {
11721 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
11722 {
11723 return false;
11724 }
11725 get_ignore_noop();
11726 }
11727 }
11728
11729 return sax->end_array();
11730 }
11731
11735 bool get_ubjson_object()
11736 {
11737 std::pair<std::size_t, char_int_type> size_and_type;
11738 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11739 {
11740 return false;
11741 }
11742
11743 // do not accept ND-array size in objects in BJData
11744 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11745 {
11746 auto last_token = get_token_string();
11747 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11748 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
11749 }
11750
11751 string_t key;
11752 if (size_and_type.first != npos)
11753 {
11754 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
11755 {
11756 return false;
11757 }
11758
11759 if (size_and_type.second != 0)
11760 {
11761 for (std::size_t i = 0; i < size_and_type.first; ++i)
11762 {
11763 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11764 {
11765 return false;
11766 }
11767 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11768 {
11769 return false;
11770 }
11771 key.clear();
11772 }
11773 }
11774 else
11775 {
11776 for (std::size_t i = 0; i < size_and_type.first; ++i)
11777 {
11778 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11779 {
11780 return false;
11781 }
11782 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11783 {
11784 return false;
11785 }
11786 key.clear();
11787 }
11788 }
11789 }
11790 else
11791 {
11792 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
11793 {
11794 return false;
11795 }
11796
11797 while (current != '}')
11798 {
11799 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
11800 {
11801 return false;
11802 }
11803 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11804 {
11805 return false;
11806 }
11807 get_ignore_noop();
11808 key.clear();
11809 }
11810 }
11811
11812 return sax->end_object();
11813 }
11814
11815 // Note, no reader for UBJSON binary types is implemented because they do
11816 // not exist
11817
11818 bool get_ubjson_high_precision_number()
11819 {
11820 // get size of following number string
11821 std::size_t size{};
11822 bool no_ndarray = true;
11823 auto res = get_ubjson_size_value(size, no_ndarray);
11824 if (JSON_HEDLEY_UNLIKELY(!res))
11825 {
11826 return res;
11827 }
11828
11829 // get number string
11830 std::vector<char> number_vector;
11831 for (std::size_t i = 0; i < size; ++i)
11832 {
11833 get();
11834 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11835 {
11836 return false;
11837 }
11838 number_vector.push_back(static_cast<char>(current));
11839 }
11840
11841 // parse number string
11842 using ia_type = decltype(detail::input_adapter(number_vector));
11843 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11844 const auto result_number = number_lexer.scan();
11845 const auto number_string = number_lexer.get_token_string();
11846 const auto result_remainder = number_lexer.scan();
11847
11848 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
11849
11850 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
11851 {
11852 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11853 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11854 }
11855
11856 switch (result_number)
11857 {
11858 case token_type::value_integer:
11859 return sax->number_integer(number_lexer.get_number_integer());
11860 case token_type::value_unsigned:
11861 return sax->number_unsigned(number_lexer.get_number_unsigned());
11862 case token_type::value_float:
11863 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11864 case token_type::uninitialized:
11865 case token_type::literal_true:
11866 case token_type::literal_false:
11867 case token_type::literal_null:
11868 case token_type::value_string:
11869 case token_type::begin_array:
11870 case token_type::begin_object:
11871 case token_type::end_array:
11872 case token_type::end_object:
11873 case token_type::name_separator:
11874 case token_type::value_separator:
11875 case token_type::parse_error:
11876 case token_type::end_of_input:
11877 case token_type::literal_or_value:
11878 default:
11879 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11880 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11881 }
11882 }
11883
11885 // Utility functions //
11887
11897 char_int_type get()
11898 {
11899 ++chars_read;
11900 return current = ia.get_character();
11901 }
11902
11906 char_int_type get_ignore_noop()
11907 {
11908 do
11909 {
11910 get();
11911 }
11912 while (current == 'N');
11913
11914 return current;
11915 }
11916
11917 /*
11918 @brief read a number from the input
11919
11920 @tparam NumberType the type of the number
11921 @param[in] format the current format (for diagnostics)
11922 @param[out] result number of type @a NumberType
11923
11924 @return whether conversion completed
11925
11926 @note This function needs to respect the system's endianness, because
11927 bytes in CBOR, MessagePack, and UBJSON are stored in network order
11928 (big endian) and therefore need reordering on little endian systems.
11929 On the other hand, BSON and BJData use little endian and should reorder
11930 on big endian systems.
11931 */
11932 template<typename NumberType, bool InputIsLittleEndian = false>
11933 bool get_number(const input_format_t format, NumberType& result)
11934 {
11935 // step 1: read input into array with system's byte order
11936 std::array<std::uint8_t, sizeof(NumberType)> vec{};
11937 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
11938 {
11939 get();
11940 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
11941 {
11942 return false;
11943 }
11944
11945 // reverse byte order prior to conversion if necessary
11946 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
11947 {
11948 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
11949 }
11950 else
11951 {
11952 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
11953 }
11954 }
11955
11956 // step 2: convert array into number of type T and return
11957 std::memcpy(&result, vec.data(), sizeof(NumberType));
11958 return true;
11959 }
11960
11975 template<typename NumberType>
11976 bool get_string(const input_format_t format,
11977 const NumberType len,
11978 string_t& result)
11979 {
11980 bool success = true;
11981 for (NumberType i = 0; i < len; i++)
11982 {
11983 get();
11984 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
11985 {
11986 success = false;
11987 break;
11988 }
11989 result.push_back(static_cast<typename string_t::value_type>(current));
11990 }
11991 return success;
11992 }
11993
12008 template<typename NumberType>
12009 bool get_binary(const input_format_t format,
12010 const NumberType len,
12011 binary_t& result)
12012 {
12013 bool success = true;
12014 for (NumberType i = 0; i < len; i++)
12015 {
12016 get();
12017 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12018 {
12019 success = false;
12020 break;
12021 }
12022 result.push_back(static_cast<std::uint8_t>(current));
12023 }
12024 return success;
12025 }
12026
12032 JSON_HEDLEY_NON_NULL(3)
12033 bool unexpect_eof(const input_format_t format, const char* context) const
12034 {
12035 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12036 {
12037 return sax->parse_error(chars_read, "<end of file>",
12038 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12039 }
12040 return true;
12041 }
12042
12046 std::string get_token_string() const
12047 {
12048 std::array<char, 3> cr{{}};
12049 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12050 return std::string{cr.data()};
12051 }
12052
12059 std::string exception_message(const input_format_t format,
12060 const std::string& detail,
12061 const std::string& context) const
12062 {
12063 std::string error_msg = "syntax error while parsing ";
12064
12065 switch (format)
12066 {
12067 case input_format_t::cbor:
12068 error_msg += "CBOR";
12069 break;
12070
12071 case input_format_t::msgpack:
12072 error_msg += "MessagePack";
12073 break;
12074
12075 case input_format_t::ubjson:
12076 error_msg += "UBJSON";
12077 break;
12078
12079 case input_format_t::bson:
12080 error_msg += "BSON";
12081 break;
12082
12083 case input_format_t::bjdata:
12084 error_msg += "BJData";
12085 break;
12086
12087 case input_format_t::json: // LCOV_EXCL_LINE
12088 default: // LCOV_EXCL_LINE
12089 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12090 }
12091
12092 return concat(error_msg, ' ', context, ": ", detail);
12093 }
12094
12095 private:
12096 static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
12097
12099 InputAdapterType ia;
12100
12102 char_int_type current = char_traits<char_type>::eof();
12103
12105 std::size_t chars_read = 0;
12106
12108 const bool is_little_endian = little_endianness();
12109
12111 const input_format_t input_format = input_format_t::json;
12112
12114 json_sax_t* sax = nullptr;
12115
12116 // excluded markers in bjdata optimized type
12117#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12118 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12119
12120#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12121 make_array<bjd_type>( \
12122 bjd_type{'C', "char"}, \
12123 bjd_type{'D', "double"}, \
12124 bjd_type{'I', "int16"}, \
12125 bjd_type{'L', "int64"}, \
12126 bjd_type{'M', "uint64"}, \
12127 bjd_type{'U', "uint8"}, \
12128 bjd_type{'d', "single"}, \
12129 bjd_type{'i', "int8"}, \
12130 bjd_type{'l', "int32"}, \
12131 bjd_type{'m', "uint32"}, \
12132 bjd_type{'u', "uint16"})
12133
12134 JSON_PRIVATE_UNLESS_TESTED:
12135 // lookup tables
12136 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12137 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12138 JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
12139
12140 using bjd_type = std::pair<char_int_type, string_t>;
12141 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12142 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12143 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
12144
12145#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12146#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12147};
12148
12149#ifndef JSON_HAS_CPP_17
12150 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12151 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12152#endif
12153
12154} // namespace detail
12155NLOHMANN_JSON_NAMESPACE_END
12156
12157// #include <nlohmann/detail/input/input_adapters.hpp>
12158
12159// #include <nlohmann/detail/input/lexer.hpp>
12160
12161// #include <nlohmann/detail/input/parser.hpp>
12162// __ _____ _____ _____
12163// __| | __| | | | JSON for Modern C++
12164// | | |__ | | | | | | version 3.11.3
12165// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12166//
12167// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12168// SPDX-License-Identifier: MIT
12169
12170
12171
12172#include <cmath> // isfinite
12173#include <cstdint> // uint8_t
12174#include <functional> // function
12175#include <string> // string
12176#include <utility> // move
12177#include <vector> // vector
12178
12179// #include <nlohmann/detail/exceptions.hpp>
12180
12181// #include <nlohmann/detail/input/input_adapters.hpp>
12182
12183// #include <nlohmann/detail/input/json_sax.hpp>
12184
12185// #include <nlohmann/detail/input/lexer.hpp>
12186
12187// #include <nlohmann/detail/macro_scope.hpp>
12188
12189// #include <nlohmann/detail/meta/is_sax.hpp>
12190
12191// #include <nlohmann/detail/string_concat.hpp>
12192
12193// #include <nlohmann/detail/value_t.hpp>
12194
12195
12196NLOHMANN_JSON_NAMESPACE_BEGIN
12197namespace detail
12198{
12200// parser //
12202
12203enum class parse_event_t : std::uint8_t
12204{
12208 object_end,
12212 array_end,
12214 key,
12216 value
12217};
12218
12219template<typename BasicJsonType>
12220using parser_callback_t =
12221 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12222
12228template<typename BasicJsonType, typename InputAdapterType>
12229class parser
12230{
12231 using number_integer_t = typename BasicJsonType::number_integer_t;
12232 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12233 using number_float_t = typename BasicJsonType::number_float_t;
12234 using string_t = typename BasicJsonType::string_t;
12235 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
12236 using token_type = typename lexer_t::token_type;
12237
12238 public:
12240 explicit parser(InputAdapterType&& adapter,
12241 const parser_callback_t<BasicJsonType> cb = nullptr,
12242 const bool allow_exceptions_ = true,
12243 const bool skip_comments = false)
12244 : callback(cb)
12245 , m_lexer(std::move(adapter), skip_comments)
12246 , allow_exceptions(allow_exceptions_)
12247 {
12248 // read first token
12249 get_token();
12250 }
12251
12262 void parse(const bool strict, BasicJsonType& result)
12263 {
12264 if (callback)
12265 {
12266 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
12267 sax_parse_internal(&sdp);
12268
12269 // in strict mode, input must be completely read
12270 if (strict && (get_token() != token_type::end_of_input))
12271 {
12272 sdp.parse_error(m_lexer.get_position(),
12273 m_lexer.get_token_string(),
12274 parse_error::create(101, m_lexer.get_position(),
12275 exception_message(token_type::end_of_input, "value"), nullptr));
12276 }
12277
12278 // in case of an error, return discarded value
12279 if (sdp.is_errored())
12280 {
12281 result = value_t::discarded;
12282 return;
12283 }
12284
12285 // set top-level value to null if it was discarded by the callback
12286 // function
12287 if (result.is_discarded())
12288 {
12289 result = nullptr;
12290 }
12291 }
12292 else
12293 {
12294 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
12295 sax_parse_internal(&sdp);
12296
12297 // in strict mode, input must be completely read
12298 if (strict && (get_token() != token_type::end_of_input))
12299 {
12300 sdp.parse_error(m_lexer.get_position(),
12301 m_lexer.get_token_string(),
12302 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12303 }
12304
12305 // in case of an error, return discarded value
12306 if (sdp.is_errored())
12307 {
12308 result = value_t::discarded;
12309 return;
12310 }
12311 }
12312
12313 result.assert_invariant();
12314 }
12315
12322 bool accept(const bool strict = true)
12323 {
12325 return sax_parse(&sax_acceptor, strict);
12326 }
12327
12328 template<typename SAX>
12329 JSON_HEDLEY_NON_NULL(2)
12330 bool sax_parse(SAX* sax, const bool strict = true)
12331 {
12333 const bool result = sax_parse_internal(sax);
12334
12335 // strict mode: next byte must be EOF
12336 if (result && strict && (get_token() != token_type::end_of_input))
12337 {
12338 return sax->parse_error(m_lexer.get_position(),
12339 m_lexer.get_token_string(),
12340 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12341 }
12342
12343 return result;
12344 }
12345
12346 private:
12347 template<typename SAX>
12348 JSON_HEDLEY_NON_NULL(2)
12349 bool sax_parse_internal(SAX* sax)
12350 {
12351 // stack to remember the hierarchy of structured values we are parsing
12352 // true = array; false = object
12353 std::vector<bool> states;
12354 // value to avoid a goto (see comment where set to true)
12355 bool skip_to_state_evaluation = false;
12356
12357 while (true)
12358 {
12359 if (!skip_to_state_evaluation)
12360 {
12361 // invariant: get_token() was called before each iteration
12362 switch (last_token)
12363 {
12364 case token_type::begin_object:
12365 {
12366 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
12367 {
12368 return false;
12369 }
12370
12371 // closing } -> we are done
12372 if (get_token() == token_type::end_object)
12373 {
12374 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12375 {
12376 return false;
12377 }
12378 break;
12379 }
12380
12381 // parse key
12382 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
12383 {
12384 return sax->parse_error(m_lexer.get_position(),
12385 m_lexer.get_token_string(),
12386 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12387 }
12388 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12389 {
12390 return false;
12391 }
12392
12393 // parse separator (:)
12394 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12395 {
12396 return sax->parse_error(m_lexer.get_position(),
12397 m_lexer.get_token_string(),
12398 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12399 }
12400
12401 // remember we are now inside an object
12402 states.push_back(false);
12403
12404 // parse values
12405 get_token();
12406 continue;
12407 }
12408
12409 case token_type::begin_array:
12410 {
12411 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
12412 {
12413 return false;
12414 }
12415
12416 // closing ] -> we are done
12417 if (get_token() == token_type::end_array)
12418 {
12419 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12420 {
12421 return false;
12422 }
12423 break;
12424 }
12425
12426 // remember we are now inside an array
12427 states.push_back(true);
12428
12429 // parse values (no need to call get_token)
12430 continue;
12431 }
12432
12433 case token_type::value_float:
12434 {
12435 const auto res = m_lexer.get_number_float();
12436
12437 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
12438 {
12439 return sax->parse_error(m_lexer.get_position(),
12440 m_lexer.get_token_string(),
12441 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
12442 }
12443
12444 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
12445 {
12446 return false;
12447 }
12448
12449 break;
12450 }
12451
12452 case token_type::literal_false:
12453 {
12454 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
12455 {
12456 return false;
12457 }
12458 break;
12459 }
12460
12461 case token_type::literal_null:
12462 {
12463 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
12464 {
12465 return false;
12466 }
12467 break;
12468 }
12469
12470 case token_type::literal_true:
12471 {
12472 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
12473 {
12474 return false;
12475 }
12476 break;
12477 }
12478
12479 case token_type::value_integer:
12480 {
12481 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
12482 {
12483 return false;
12484 }
12485 break;
12486 }
12487
12488 case token_type::value_string:
12489 {
12490 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
12491 {
12492 return false;
12493 }
12494 break;
12495 }
12496
12497 case token_type::value_unsigned:
12498 {
12499 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
12500 {
12501 return false;
12502 }
12503 break;
12504 }
12505
12506 case token_type::parse_error:
12507 {
12508 // using "uninitialized" to avoid "expected" message
12509 return sax->parse_error(m_lexer.get_position(),
12510 m_lexer.get_token_string(),
12511 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
12512 }
12513 case token_type::end_of_input:
12514 {
12515 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
12516 {
12517 return sax->parse_error(m_lexer.get_position(),
12518 m_lexer.get_token_string(),
12519 parse_error::create(101, m_lexer.get_position(),
12520 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
12521 }
12522
12523 return sax->parse_error(m_lexer.get_position(),
12524 m_lexer.get_token_string(),
12525 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12526 }
12527 case token_type::uninitialized:
12528 case token_type::end_array:
12529 case token_type::end_object:
12530 case token_type::name_separator:
12531 case token_type::value_separator:
12532 case token_type::literal_or_value:
12533 default: // the last token was unexpected
12534 {
12535 return sax->parse_error(m_lexer.get_position(),
12536 m_lexer.get_token_string(),
12537 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12538 }
12539 }
12540 }
12541 else
12542 {
12543 skip_to_state_evaluation = false;
12544 }
12545
12546 // we reached this line after we successfully parsed a value
12547 if (states.empty())
12548 {
12549 // empty stack: we reached the end of the hierarchy: done
12550 return true;
12551 }
12552
12553 if (states.back()) // array
12554 {
12555 // comma -> next value
12556 if (get_token() == token_type::value_separator)
12557 {
12558 // parse a new value
12559 get_token();
12560 continue;
12561 }
12562
12563 // closing ]
12564 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
12565 {
12566 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12567 {
12568 return false;
12569 }
12570
12571 // We are done with this array. Before we can parse a
12572 // new value, we need to evaluate the new state first.
12573 // By setting skip_to_state_evaluation to false, we
12574 // are effectively jumping to the beginning of this if.
12575 JSON_ASSERT(!states.empty());
12576 states.pop_back();
12577 skip_to_state_evaluation = true;
12578 continue;
12579 }
12580
12581 return sax->parse_error(m_lexer.get_position(),
12582 m_lexer.get_token_string(),
12583 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
12584 }
12585
12586 // states.back() is false -> object
12587
12588 // comma -> next value
12589 if (get_token() == token_type::value_separator)
12590 {
12591 // parse key
12592 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
12593 {
12594 return sax->parse_error(m_lexer.get_position(),
12595 m_lexer.get_token_string(),
12596 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12597 }
12598
12599 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12600 {
12601 return false;
12602 }
12603
12604 // parse separator (:)
12605 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12606 {
12607 return sax->parse_error(m_lexer.get_position(),
12608 m_lexer.get_token_string(),
12609 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12610 }
12611
12612 // parse values
12613 get_token();
12614 continue;
12615 }
12616
12617 // closing }
12618 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
12619 {
12620 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12621 {
12622 return false;
12623 }
12624
12625 // We are done with this object. Before we can parse a
12626 // new value, we need to evaluate the new state first.
12627 // By setting skip_to_state_evaluation to false, we
12628 // are effectively jumping to the beginning of this if.
12629 JSON_ASSERT(!states.empty());
12630 states.pop_back();
12631 skip_to_state_evaluation = true;
12632 continue;
12633 }
12634
12635 return sax->parse_error(m_lexer.get_position(),
12636 m_lexer.get_token_string(),
12637 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
12638 }
12639 }
12640
12642 token_type get_token()
12643 {
12644 return last_token = m_lexer.scan();
12645 }
12646
12647 std::string exception_message(const token_type expected, const std::string& context)
12648 {
12649 std::string error_msg = "syntax error ";
12650
12651 if (!context.empty())
12652 {
12653 error_msg += concat("while parsing ", context, ' ');
12654 }
12655
12656 error_msg += "- ";
12657
12658 if (last_token == token_type::parse_error)
12659 {
12660 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12661 m_lexer.get_token_string(), '\'');
12662 }
12663 else
12664 {
12665 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12666 }
12667
12668 if (expected != token_type::uninitialized)
12669 {
12670 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12671 }
12672
12673 return error_msg;
12674 }
12675
12676 private:
12678 const parser_callback_t<BasicJsonType> callback = nullptr;
12680 token_type last_token = token_type::uninitialized;
12682 lexer_t m_lexer;
12684 const bool allow_exceptions = true;
12685};
12686
12687} // namespace detail
12688NLOHMANN_JSON_NAMESPACE_END
12689
12690// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12691// __ _____ _____ _____
12692// __| | __| | | | JSON for Modern C++
12693// | | |__ | | | | | | version 3.11.3
12694// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12695//
12696// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12697// SPDX-License-Identifier: MIT
12698
12699
12700
12701// #include <nlohmann/detail/abi_macros.hpp>
12702
12703// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12704// __ _____ _____ _____
12705// __| | __| | | | JSON for Modern C++
12706// | | |__ | | | | | | version 3.11.3
12707// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12708//
12709// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12710// SPDX-License-Identifier: MIT
12711
12712
12713
12714#include <cstddef> // ptrdiff_t
12715#include <limits> // numeric_limits
12716
12717// #include <nlohmann/detail/macro_scope.hpp>
12718
12719
12720NLOHMANN_JSON_NAMESPACE_BEGIN
12721namespace detail
12722{
12723
12724/*
12725@brief an iterator for primitive JSON types
12726
12727This class models an iterator for primitive JSON types (boolean, number,
12728string). It's only purpose is to allow the iterator/const_iterator classes
12729to "iterate" over primitive values. Internally, the iterator is modeled by
12730a `difference_type` variable. Value begin_value (`0`) models the begin,
12731end_value (`1`) models past the end.
12732*/
12733class primitive_iterator_t
12734{
12735 private:
12736 using difference_type = std::ptrdiff_t;
12737 static constexpr difference_type begin_value = 0;
12738 static constexpr difference_type end_value = begin_value + 1;
12739
12740 JSON_PRIVATE_UNLESS_TESTED:
12742 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12743
12744 public:
12745 constexpr difference_type get_value() const noexcept
12746 {
12747 return m_it;
12748 }
12749
12751 void set_begin() noexcept
12752 {
12753 m_it = begin_value;
12754 }
12755
12757 void set_end() noexcept
12758 {
12759 m_it = end_value;
12760 }
12761
12763 constexpr bool is_begin() const noexcept
12764 {
12765 return m_it == begin_value;
12766 }
12767
12769 constexpr bool is_end() const noexcept
12770 {
12771 return m_it == end_value;
12772 }
12773
12774 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12775 {
12776 return lhs.m_it == rhs.m_it;
12777 }
12778
12779 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12780 {
12781 return lhs.m_it < rhs.m_it;
12782 }
12783
12784 primitive_iterator_t operator+(difference_type n) noexcept
12785 {
12786 auto result = *this;
12787 result += n;
12788 return result;
12789 }
12790
12791 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12792 {
12793 return lhs.m_it - rhs.m_it;
12794 }
12795
12796 primitive_iterator_t& operator++() noexcept
12797 {
12798 ++m_it;
12799 return *this;
12800 }
12801
12802 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
12803 {
12804 auto result = *this;
12805 ++m_it;
12806 return result;
12807 }
12808
12809 primitive_iterator_t& operator--() noexcept
12810 {
12811 --m_it;
12812 return *this;
12813 }
12814
12815 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
12816 {
12817 auto result = *this;
12818 --m_it;
12819 return result;
12820 }
12821
12822 primitive_iterator_t& operator+=(difference_type n) noexcept
12823 {
12824 m_it += n;
12825 return *this;
12826 }
12827
12828 primitive_iterator_t& operator-=(difference_type n) noexcept
12829 {
12830 m_it -= n;
12831 return *this;
12832 }
12833};
12834
12835} // namespace detail
12836NLOHMANN_JSON_NAMESPACE_END
12837
12838
12839NLOHMANN_JSON_NAMESPACE_BEGIN
12840namespace detail
12841{
12842
12849template<typename BasicJsonType> struct internal_iterator
12850{
12852 typename BasicJsonType::object_t::iterator object_iterator {};
12854 typename BasicJsonType::array_t::iterator array_iterator {};
12857};
12858
12859} // namespace detail
12860NLOHMANN_JSON_NAMESPACE_END
12861
12862// #include <nlohmann/detail/iterators/iter_impl.hpp>
12863// __ _____ _____ _____
12864// __| | __| | | | JSON for Modern C++
12865// | | |__ | | | | | | version 3.11.3
12866// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12867//
12868// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12869// SPDX-License-Identifier: MIT
12870
12871
12872
12873#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
12874#include <type_traits> // conditional, is_const, remove_const
12875
12876// #include <nlohmann/detail/exceptions.hpp>
12877
12878// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12879
12880// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12881
12882// #include <nlohmann/detail/macro_scope.hpp>
12883
12884// #include <nlohmann/detail/meta/cpp_future.hpp>
12885
12886// #include <nlohmann/detail/meta/type_traits.hpp>
12887
12888// #include <nlohmann/detail/value_t.hpp>
12889
12890
12891NLOHMANN_JSON_NAMESPACE_BEGIN
12892namespace detail
12893{
12894
12895// forward declare, to be able to friend it later on
12896template<typename IteratorType> class iteration_proxy;
12897template<typename IteratorType> class iteration_proxy_value;
12898
12915template<typename BasicJsonType>
12916class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
12917{
12919 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
12921 friend other_iter_impl;
12922 friend BasicJsonType;
12923 friend iteration_proxy<iter_impl>;
12924 friend iteration_proxy_value<iter_impl>;
12925
12926 using object_t = typename BasicJsonType::object_t;
12927 using array_t = typename BasicJsonType::array_t;
12928 // make sure BasicJsonType is basic_json or const basic_json
12929 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
12930 "iter_impl only accepts (const) basic_json");
12931 // superficial check for the LegacyBidirectionalIterator named requirement
12932 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
12933 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
12934 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
12935
12936 public:
12942 using iterator_category = std::bidirectional_iterator_tag;
12943
12945 using value_type = typename BasicJsonType::value_type;
12947 using difference_type = typename BasicJsonType::difference_type;
12949 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
12950 typename BasicJsonType::const_pointer,
12951 typename BasicJsonType::pointer>::type;
12954 typename std::conditional<std::is_const<BasicJsonType>::value,
12955 typename BasicJsonType::const_reference,
12956 typename BasicJsonType::reference>::type;
12957
12958 iter_impl() = default;
12959 ~iter_impl() = default;
12960 iter_impl(iter_impl&&) noexcept = default;
12961 iter_impl& operator=(iter_impl&&) noexcept = default;
12962
12969 explicit iter_impl(pointer object) noexcept : m_object(object)
12970 {
12971 JSON_ASSERT(m_object != nullptr);
12972
12973 switch (m_object->m_data.m_type)
12974 {
12975 case value_t::object:
12976 {
12977 m_it.object_iterator = typename object_t::iterator();
12978 break;
12979 }
12980
12981 case value_t::array:
12982 {
12983 m_it.array_iterator = typename array_t::iterator();
12984 break;
12985 }
12986
12987 case value_t::null:
12988 case value_t::string:
12989 case value_t::boolean:
12993 case value_t::binary:
12994 case value_t::discarded:
12995 default:
12996 {
12997 m_it.primitive_iterator = primitive_iterator_t();
12998 break;
12999 }
13000 }
13001 }
13002
13020 : m_object(other.m_object), m_it(other.m_it)
13021 {}
13022
13030 {
13031 if (&other != this)
13032 {
13033 m_object = other.m_object;
13034 m_it = other.m_it;
13035 }
13036 return *this;
13037 }
13038
13044 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13045 : m_object(other.m_object), m_it(other.m_it)
13046 {}
13047
13054 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13055 {
13056 m_object = other.m_object;
13057 m_it = other.m_it;
13058 return *this;
13059 }
13060
13061 JSON_PRIVATE_UNLESS_TESTED:
13066 void set_begin() noexcept
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 = m_object->m_data.m_value.object->begin();
13075 break;
13076 }
13077
13078 case value_t::array:
13079 {
13080 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13081 break;
13082 }
13083
13084 case value_t::null:
13085 {
13086 // set to end so begin()==end() is true: null is empty
13087 m_it.primitive_iterator.set_end();
13088 break;
13089 }
13090
13091 case value_t::string:
13092 case value_t::boolean:
13096 case value_t::binary:
13097 case value_t::discarded:
13098 default:
13099 {
13100 m_it.primitive_iterator.set_begin();
13101 break;
13102 }
13103 }
13104 }
13105
13110 void set_end() noexcept
13111 {
13112 JSON_ASSERT(m_object != nullptr);
13113
13114 switch (m_object->m_data.m_type)
13115 {
13116 case value_t::object:
13117 {
13118 m_it.object_iterator = m_object->m_data.m_value.object->end();
13119 break;
13120 }
13121
13122 case value_t::array:
13123 {
13124 m_it.array_iterator = m_object->m_data.m_value.array->end();
13125 break;
13126 }
13127
13128 case value_t::null:
13129 case value_t::string:
13130 case value_t::boolean:
13134 case value_t::binary:
13135 case value_t::discarded:
13136 default:
13137 {
13138 m_it.primitive_iterator.set_end();
13139 break;
13140 }
13141 }
13142 }
13143
13144 public:
13150 {
13151 JSON_ASSERT(m_object != nullptr);
13152
13153 switch (m_object->m_data.m_type)
13154 {
13155 case value_t::object:
13156 {
13157 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13158 return m_it.object_iterator->second;
13159 }
13160
13161 case value_t::array:
13162 {
13163 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13164 return *m_it.array_iterator;
13165 }
13166
13167 case value_t::null:
13168 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13169
13170 case value_t::string:
13171 case value_t::boolean:
13175 case value_t::binary:
13176 case value_t::discarded:
13177 default:
13178 {
13179 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13180 {
13181 return *m_object;
13182 }
13183
13184 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13185 }
13186 }
13187 }
13188
13194 {
13195 JSON_ASSERT(m_object != nullptr);
13196
13197 switch (m_object->m_data.m_type)
13198 {
13199 case value_t::object:
13200 {
13201 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13202 return &(m_it.object_iterator->second);
13203 }
13204
13205 case value_t::array:
13206 {
13207 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13208 return &*m_it.array_iterator;
13209 }
13210
13211 case value_t::null:
13212 case value_t::string:
13213 case value_t::boolean:
13217 case value_t::binary:
13218 case value_t::discarded:
13219 default:
13220 {
13221 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13222 {
13223 return m_object;
13224 }
13225
13226 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13227 }
13228 }
13229 }
13230
13235 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13236 {
13237 auto result = *this;
13238 ++(*this);
13239 return result;
13240 }
13241
13247 {
13248 JSON_ASSERT(m_object != nullptr);
13249
13250 switch (m_object->m_data.m_type)
13251 {
13252 case value_t::object:
13253 {
13254 std::advance(m_it.object_iterator, 1);
13255 break;
13256 }
13257
13258 case value_t::array:
13259 {
13260 std::advance(m_it.array_iterator, 1);
13261 break;
13262 }
13263
13264 case value_t::null:
13265 case value_t::string:
13266 case value_t::boolean:
13270 case value_t::binary:
13271 case value_t::discarded:
13272 default:
13273 {
13274 ++m_it.primitive_iterator;
13275 break;
13276 }
13277 }
13278
13279 return *this;
13280 }
13281
13286 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13287 {
13288 auto result = *this;
13289 --(*this);
13290 return result;
13291 }
13292
13298 {
13299 JSON_ASSERT(m_object != nullptr);
13300
13301 switch (m_object->m_data.m_type)
13302 {
13303 case value_t::object:
13304 {
13305 std::advance(m_it.object_iterator, -1);
13306 break;
13307 }
13308
13309 case value_t::array:
13310 {
13311 std::advance(m_it.array_iterator, -1);
13312 break;
13313 }
13314
13315 case value_t::null:
13316 case value_t::string:
13317 case value_t::boolean:
13321 case value_t::binary:
13322 case value_t::discarded:
13323 default:
13324 {
13325 --m_it.primitive_iterator;
13326 break;
13327 }
13328 }
13329
13330 return *this;
13331 }
13332
13337 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 >
13338 bool operator==(const IterImpl& other) const
13339 {
13340 // if objects are not the same, the comparison is undefined
13341 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13342 {
13343 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13344 }
13345
13346 JSON_ASSERT(m_object != nullptr);
13347
13348 switch (m_object->m_data.m_type)
13349 {
13350 case value_t::object:
13351 return (m_it.object_iterator == other.m_it.object_iterator);
13352
13353 case value_t::array:
13354 return (m_it.array_iterator == other.m_it.array_iterator);
13355
13356 case value_t::null:
13357 case value_t::string:
13358 case value_t::boolean:
13362 case value_t::binary:
13363 case value_t::discarded:
13364 default:
13365 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
13366 }
13367 }
13368
13373 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 >
13374 bool operator!=(const IterImpl& other) const
13375 {
13376 return !operator==(other);
13377 }
13378
13383 bool operator<(const iter_impl& other) const
13384 {
13385 // if objects are not the same, the comparison is undefined
13386 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13387 {
13388 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13389 }
13390
13391 JSON_ASSERT(m_object != nullptr);
13392
13393 switch (m_object->m_data.m_type)
13394 {
13395 case value_t::object:
13396 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
13397
13398 case value_t::array:
13399 return (m_it.array_iterator < other.m_it.array_iterator);
13400
13401 case value_t::null:
13402 case value_t::string:
13403 case value_t::boolean:
13407 case value_t::binary:
13408 case value_t::discarded:
13409 default:
13410 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
13411 }
13412 }
13413
13418 bool operator<=(const iter_impl& other) const
13419 {
13420 return !other.operator < (*this);
13421 }
13422
13427 bool operator>(const iter_impl& other) const
13428 {
13429 return !operator<=(other);
13430 }
13431
13436 bool operator>=(const iter_impl& other) const
13437 {
13438 return !operator<(other);
13439 }
13440
13446 {
13447 JSON_ASSERT(m_object != nullptr);
13448
13449 switch (m_object->m_data.m_type)
13450 {
13451 case value_t::object:
13452 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13453
13454 case value_t::array:
13455 {
13456 std::advance(m_it.array_iterator, i);
13457 break;
13458 }
13459
13460 case value_t::null:
13461 case value_t::string:
13462 case value_t::boolean:
13466 case value_t::binary:
13467 case value_t::discarded:
13468 default:
13469 {
13470 m_it.primitive_iterator += i;
13471 break;
13472 }
13473 }
13474
13475 return *this;
13476 }
13477
13483 {
13484 return operator+=(-i);
13485 }
13486
13492 {
13493 auto result = *this;
13494 result += i;
13495 return result;
13496 }
13497
13503 {
13504 auto result = it;
13505 result += i;
13506 return result;
13507 }
13508
13514 {
13515 auto result = *this;
13516 result -= i;
13517 return result;
13518 }
13519
13525 {
13526 JSON_ASSERT(m_object != nullptr);
13527
13528 switch (m_object->m_data.m_type)
13529 {
13530 case value_t::object:
13531 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13532
13533 case value_t::array:
13534 return m_it.array_iterator - other.m_it.array_iterator;
13535
13536 case value_t::null:
13537 case value_t::string:
13538 case value_t::boolean:
13542 case value_t::binary:
13543 case value_t::discarded:
13544 default:
13545 return m_it.primitive_iterator - other.m_it.primitive_iterator;
13546 }
13547 }
13548
13554 {
13555 JSON_ASSERT(m_object != nullptr);
13556
13557 switch (m_object->m_data.m_type)
13558 {
13559 case value_t::object:
13560 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
13561
13562 case value_t::array:
13563 return *std::next(m_it.array_iterator, n);
13564
13565 case value_t::null:
13566 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13567
13568 case value_t::string:
13569 case value_t::boolean:
13573 case value_t::binary:
13574 case value_t::discarded:
13575 default:
13576 {
13577 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
13578 {
13579 return *m_object;
13580 }
13581
13582 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13583 }
13584 }
13585 }
13586
13591 const typename object_t::key_type& key() const
13592 {
13593 JSON_ASSERT(m_object != nullptr);
13594
13595 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
13596 {
13597 return m_it.object_iterator->first;
13598 }
13599
13600 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
13601 }
13602
13608 {
13609 return operator*();
13610 }
13611
13612 JSON_PRIVATE_UNLESS_TESTED:
13614 pointer m_object = nullptr;
13617};
13618
13619} // namespace detail
13620NLOHMANN_JSON_NAMESPACE_END
13621
13622// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
13623
13624// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
13625// __ _____ _____ _____
13626// __| | __| | | | JSON for Modern C++
13627// | | |__ | | | | | | version 3.11.3
13628// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13629//
13630// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13631// SPDX-License-Identifier: MIT
13632
13633
13634
13635#include <cstddef> // ptrdiff_t
13636#include <iterator> // reverse_iterator
13637#include <utility> // declval
13638
13639// #include <nlohmann/detail/abi_macros.hpp>
13640
13641
13642NLOHMANN_JSON_NAMESPACE_BEGIN
13643namespace detail
13644{
13645
13647// reverse_iterator //
13649
13668template<typename Base>
13669class json_reverse_iterator : public std::reverse_iterator<Base>
13670{
13671 public:
13672 using difference_type = std::ptrdiff_t;
13674 using base_iterator = std::reverse_iterator<Base>;
13676 using reference = typename Base::reference;
13677
13679 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13680 : base_iterator(it) {}
13681
13683 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13684
13686 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
13687 {
13688 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13689 }
13690
13693 {
13694 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13695 }
13696
13698 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
13699 {
13700 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13701 }
13702
13705 {
13706 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13707 }
13708
13711 {
13712 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13713 }
13714
13716 json_reverse_iterator operator+(difference_type i) const
13717 {
13718 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13719 }
13720
13722 json_reverse_iterator operator-(difference_type i) const
13723 {
13724 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13725 }
13726
13728 difference_type operator-(const json_reverse_iterator& other) const
13729 {
13730 return base_iterator(*this) - base_iterator(other);
13731 }
13732
13734 reference operator[](difference_type n) const
13735 {
13736 return *(this->operator+(n));
13737 }
13738
13740 auto key() const -> decltype(std::declval<Base>().key())
13741 {
13742 auto it = --this->base();
13743 return it.key();
13744 }
13745
13748 {
13749 auto it = --this->base();
13750 return it.operator * ();
13751 }
13752};
13753
13754} // namespace detail
13755NLOHMANN_JSON_NAMESPACE_END
13756
13757// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13758
13759// #include <nlohmann/detail/json_custom_base_class.hpp>
13760// __ _____ _____ _____
13761// __| | __| | | | JSON for Modern C++
13762// | | |__ | | | | | | version 3.11.3
13763// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13764//
13765// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13766// SPDX-License-Identifier: MIT
13767
13768
13769
13770#include <type_traits> // conditional, is_same
13771
13772// #include <nlohmann/detail/abi_macros.hpp>
13773
13774
13775NLOHMANN_JSON_NAMESPACE_BEGIN
13776namespace detail
13777{
13778
13789struct json_default_base {};
13790
13791template<class T>
13792using json_base_class = typename std::conditional <
13793 std::is_same<T, void>::value,
13794 json_default_base,
13795 T
13796 >::type;
13797
13798} // namespace detail
13799NLOHMANN_JSON_NAMESPACE_END
13800
13801// #include <nlohmann/detail/json_pointer.hpp>
13802// __ _____ _____ _____
13803// __| | __| | | | JSON for Modern C++
13804// | | |__ | | | | | | version 3.11.3
13805// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13806//
13807// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13808// SPDX-License-Identifier: MIT
13809
13810
13811
13812#include <algorithm> // all_of
13813#include <cctype> // isdigit
13814#include <cerrno> // errno, ERANGE
13815#include <cstdlib> // strtoull
13816#ifndef JSON_NO_IO
13817 #include <iosfwd> // ostream
13818#endif // JSON_NO_IO
13819#include <limits> // max
13820#include <numeric> // accumulate
13821#include <string> // string
13822#include <utility> // move
13823#include <vector> // vector
13824
13825// #include <nlohmann/detail/exceptions.hpp>
13826
13827// #include <nlohmann/detail/macro_scope.hpp>
13828
13829// #include <nlohmann/detail/string_concat.hpp>
13830
13831// #include <nlohmann/detail/string_escape.hpp>
13832
13833// #include <nlohmann/detail/value_t.hpp>
13834
13835
13836NLOHMANN_JSON_NAMESPACE_BEGIN
13837
13840template<typename RefStringType>
13841class json_pointer
13842{
13843 // allow basic_json to access private members
13844 NLOHMANN_BASIC_JSON_TPL_DECLARATION
13845 friend class basic_json;
13846
13847 template<typename>
13848 friend class json_pointer;
13849
13850 template<typename T>
13851 struct string_t_helper
13852 {
13853 using type = T;
13854 };
13855
13856 NLOHMANN_BASIC_JSON_TPL_DECLARATION
13857 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
13858 {
13859 using type = StringType;
13860 };
13861
13862 public:
13863 // for backwards compatibility accept BasicJsonType
13864 using string_t = typename string_t_helper<RefStringType>::type;
13865
13868 explicit json_pointer(const string_t& s = "")
13869 : reference_tokens(split(s))
13870 {}
13871
13874 string_t to_string() const
13875 {
13876 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
13877 string_t{},
13878 [](const string_t& a, const string_t& b)
13879 {
13880 return detail::concat(a, '/', detail::escape(b));
13881 });
13882 }
13883
13886 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
13887 operator string_t() const
13888 {
13889 return to_string();
13890 }
13891
13892#ifndef JSON_NO_IO
13895 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
13896 {
13897 o << ptr.to_string();
13898 return o;
13899 }
13900#endif
13901
13905 {
13906 reference_tokens.insert(reference_tokens.end(),
13907 ptr.reference_tokens.begin(),
13908 ptr.reference_tokens.end());
13909 return *this;
13910 }
13911
13914 json_pointer& operator/=(string_t token)
13915 {
13916 push_back(std::move(token));
13917 return *this;
13918 }
13919
13922 json_pointer& operator/=(std::size_t array_idx)
13923 {
13924 return *this /= std::to_string(array_idx);
13925 }
13926
13930 const json_pointer& rhs)
13931 {
13932 return json_pointer(lhs) /= rhs;
13933 }
13934
13937 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
13938 {
13939 return json_pointer(lhs) /= std::move(token);
13940 }
13941
13944 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
13945 {
13946 return json_pointer(lhs) /= array_idx;
13947 }
13948
13952 {
13953 if (empty())
13954 {
13955 return *this;
13956 }
13957
13958 json_pointer res = *this;
13959 res.pop_back();
13960 return res;
13961 }
13962
13966 {
13967 if (JSON_HEDLEY_UNLIKELY(empty()))
13968 {
13969 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13970 }
13971
13972 reference_tokens.pop_back();
13973 }
13974
13977 const string_t& back() const
13978 {
13979 if (JSON_HEDLEY_UNLIKELY(empty()))
13980 {
13981 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13982 }
13983
13984 return reference_tokens.back();
13985 }
13986
13989 void push_back(const string_t& token)
13990 {
13991 reference_tokens.push_back(token);
13992 }
13993
13996 void push_back(string_t&& token)
13997 {
13998 reference_tokens.push_back(std::move(token));
13999 }
14000
14003 bool empty() const noexcept
14004 {
14005 return reference_tokens.empty();
14006 }
14007
14008 private:
14019 template<typename BasicJsonType>
14020 static typename BasicJsonType::size_type array_index(const string_t& s)
14021 {
14022 using size_type = typename BasicJsonType::size_type;
14023
14024 // error condition (cf. RFC 6901, Sect. 4)
14025 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14026 {
14027 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14028 }
14029
14030 // error condition (cf. RFC 6901, Sect. 4)
14031 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14032 {
14033 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14034 }
14035
14036 const char* p = s.c_str();
14037 char* p_end = nullptr;
14038 errno = 0; // strtoull doesn't reset errno
14039 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14040 if (p == p_end // invalid input or empty string
14041 || errno == ERANGE // out of range
14042 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14043 {
14044 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14045 }
14046
14047 // only triggered on special platforms (like 32bit), see also
14048 // https://github.com/nlohmann/json/pull/2203
14049 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14050 {
14051 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14052 }
14053
14054 return static_cast<size_type>(res);
14055 }
14056
14057 JSON_PRIVATE_UNLESS_TESTED:
14058 json_pointer top() const
14059 {
14060 if (JSON_HEDLEY_UNLIKELY(empty()))
14061 {
14062 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14063 }
14064
14065 json_pointer result = *this;
14066 result.reference_tokens = {reference_tokens[0]};
14067 return result;
14068 }
14069
14070 private:
14079 template<typename BasicJsonType>
14080 BasicJsonType& get_and_create(BasicJsonType& j) const
14081 {
14082 auto* result = &j;
14083
14084 // in case no reference tokens exist, return a reference to the JSON value
14085 // j which will be overwritten by a primitive value
14086 for (const auto& reference_token : reference_tokens)
14087 {
14088 switch (result->type())
14089 {
14091 {
14092 if (reference_token == "0")
14093 {
14094 // start a new array if reference token is 0
14095 result = &result->operator[](0);
14096 }
14097 else
14098 {
14099 // start a new object otherwise
14100 result = &result->operator[](reference_token);
14101 }
14102 break;
14103 }
14104
14106 {
14107 // create an entry in the object
14108 result = &result->operator[](reference_token);
14109 break;
14110 }
14111
14113 {
14114 // create an entry in the array
14115 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14116 break;
14117 }
14118
14119 /*
14120 The following code is only reached if there exists a reference
14121 token _and_ the current value is primitive. In this case, we have
14122 an error situation, because primitive values may only occur as
14123 single value; that is, with an empty list of reference tokens.
14124 */
14132 default:
14133 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14134 }
14135 }
14136
14137 return *result;
14138 }
14139
14159 template<typename BasicJsonType>
14160 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14161 {
14162 for (const auto& reference_token : reference_tokens)
14163 {
14164 // convert null values to arrays or objects before continuing
14165 if (ptr->is_null())
14166 {
14167 // check if reference token is a number
14168 const bool nums =
14169 std::all_of(reference_token.begin(), reference_token.end(),
14170 [](const unsigned char x)
14171 {
14172 return std::isdigit(x);
14173 });
14174
14175 // change value to array for numbers or "-" or to object otherwise
14176 *ptr = (nums || reference_token == "-")
14178 : detail::value_t::object;
14179 }
14180
14181 switch (ptr->type())
14182 {
14184 {
14185 // use unchecked object access
14186 ptr = &ptr->operator[](reference_token);
14187 break;
14188 }
14189
14191 {
14192 if (reference_token == "-")
14193 {
14194 // explicitly treat "-" as index beyond the end
14195 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14196 }
14197 else
14198 {
14199 // convert array index to number; unchecked access
14200 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14201 }
14202 break;
14203 }
14204
14213 default:
14214 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14215 }
14216 }
14217
14218 return *ptr;
14219 }
14220
14227 template<typename BasicJsonType>
14228 BasicJsonType& get_checked(BasicJsonType* ptr) const
14229 {
14230 for (const auto& reference_token : reference_tokens)
14231 {
14232 switch (ptr->type())
14233 {
14235 {
14236 // note: at performs range check
14237 ptr = &ptr->at(reference_token);
14238 break;
14239 }
14240
14242 {
14243 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14244 {
14245 // "-" always fails the range check
14246 JSON_THROW(detail::out_of_range::create(402, detail::concat(
14247 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14248 ") is out of range"), ptr));
14249 }
14250
14251 // note: at performs range check
14252 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14253 break;
14254 }
14255
14264 default:
14265 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14266 }
14267 }
14268
14269 return *ptr;
14270 }
14271
14285 template<typename BasicJsonType>
14286 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
14287 {
14288 for (const auto& reference_token : reference_tokens)
14289 {
14290 switch (ptr->type())
14291 {
14293 {
14294 // use unchecked object access
14295 ptr = &ptr->operator[](reference_token);
14296 break;
14297 }
14298
14300 {
14301 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14302 {
14303 // "-" cannot be used for const access
14304 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));
14305 }
14306
14307 // use unchecked array access
14308 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14309 break;
14310 }
14311
14320 default:
14321 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14322 }
14323 }
14324
14325 return *ptr;
14326 }
14327
14334 template<typename BasicJsonType>
14335 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
14336 {
14337 for (const auto& reference_token : reference_tokens)
14338 {
14339 switch (ptr->type())
14340 {
14342 {
14343 // note: at performs range check
14344 ptr = &ptr->at(reference_token);
14345 break;
14346 }
14347
14349 {
14350 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14351 {
14352 // "-" always fails the range check
14353 JSON_THROW(detail::out_of_range::create(402, detail::concat(
14354 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14355 ") is out of range"), ptr));
14356 }
14357
14358 // note: at performs range check
14359 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14360 break;
14361 }
14362
14371 default:
14372 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14373 }
14374 }
14375
14376 return *ptr;
14377 }
14378
14383 template<typename BasicJsonType>
14384 bool contains(const BasicJsonType* ptr) const
14385 {
14386 for (const auto& reference_token : reference_tokens)
14387 {
14388 switch (ptr->type())
14389 {
14391 {
14392 if (!ptr->contains(reference_token))
14393 {
14394 // we did not find the key in the object
14395 return false;
14396 }
14397
14398 ptr = &ptr->operator[](reference_token);
14399 break;
14400 }
14401
14403 {
14404 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14405 {
14406 // "-" always fails the range check
14407 return false;
14408 }
14409 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
14410 {
14411 // invalid char
14412 return false;
14413 }
14414 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
14415 {
14416 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
14417 {
14418 // first char should be between '1' and '9'
14419 return false;
14420 }
14421 for (std::size_t i = 1; i < reference_token.size(); i++)
14422 {
14423 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
14424 {
14425 // other char should be between '0' and '9'
14426 return false;
14427 }
14428 }
14429 }
14430
14431 const auto idx = array_index<BasicJsonType>(reference_token);
14432 if (idx >= ptr->size())
14433 {
14434 // index out of range
14435 return false;
14436 }
14437
14438 ptr = &ptr->operator[](idx);
14439 break;
14440 }
14441
14450 default:
14451 {
14452 // we do not expect primitive values if there is still a
14453 // reference token to process
14454 return false;
14455 }
14456 }
14457 }
14458
14459 // no reference token left means we found a primitive value
14460 return true;
14461 }
14462
14472 static std::vector<string_t> split(const string_t& reference_string)
14473 {
14474 std::vector<string_t> result;
14475
14476 // special case: empty reference string -> no reference tokens
14477 if (reference_string.empty())
14478 {
14479 return result;
14480 }
14481
14482 // check if nonempty reference string begins with slash
14483 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
14484 {
14485 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
14486 }
14487
14488 // extract the reference tokens:
14489 // - slash: position of the last read slash (or end of string)
14490 // - start: position after the previous slash
14491 for (
14492 // search for the first slash after the first character
14493 std::size_t slash = reference_string.find_first_of('/', 1),
14494 // set the beginning of the first reference token
14495 start = 1;
14496 // we can stop if start == 0 (if slash == string_t::npos)
14497 start != 0;
14498 // set the beginning of the next reference token
14499 // (will eventually be 0 if slash == string_t::npos)
14500 start = (slash == string_t::npos) ? 0 : slash + 1,
14501 // find next slash
14502 slash = reference_string.find_first_of('/', start))
14503 {
14504 // use the text between the beginning of the reference token
14505 // (start) and the last slash (slash).
14506 auto reference_token = reference_string.substr(start, slash - start);
14507
14508 // check reference tokens are properly escaped
14509 for (std::size_t pos = reference_token.find_first_of('~');
14510 pos != string_t::npos;
14511 pos = reference_token.find_first_of('~', pos + 1))
14512 {
14513 JSON_ASSERT(reference_token[pos] == '~');
14514
14515 // ~ must be followed by 0 or 1
14516 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
14517 (reference_token[pos + 1] != '0' &&
14518 reference_token[pos + 1] != '1')))
14519 {
14520 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
14521 }
14522 }
14523
14524 // finally, store the reference token
14525 detail::unescape(reference_token);
14526 result.push_back(reference_token);
14527 }
14528
14529 return result;
14530 }
14531
14532 private:
14540 template<typename BasicJsonType>
14541 static void flatten(const string_t& reference_string,
14542 const BasicJsonType& value,
14543 BasicJsonType& result)
14544 {
14545 switch (value.type())
14546 {
14548 {
14549 if (value.m_data.m_value.array->empty())
14550 {
14551 // flatten empty array as null
14552 result[reference_string] = nullptr;
14553 }
14554 else
14555 {
14556 // iterate array and use index as reference string
14557 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
14558 {
14559 flatten(detail::concat(reference_string, '/', std::to_string(i)),
14560 value.m_data.m_value.array->operator[](i), result);
14561 }
14562 }
14563 break;
14564 }
14565
14567 {
14568 if (value.m_data.m_value.object->empty())
14569 {
14570 // flatten empty object as null
14571 result[reference_string] = nullptr;
14572 }
14573 else
14574 {
14575 // iterate object and use keys as reference string
14576 for (const auto& element : *value.m_data.m_value.object)
14577 {
14578 flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
14579 }
14580 }
14581 break;
14582 }
14583
14592 default:
14593 {
14594 // add primitive value with its reference string
14595 result[reference_string] = value;
14596 break;
14597 }
14598 }
14599 }
14600
14611 template<typename BasicJsonType>
14612 static BasicJsonType
14613 unflatten(const BasicJsonType& value)
14614 {
14615 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
14616 {
14617 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
14618 }
14619
14620 BasicJsonType result;
14621
14622 // iterate the JSON object values
14623 for (const auto& element : *value.m_data.m_value.object)
14624 {
14625 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
14626 {
14627 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
14628 }
14629
14630 // assign value to reference pointed to by JSON pointer; Note that if
14631 // the JSON pointer is "" (i.e., points to the whole value), function
14632 // get_and_create returns a reference to result itself. An assignment
14633 // will then create a primitive value.
14634 json_pointer(element.first).get_and_create(result) = element.second;
14635 }
14636
14637 return result;
14638 }
14639
14640 // can't use conversion operator because of ambiguity
14641 json_pointer<string_t> convert() const&
14642 {
14644 result.reference_tokens = reference_tokens;
14645 return result;
14646 }
14647
14648 json_pointer<string_t> convert()&&
14649 {
14651 result.reference_tokens = std::move(reference_tokens);
14652 return result;
14653 }
14654
14655 public:
14656#if JSON_HAS_THREE_WAY_COMPARISON
14659 template<typename RefStringTypeRhs>
14660 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
14661 {
14662 return reference_tokens == rhs.reference_tokens;
14663 }
14664
14667 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
14668 bool operator==(const string_t& rhs) const
14669 {
14670 return *this == json_pointer(rhs);
14671 }
14672
14674 template<typename RefStringTypeRhs>
14675 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
14676 {
14677 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
14678 }
14679#else
14682 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14683 // NOLINTNEXTLINE(readability-redundant-declaration)
14684 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14685 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14686
14689 template<typename RefStringTypeLhs, typename StringType>
14690 // NOLINTNEXTLINE(readability-redundant-declaration)
14691 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14692 const StringType& rhs);
14693
14696 template<typename RefStringTypeRhs, typename StringType>
14697 // NOLINTNEXTLINE(readability-redundant-declaration)
14698 friend bool operator==(const StringType& lhs,
14700
14703 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14704 // NOLINTNEXTLINE(readability-redundant-declaration)
14705 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14706 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14707
14710 template<typename RefStringTypeLhs, typename StringType>
14711 // NOLINTNEXTLINE(readability-redundant-declaration)
14712 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14713 const StringType& rhs);
14714
14717 template<typename RefStringTypeRhs, typename StringType>
14718 // NOLINTNEXTLINE(readability-redundant-declaration)
14719 friend bool operator!=(const StringType& lhs,
14721
14723 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14724 // NOLINTNEXTLINE(readability-redundant-declaration)
14725 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14726 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14727#endif
14728
14729 private:
14731 std::vector<string_t> reference_tokens;
14732};
14733
14734#if !JSON_HAS_THREE_WAY_COMPARISON
14735// functions cannot be defined inside class due to ODR violations
14736template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14737inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14738 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14739{
14740 return lhs.reference_tokens == rhs.reference_tokens;
14741}
14742
14743template<typename RefStringTypeLhs,
14744 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14745JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
14746inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14747 const StringType& rhs)
14748{
14749 return lhs == json_pointer<RefStringTypeLhs>(rhs);
14750}
14751
14752template<typename RefStringTypeRhs,
14753 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14754JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
14755inline bool operator==(const StringType& lhs,
14756 const json_pointer<RefStringTypeRhs>& rhs)
14757{
14758 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
14759}
14760
14761template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14762inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14763 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14764{
14765 return !(lhs == rhs);
14766}
14767
14768template<typename RefStringTypeLhs,
14769 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14770JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14771inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14772 const StringType& rhs)
14773{
14774 return !(lhs == rhs);
14775}
14776
14777template<typename RefStringTypeRhs,
14778 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14779JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14780inline bool operator!=(const StringType& lhs,
14781 const json_pointer<RefStringTypeRhs>& rhs)
14782{
14783 return !(lhs == rhs);
14784}
14785
14786template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14787inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14788 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14789{
14790 return lhs.reference_tokens < rhs.reference_tokens;
14791}
14792#endif
14793
14794NLOHMANN_JSON_NAMESPACE_END
14795
14796// #include <nlohmann/detail/json_ref.hpp>
14797// __ _____ _____ _____
14798// __| | __| | | | JSON for Modern C++
14799// | | |__ | | | | | | version 3.11.3
14800// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14801//
14802// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14803// SPDX-License-Identifier: MIT
14804
14805
14806
14807#include <initializer_list>
14808#include <utility>
14809
14810// #include <nlohmann/detail/abi_macros.hpp>
14811
14812// #include <nlohmann/detail/meta/type_traits.hpp>
14813
14814
14815NLOHMANN_JSON_NAMESPACE_BEGIN
14816namespace detail
14817{
14818
14819template<typename BasicJsonType>
14820class json_ref
14821{
14822 public:
14823 using value_type = BasicJsonType;
14824
14825 json_ref(value_type&& value)
14826 : owned_value(std::move(value))
14827 {}
14828
14829 json_ref(const value_type& value)
14830 : value_ref(&value)
14831 {}
14832
14833 json_ref(std::initializer_list<json_ref> init)
14834 : owned_value(init)
14835 {}
14836
14837 template <
14838 class... Args,
14839 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
14840 json_ref(Args && ... args)
14841 : owned_value(std::forward<Args>(args)...)
14842 {}
14843
14844 // class should be movable only
14845 json_ref(json_ref&&) noexcept = default;
14846 json_ref(const json_ref&) = delete;
14847 json_ref& operator=(const json_ref&) = delete;
14848 json_ref& operator=(json_ref&&) = delete;
14849 ~json_ref() = default;
14850
14851 value_type moved_or_copied() const
14852 {
14853 if (value_ref == nullptr)
14854 {
14855 return std::move(owned_value);
14856 }
14857 return *value_ref;
14858 }
14859
14860 value_type const& operator*() const
14861 {
14862 return value_ref ? *value_ref : owned_value;
14863 }
14864
14865 value_type const* operator->() const
14866 {
14867 return &** this;
14868 }
14869
14870 private:
14871 mutable value_type owned_value = nullptr;
14872 value_type const* value_ref = nullptr;
14873};
14874
14875} // namespace detail
14876NLOHMANN_JSON_NAMESPACE_END
14877
14878// #include <nlohmann/detail/macro_scope.hpp>
14879
14880// #include <nlohmann/detail/string_concat.hpp>
14881
14882// #include <nlohmann/detail/string_escape.hpp>
14883
14884// #include <nlohmann/detail/meta/cpp_future.hpp>
14885
14886// #include <nlohmann/detail/meta/type_traits.hpp>
14887
14888// #include <nlohmann/detail/output/binary_writer.hpp>
14889// __ _____ _____ _____
14890// __| | __| | | | JSON for Modern C++
14891// | | |__ | | | | | | version 3.11.3
14892// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14893//
14894// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14895// SPDX-License-Identifier: MIT
14896
14897
14898
14899#include <algorithm> // reverse
14900#include <array> // array
14901#include <map> // map
14902#include <cmath> // isnan, isinf
14903#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
14904#include <cstring> // memcpy
14905#include <limits> // numeric_limits
14906#include <string> // string
14907#include <utility> // move
14908#include <vector> // vector
14909
14910// #include <nlohmann/detail/input/binary_reader.hpp>
14911
14912// #include <nlohmann/detail/macro_scope.hpp>
14913
14914// #include <nlohmann/detail/output/output_adapters.hpp>
14915// __ _____ _____ _____
14916// __| | __| | | | JSON for Modern C++
14917// | | |__ | | | | | | version 3.11.3
14918// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14919//
14920// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14921// SPDX-License-Identifier: MIT
14922
14923
14924
14925#include <algorithm> // copy
14926#include <cstddef> // size_t
14927#include <iterator> // back_inserter
14928#include <memory> // shared_ptr, make_shared
14929#include <string> // basic_string
14930#include <vector> // vector
14931
14932#ifndef JSON_NO_IO
14933 #include <ios> // streamsize
14934 #include <ostream> // basic_ostream
14935#endif // JSON_NO_IO
14936
14937// #include <nlohmann/detail/macro_scope.hpp>
14938
14939
14940NLOHMANN_JSON_NAMESPACE_BEGIN
14941namespace detail
14942{
14943
14945template<typename CharType> struct output_adapter_protocol
14946{
14947 virtual void write_character(CharType c) = 0;
14948 virtual void write_characters(const CharType* s, std::size_t length) = 0;
14949 virtual ~output_adapter_protocol() = default;
14950
14951 output_adapter_protocol() = default;
14952 output_adapter_protocol(const output_adapter_protocol&) = default;
14953 output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
14954 output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
14955 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
14956};
14957
14959template<typename CharType>
14960using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
14961
14963template<typename CharType, typename AllocatorType = std::allocator<CharType>>
14964class output_vector_adapter : public output_adapter_protocol<CharType>
14965{
14966 public:
14967 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
14968 : v(vec)
14969 {}
14970
14971 void write_character(CharType c) override
14972 {
14973 v.push_back(c);
14974 }
14975
14976 JSON_HEDLEY_NON_NULL(2)
14977 void write_characters(const CharType* s, std::size_t length) override
14978 {
14979 v.insert(v.end(), s, s + length);
14980 }
14981
14982 private:
14983 std::vector<CharType, AllocatorType>& v;
14984};
14985
14986#ifndef JSON_NO_IO
14988template<typename CharType>
14989class output_stream_adapter : public output_adapter_protocol<CharType>
14990{
14991 public:
14992 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
14993 : stream(s)
14994 {}
14995
14996 void write_character(CharType c) override
14997 {
14998 stream.put(c);
14999 }
15000
15001 JSON_HEDLEY_NON_NULL(2)
15002 void write_characters(const CharType* s, std::size_t length) override
15003 {
15004 stream.write(s, static_cast<std::streamsize>(length));
15005 }
15006
15007 private:
15008 std::basic_ostream<CharType>& stream;
15009};
15010#endif // JSON_NO_IO
15011
15013template<typename CharType, typename StringType = std::basic_string<CharType>>
15014class output_string_adapter : public output_adapter_protocol<CharType>
15015{
15016 public:
15017 explicit output_string_adapter(StringType& s) noexcept
15018 : str(s)
15019 {}
15020
15021 void write_character(CharType c) override
15022 {
15023 str.push_back(c);
15024 }
15025
15026 JSON_HEDLEY_NON_NULL(2)
15027 void write_characters(const CharType* s, std::size_t length) override
15028 {
15029 str.append(s, length);
15030 }
15031
15032 private:
15033 StringType& str;
15034};
15035
15036template<typename CharType, typename StringType = std::basic_string<CharType>>
15037class output_adapter
15038{
15039 public:
15040 template<typename AllocatorType = std::allocator<CharType>>
15041 output_adapter(std::vector<CharType, AllocatorType>& vec)
15042 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15043
15044#ifndef JSON_NO_IO
15045 output_adapter(std::basic_ostream<CharType>& s)
15046 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15047#endif // JSON_NO_IO
15048
15049 output_adapter(StringType& s)
15050 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15051
15052 operator output_adapter_t<CharType>()
15053 {
15054 return oa;
15055 }
15056
15057 private:
15058 output_adapter_t<CharType> oa = nullptr;
15059};
15060
15061} // namespace detail
15062NLOHMANN_JSON_NAMESPACE_END
15063
15064// #include <nlohmann/detail/string_concat.hpp>
15065
15066
15067NLOHMANN_JSON_NAMESPACE_BEGIN
15068namespace detail
15069{
15070
15072// binary writer //
15074
15078template<typename BasicJsonType, typename CharType>
15079class binary_writer
15080{
15081 using string_t = typename BasicJsonType::string_t;
15082 using binary_t = typename BasicJsonType::binary_t;
15083 using number_float_t = typename BasicJsonType::number_float_t;
15084
15085 public:
15091 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15092 {
15093 JSON_ASSERT(oa);
15094 }
15095
15100 void write_bson(const BasicJsonType& j)
15101 {
15102 switch (j.type())
15103 {
15104 case value_t::object:
15105 {
15106 write_bson_object(*j.m_data.m_value.object);
15107 break;
15108 }
15109
15110 case value_t::null:
15111 case value_t::array:
15112 case value_t::string:
15113 case value_t::boolean:
15114 case value_t::number_integer:
15115 case value_t::number_unsigned:
15116 case value_t::number_float:
15117 case value_t::binary:
15118 case value_t::discarded:
15119 default:
15120 {
15121 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15122 }
15123 }
15124 }
15125
15129 void write_cbor(const BasicJsonType& j)
15130 {
15131 switch (j.type())
15132 {
15133 case value_t::null:
15134 {
15135 oa->write_character(to_char_type(0xF6));
15136 break;
15137 }
15138
15139 case value_t::boolean:
15140 {
15141 oa->write_character(j.m_data.m_value.boolean
15142 ? to_char_type(0xF5)
15143 : to_char_type(0xF4));
15144 break;
15145 }
15146
15147 case value_t::number_integer:
15148 {
15149 if (j.m_data.m_value.number_integer >= 0)
15150 {
15151 // CBOR does not differentiate between positive signed
15152 // integers and unsigned integers. Therefore, we used the
15153 // code from the value_t::number_unsigned case here.
15154 if (j.m_data.m_value.number_integer <= 0x17)
15155 {
15156 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15157 }
15158 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15159 {
15160 oa->write_character(to_char_type(0x18));
15161 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15162 }
15163 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15164 {
15165 oa->write_character(to_char_type(0x19));
15166 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15167 }
15168 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15169 {
15170 oa->write_character(to_char_type(0x1A));
15171 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15172 }
15173 else
15174 {
15175 oa->write_character(to_char_type(0x1B));
15176 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15177 }
15178 }
15179 else
15180 {
15181 // The conversions below encode the sign in the first
15182 // byte, and the value is converted to a positive number.
15183 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15184 if (j.m_data.m_value.number_integer >= -24)
15185 {
15186 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15187 }
15188 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15189 {
15190 oa->write_character(to_char_type(0x38));
15191 write_number(static_cast<std::uint8_t>(positive_number));
15192 }
15193 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15194 {
15195 oa->write_character(to_char_type(0x39));
15196 write_number(static_cast<std::uint16_t>(positive_number));
15197 }
15198 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15199 {
15200 oa->write_character(to_char_type(0x3A));
15201 write_number(static_cast<std::uint32_t>(positive_number));
15202 }
15203 else
15204 {
15205 oa->write_character(to_char_type(0x3B));
15206 write_number(static_cast<std::uint64_t>(positive_number));
15207 }
15208 }
15209 break;
15210 }
15211
15212 case value_t::number_unsigned:
15213 {
15214 if (j.m_data.m_value.number_unsigned <= 0x17)
15215 {
15216 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15217 }
15218 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15219 {
15220 oa->write_character(to_char_type(0x18));
15221 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15222 }
15223 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15224 {
15225 oa->write_character(to_char_type(0x19));
15226 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15227 }
15228 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15229 {
15230 oa->write_character(to_char_type(0x1A));
15231 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15232 }
15233 else
15234 {
15235 oa->write_character(to_char_type(0x1B));
15236 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15237 }
15238 break;
15239 }
15240
15241 case value_t::number_float:
15242 {
15243 if (std::isnan(j.m_data.m_value.number_float))
15244 {
15245 // NaN is 0xf97e00 in CBOR
15246 oa->write_character(to_char_type(0xF9));
15247 oa->write_character(to_char_type(0x7E));
15248 oa->write_character(to_char_type(0x00));
15249 }
15250 else if (std::isinf(j.m_data.m_value.number_float))
15251 {
15252 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
15253 oa->write_character(to_char_type(0xf9));
15254 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15255 oa->write_character(to_char_type(0x00));
15256 }
15257 else
15258 {
15259 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15260 }
15261 break;
15262 }
15263
15264 case value_t::string:
15265 {
15266 // step 1: write control byte and the string length
15267 const auto N = j.m_data.m_value.string->size();
15268 if (N <= 0x17)
15269 {
15270 write_number(static_cast<std::uint8_t>(0x60 + N));
15271 }
15272 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15273 {
15274 oa->write_character(to_char_type(0x78));
15275 write_number(static_cast<std::uint8_t>(N));
15276 }
15277 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15278 {
15279 oa->write_character(to_char_type(0x79));
15280 write_number(static_cast<std::uint16_t>(N));
15281 }
15282 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15283 {
15284 oa->write_character(to_char_type(0x7A));
15285 write_number(static_cast<std::uint32_t>(N));
15286 }
15287 // LCOV_EXCL_START
15288 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15289 {
15290 oa->write_character(to_char_type(0x7B));
15291 write_number(static_cast<std::uint64_t>(N));
15292 }
15293 // LCOV_EXCL_STOP
15294
15295 // step 2: write the string
15296 oa->write_characters(
15297 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15298 j.m_data.m_value.string->size());
15299 break;
15300 }
15301
15302 case value_t::array:
15303 {
15304 // step 1: write control byte and the array size
15305 const auto N = j.m_data.m_value.array->size();
15306 if (N <= 0x17)
15307 {
15308 write_number(static_cast<std::uint8_t>(0x80 + N));
15309 }
15310 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15311 {
15312 oa->write_character(to_char_type(0x98));
15313 write_number(static_cast<std::uint8_t>(N));
15314 }
15315 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15316 {
15317 oa->write_character(to_char_type(0x99));
15318 write_number(static_cast<std::uint16_t>(N));
15319 }
15320 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15321 {
15322 oa->write_character(to_char_type(0x9A));
15323 write_number(static_cast<std::uint32_t>(N));
15324 }
15325 // LCOV_EXCL_START
15326 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15327 {
15328 oa->write_character(to_char_type(0x9B));
15329 write_number(static_cast<std::uint64_t>(N));
15330 }
15331 // LCOV_EXCL_STOP
15332
15333 // step 2: write each element
15334 for (const auto& el : *j.m_data.m_value.array)
15335 {
15336 write_cbor(el);
15337 }
15338 break;
15339 }
15340
15341 case value_t::binary:
15342 {
15343 if (j.m_data.m_value.binary->has_subtype())
15344 {
15345 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
15346 {
15347 write_number(static_cast<std::uint8_t>(0xd8));
15348 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
15349 }
15350 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
15351 {
15352 write_number(static_cast<std::uint8_t>(0xd9));
15353 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
15354 }
15355 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
15356 {
15357 write_number(static_cast<std::uint8_t>(0xda));
15358 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
15359 }
15360 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
15361 {
15362 write_number(static_cast<std::uint8_t>(0xdb));
15363 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
15364 }
15365 }
15366
15367 // step 1: write control byte and the binary array size
15368 const auto N = j.m_data.m_value.binary->size();
15369 if (N <= 0x17)
15370 {
15371 write_number(static_cast<std::uint8_t>(0x40 + N));
15372 }
15373 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15374 {
15375 oa->write_character(to_char_type(0x58));
15376 write_number(static_cast<std::uint8_t>(N));
15377 }
15378 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15379 {
15380 oa->write_character(to_char_type(0x59));
15381 write_number(static_cast<std::uint16_t>(N));
15382 }
15383 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15384 {
15385 oa->write_character(to_char_type(0x5A));
15386 write_number(static_cast<std::uint32_t>(N));
15387 }
15388 // LCOV_EXCL_START
15389 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15390 {
15391 oa->write_character(to_char_type(0x5B));
15392 write_number(static_cast<std::uint64_t>(N));
15393 }
15394 // LCOV_EXCL_STOP
15395
15396 // step 2: write each element
15397 oa->write_characters(
15398 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15399 N);
15400
15401 break;
15402 }
15403
15404 case value_t::object:
15405 {
15406 // step 1: write control byte and the object size
15407 const auto N = j.m_data.m_value.object->size();
15408 if (N <= 0x17)
15409 {
15410 write_number(static_cast<std::uint8_t>(0xA0 + N));
15411 }
15412 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15413 {
15414 oa->write_character(to_char_type(0xB8));
15415 write_number(static_cast<std::uint8_t>(N));
15416 }
15417 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15418 {
15419 oa->write_character(to_char_type(0xB9));
15420 write_number(static_cast<std::uint16_t>(N));
15421 }
15422 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15423 {
15424 oa->write_character(to_char_type(0xBA));
15425 write_number(static_cast<std::uint32_t>(N));
15426 }
15427 // LCOV_EXCL_START
15428 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15429 {
15430 oa->write_character(to_char_type(0xBB));
15431 write_number(static_cast<std::uint64_t>(N));
15432 }
15433 // LCOV_EXCL_STOP
15434
15435 // step 2: write each element
15436 for (const auto& el : *j.m_data.m_value.object)
15437 {
15438 write_cbor(el.first);
15439 write_cbor(el.second);
15440 }
15441 break;
15442 }
15443
15444 case value_t::discarded:
15445 default:
15446 break;
15447 }
15448 }
15449
15453 void write_msgpack(const BasicJsonType& j)
15454 {
15455 switch (j.type())
15456 {
15457 case value_t::null: // nil
15458 {
15459 oa->write_character(to_char_type(0xC0));
15460 break;
15461 }
15462
15463 case value_t::boolean: // true and false
15464 {
15465 oa->write_character(j.m_data.m_value.boolean
15466 ? to_char_type(0xC3)
15467 : to_char_type(0xC2));
15468 break;
15469 }
15470
15471 case value_t::number_integer:
15472 {
15473 if (j.m_data.m_value.number_integer >= 0)
15474 {
15475 // MessagePack does not differentiate between positive
15476 // signed integers and unsigned integers. Therefore, we used
15477 // the code from the value_t::number_unsigned case here.
15478 if (j.m_data.m_value.number_unsigned < 128)
15479 {
15480 // positive fixnum
15481 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15482 }
15483 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15484 {
15485 // uint 8
15486 oa->write_character(to_char_type(0xCC));
15487 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15488 }
15489 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15490 {
15491 // uint 16
15492 oa->write_character(to_char_type(0xCD));
15493 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15494 }
15495 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15496 {
15497 // uint 32
15498 oa->write_character(to_char_type(0xCE));
15499 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15500 }
15501 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15502 {
15503 // uint 64
15504 oa->write_character(to_char_type(0xCF));
15505 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15506 }
15507 }
15508 else
15509 {
15510 if (j.m_data.m_value.number_integer >= -32)
15511 {
15512 // negative fixnum
15513 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15514 }
15515 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
15516 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
15517 {
15518 // int 8
15519 oa->write_character(to_char_type(0xD0));
15520 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15521 }
15522 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
15523 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
15524 {
15525 // int 16
15526 oa->write_character(to_char_type(0xD1));
15527 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
15528 }
15529 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
15530 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
15531 {
15532 // int 32
15533 oa->write_character(to_char_type(0xD2));
15534 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
15535 }
15536 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
15537 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
15538 {
15539 // int 64
15540 oa->write_character(to_char_type(0xD3));
15541 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
15542 }
15543 }
15544 break;
15545 }
15546
15547 case value_t::number_unsigned:
15548 {
15549 if (j.m_data.m_value.number_unsigned < 128)
15550 {
15551 // positive fixnum
15552 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15553 }
15554 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15555 {
15556 // uint 8
15557 oa->write_character(to_char_type(0xCC));
15558 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15559 }
15560 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15561 {
15562 // uint 16
15563 oa->write_character(to_char_type(0xCD));
15564 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15565 }
15566 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15567 {
15568 // uint 32
15569 oa->write_character(to_char_type(0xCE));
15570 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15571 }
15572 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15573 {
15574 // uint 64
15575 oa->write_character(to_char_type(0xCF));
15576 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15577 }
15578 break;
15579 }
15580
15581 case value_t::number_float:
15582 {
15583 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
15584 break;
15585 }
15586
15587 case value_t::string:
15588 {
15589 // step 1: write control byte and the string length
15590 const auto N = j.m_data.m_value.string->size();
15591 if (N <= 31)
15592 {
15593 // fixstr
15594 write_number(static_cast<std::uint8_t>(0xA0 | N));
15595 }
15596 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15597 {
15598 // str 8
15599 oa->write_character(to_char_type(0xD9));
15600 write_number(static_cast<std::uint8_t>(N));
15601 }
15602 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15603 {
15604 // str 16
15605 oa->write_character(to_char_type(0xDA));
15606 write_number(static_cast<std::uint16_t>(N));
15607 }
15608 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15609 {
15610 // str 32
15611 oa->write_character(to_char_type(0xDB));
15612 write_number(static_cast<std::uint32_t>(N));
15613 }
15614
15615 // step 2: write the string
15616 oa->write_characters(
15617 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15618 j.m_data.m_value.string->size());
15619 break;
15620 }
15621
15622 case value_t::array:
15623 {
15624 // step 1: write control byte and the array size
15625 const auto N = j.m_data.m_value.array->size();
15626 if (N <= 15)
15627 {
15628 // fixarray
15629 write_number(static_cast<std::uint8_t>(0x90 | N));
15630 }
15631 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15632 {
15633 // array 16
15634 oa->write_character(to_char_type(0xDC));
15635 write_number(static_cast<std::uint16_t>(N));
15636 }
15637 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15638 {
15639 // array 32
15640 oa->write_character(to_char_type(0xDD));
15641 write_number(static_cast<std::uint32_t>(N));
15642 }
15643
15644 // step 2: write each element
15645 for (const auto& el : *j.m_data.m_value.array)
15646 {
15647 write_msgpack(el);
15648 }
15649 break;
15650 }
15651
15652 case value_t::binary:
15653 {
15654 // step 0: determine if the binary type has a set subtype to
15655 // determine whether or not to use the ext or fixext types
15656 const bool use_ext = j.m_data.m_value.binary->has_subtype();
15657
15658 // step 1: write control byte and the byte string length
15659 const auto N = j.m_data.m_value.binary->size();
15660 if (N <= (std::numeric_limits<std::uint8_t>::max)())
15661 {
15662 std::uint8_t output_type{};
15663 bool fixed = true;
15664 if (use_ext)
15665 {
15666 switch (N)
15667 {
15668 case 1:
15669 output_type = 0xD4; // fixext 1
15670 break;
15671 case 2:
15672 output_type = 0xD5; // fixext 2
15673 break;
15674 case 4:
15675 output_type = 0xD6; // fixext 4
15676 break;
15677 case 8:
15678 output_type = 0xD7; // fixext 8
15679 break;
15680 case 16:
15681 output_type = 0xD8; // fixext 16
15682 break;
15683 default:
15684 output_type = 0xC7; // ext 8
15685 fixed = false;
15686 break;
15687 }
15688
15689 }
15690 else
15691 {
15692 output_type = 0xC4; // bin 8
15693 fixed = false;
15694 }
15695
15696 oa->write_character(to_char_type(output_type));
15697 if (!fixed)
15698 {
15699 write_number(static_cast<std::uint8_t>(N));
15700 }
15701 }
15702 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15703 {
15704 const std::uint8_t output_type = use_ext
15705 ? 0xC8 // ext 16
15706 : 0xC5; // bin 16
15707
15708 oa->write_character(to_char_type(output_type));
15709 write_number(static_cast<std::uint16_t>(N));
15710 }
15711 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15712 {
15713 const std::uint8_t output_type = use_ext
15714 ? 0xC9 // ext 32
15715 : 0xC6; // bin 32
15716
15717 oa->write_character(to_char_type(output_type));
15718 write_number(static_cast<std::uint32_t>(N));
15719 }
15720
15721 // step 1.5: if this is an ext type, write the subtype
15722 if (use_ext)
15723 {
15724 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
15725 }
15726
15727 // step 2: write the byte string
15728 oa->write_characters(
15729 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15730 N);
15731
15732 break;
15733 }
15734
15735 case value_t::object:
15736 {
15737 // step 1: write control byte and the object size
15738 const auto N = j.m_data.m_value.object->size();
15739 if (N <= 15)
15740 {
15741 // fixmap
15742 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
15743 }
15744 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15745 {
15746 // map 16
15747 oa->write_character(to_char_type(0xDE));
15748 write_number(static_cast<std::uint16_t>(N));
15749 }
15750 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15751 {
15752 // map 32
15753 oa->write_character(to_char_type(0xDF));
15754 write_number(static_cast<std::uint32_t>(N));
15755 }
15756
15757 // step 2: write each element
15758 for (const auto& el : *j.m_data.m_value.object)
15759 {
15760 write_msgpack(el.first);
15761 write_msgpack(el.second);
15762 }
15763 break;
15764 }
15765
15766 case value_t::discarded:
15767 default:
15768 break;
15769 }
15770 }
15771
15779 void write_ubjson(const BasicJsonType& j, const bool use_count,
15780 const bool use_type, const bool add_prefix = true,
15781 const bool use_bjdata = false)
15782 {
15783 switch (j.type())
15784 {
15785 case value_t::null:
15786 {
15787 if (add_prefix)
15788 {
15789 oa->write_character(to_char_type('Z'));
15790 }
15791 break;
15792 }
15793
15794 case value_t::boolean:
15795 {
15796 if (add_prefix)
15797 {
15798 oa->write_character(j.m_data.m_value.boolean
15799 ? to_char_type('T')
15800 : to_char_type('F'));
15801 }
15802 break;
15803 }
15804
15805 case value_t::number_integer:
15806 {
15807 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
15808 break;
15809 }
15810
15811 case value_t::number_unsigned:
15812 {
15813 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
15814 break;
15815 }
15816
15817 case value_t::number_float:
15818 {
15819 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
15820 break;
15821 }
15822
15823 case value_t::string:
15824 {
15825 if (add_prefix)
15826 {
15827 oa->write_character(to_char_type('S'));
15828 }
15829 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
15830 oa->write_characters(
15831 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15832 j.m_data.m_value.string->size());
15833 break;
15834 }
15835
15836 case value_t::array:
15837 {
15838 if (add_prefix)
15839 {
15840 oa->write_character(to_char_type('['));
15841 }
15842
15843 bool prefix_required = true;
15844 if (use_type && !j.m_data.m_value.array->empty())
15845 {
15846 JSON_ASSERT(use_count);
15847 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15848 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
15849 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15850 {
15851 return ubjson_prefix(v, use_bjdata) == first_prefix;
15852 });
15853
15854 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15855
15856 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15857 {
15858 prefix_required = false;
15859 oa->write_character(to_char_type('$'));
15860 oa->write_character(first_prefix);
15861 }
15862 }
15863
15864 if (use_count)
15865 {
15866 oa->write_character(to_char_type('#'));
15867 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
15868 }
15869
15870 for (const auto& el : *j.m_data.m_value.array)
15871 {
15872 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
15873 }
15874
15875 if (!use_count)
15876 {
15877 oa->write_character(to_char_type(']'));
15878 }
15879
15880 break;
15881 }
15882
15883 case value_t::binary:
15884 {
15885 if (add_prefix)
15886 {
15887 oa->write_character(to_char_type('['));
15888 }
15889
15890 if (use_type && !j.m_data.m_value.binary->empty())
15891 {
15892 JSON_ASSERT(use_count);
15893 oa->write_character(to_char_type('$'));
15894 oa->write_character('U');
15895 }
15896
15897 if (use_count)
15898 {
15899 oa->write_character(to_char_type('#'));
15900 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
15901 }
15902
15903 if (use_type)
15904 {
15905 oa->write_characters(
15906 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15907 j.m_data.m_value.binary->size());
15908 }
15909 else
15910 {
15911 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
15912 {
15913 oa->write_character(to_char_type('U'));
15914 oa->write_character(j.m_data.m_value.binary->data()[i]);
15915 }
15916 }
15917
15918 if (!use_count)
15919 {
15920 oa->write_character(to_char_type(']'));
15921 }
15922
15923 break;
15924 }
15925
15926 case value_t::object:
15927 {
15928 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())
15929 {
15930 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)
15931 {
15932 break;
15933 }
15934 }
15935
15936 if (add_prefix)
15937 {
15938 oa->write_character(to_char_type('{'));
15939 }
15940
15941 bool prefix_required = true;
15942 if (use_type && !j.m_data.m_value.object->empty())
15943 {
15944 JSON_ASSERT(use_count);
15945 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15946 const bool same_prefix = std::all_of(j.begin(), j.end(),
15947 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15948 {
15949 return ubjson_prefix(v, use_bjdata) == first_prefix;
15950 });
15951
15952 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15953
15954 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15955 {
15956 prefix_required = false;
15957 oa->write_character(to_char_type('$'));
15958 oa->write_character(first_prefix);
15959 }
15960 }
15961
15962 if (use_count)
15963 {
15964 oa->write_character(to_char_type('#'));
15965 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
15966 }
15967
15968 for (const auto& el : *j.m_data.m_value.object)
15969 {
15970 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
15971 oa->write_characters(
15972 reinterpret_cast<const CharType*>(el.first.c_str()),
15973 el.first.size());
15974 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
15975 }
15976
15977 if (!use_count)
15978 {
15979 oa->write_character(to_char_type('}'));
15980 }
15981
15982 break;
15983 }
15984
15985 case value_t::discarded:
15986 default:
15987 break;
15988 }
15989 }
15990
15991 private:
15993 // BSON //
15995
16000 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16001 {
16002 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16003 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16004 {
16005 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16006 static_cast<void>(j);
16007 }
16008
16009 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16010 }
16011
16015 void write_bson_entry_header(const string_t& name,
16016 const std::uint8_t element_type)
16017 {
16018 oa->write_character(to_char_type(element_type)); // boolean
16019 oa->write_characters(
16020 reinterpret_cast<const CharType*>(name.c_str()),
16021 name.size() + 1u);
16022 }
16023
16027 void write_bson_boolean(const string_t& name,
16028 const bool value)
16029 {
16030 write_bson_entry_header(name, 0x08);
16031 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16032 }
16033
16037 void write_bson_double(const string_t& name,
16038 const double value)
16039 {
16040 write_bson_entry_header(name, 0x01);
16041 write_number<double>(value, true);
16042 }
16043
16047 static std::size_t calc_bson_string_size(const string_t& value)
16048 {
16049 return sizeof(std::int32_t) + value.size() + 1ul;
16050 }
16051
16055 void write_bson_string(const string_t& name,
16056 const string_t& value)
16057 {
16058 write_bson_entry_header(name, 0x02);
16059
16060 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16061 oa->write_characters(
16062 reinterpret_cast<const CharType*>(value.c_str()),
16063 value.size() + 1);
16064 }
16065
16069 void write_bson_null(const string_t& name)
16070 {
16071 write_bson_entry_header(name, 0x0A);
16072 }
16073
16077 static std::size_t calc_bson_integer_size(const std::int64_t value)
16078 {
16079 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16080 ? sizeof(std::int32_t)
16081 : sizeof(std::int64_t);
16082 }
16083
16087 void write_bson_integer(const string_t& name,
16088 const std::int64_t value)
16089 {
16090 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16091 {
16092 write_bson_entry_header(name, 0x10); // int32
16093 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16094 }
16095 else
16096 {
16097 write_bson_entry_header(name, 0x12); // int64
16098 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16099 }
16100 }
16101
16105 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16106 {
16107 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16108 ? sizeof(std::int32_t)
16109 : sizeof(std::int64_t);
16110 }
16111
16115 void write_bson_unsigned(const string_t& name,
16116 const BasicJsonType& j)
16117 {
16118 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16119 {
16120 write_bson_entry_header(name, 0x10 /* int32 */);
16121 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16122 }
16123 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16124 {
16125 write_bson_entry_header(name, 0x12 /* int64 */);
16126 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16127 }
16128 else
16129 {
16130 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));
16131 }
16132 }
16133
16137 void write_bson_object_entry(const string_t& name,
16138 const typename BasicJsonType::object_t& value)
16139 {
16140 write_bson_entry_header(name, 0x03); // object
16141 write_bson_object(value);
16142 }
16143
16147 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16148 {
16149 std::size_t array_index = 0ul;
16150
16151 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)
16152 {
16153 return result + calc_bson_element_size(std::to_string(array_index++), el);
16154 });
16155
16156 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16157 }
16158
16162 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16163 {
16164 return sizeof(std::int32_t) + value.size() + 1ul;
16165 }
16166
16170 void write_bson_array(const string_t& name,
16171 const typename BasicJsonType::array_t& value)
16172 {
16173 write_bson_entry_header(name, 0x04); // array
16174 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16175
16176 std::size_t array_index = 0ul;
16177
16178 for (const auto& el : value)
16179 {
16180 write_bson_element(std::to_string(array_index++), el);
16181 }
16182
16183 oa->write_character(to_char_type(0x00));
16184 }
16185
16189 void write_bson_binary(const string_t& name,
16190 const binary_t& value)
16191 {
16192 write_bson_entry_header(name, 0x05);
16193
16194 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16195 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16196
16197 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16198 }
16199
16204 static std::size_t calc_bson_element_size(const string_t& name,
16205 const BasicJsonType& j)
16206 {
16207 const auto header_size = calc_bson_entry_header_size(name, j);
16208 switch (j.type())
16209 {
16210 case value_t::object:
16211 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16212
16213 case value_t::array:
16214 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16215
16216 case value_t::binary:
16217 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16218
16219 case value_t::boolean:
16220 return header_size + 1ul;
16221
16222 case value_t::number_float:
16223 return header_size + 8ul;
16224
16225 case value_t::number_integer:
16226 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16227
16228 case value_t::number_unsigned:
16229 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16230
16231 case value_t::string:
16232 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16233
16234 case value_t::null:
16235 return header_size + 0ul;
16236
16237 // LCOV_EXCL_START
16238 case value_t::discarded:
16239 default:
16240 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16241 return 0ul;
16242 // LCOV_EXCL_STOP
16243 }
16244 }
16245
16252 void write_bson_element(const string_t& name,
16253 const BasicJsonType& j)
16254 {
16255 switch (j.type())
16256 {
16257 case value_t::object:
16258 return write_bson_object_entry(name, *j.m_data.m_value.object);
16259
16260 case value_t::array:
16261 return write_bson_array(name, *j.m_data.m_value.array);
16262
16263 case value_t::binary:
16264 return write_bson_binary(name, *j.m_data.m_value.binary);
16265
16266 case value_t::boolean:
16267 return write_bson_boolean(name, j.m_data.m_value.boolean);
16268
16269 case value_t::number_float:
16270 return write_bson_double(name, j.m_data.m_value.number_float);
16271
16272 case value_t::number_integer:
16273 return write_bson_integer(name, j.m_data.m_value.number_integer);
16274
16275 case value_t::number_unsigned:
16276 return write_bson_unsigned(name, j);
16277
16278 case value_t::string:
16279 return write_bson_string(name, *j.m_data.m_value.string);
16280
16281 case value_t::null:
16282 return write_bson_null(name);
16283
16284 // LCOV_EXCL_START
16285 case value_t::discarded:
16286 default:
16287 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16288 return;
16289 // LCOV_EXCL_STOP
16290 }
16291 }
16292
16299 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
16300 {
16301 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
16302 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
16303 {
16304 return result += calc_bson_element_size(el.first, el.second);
16305 });
16306
16307 return sizeof(std::int32_t) + document_size + 1ul;
16308 }
16309
16314 void write_bson_object(const typename BasicJsonType::object_t& value)
16315 {
16316 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
16317
16318 for (const auto& el : value)
16319 {
16320 write_bson_element(el.first, el.second);
16321 }
16322
16323 oa->write_character(to_char_type(0x00));
16324 }
16325
16327 // CBOR //
16329
16330 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
16331 {
16332 return to_char_type(0xFA); // Single-Precision Float
16333 }
16334
16335 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
16336 {
16337 return to_char_type(0xFB); // Double-Precision Float
16338 }
16339
16341 // MsgPack //
16343
16344 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
16345 {
16346 return to_char_type(0xCA); // float 32
16347 }
16348
16349 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
16350 {
16351 return to_char_type(0xCB); // float 64
16352 }
16353
16355 // UBJSON //
16357
16358 // UBJSON: write number (floating point)
16359 template<typename NumberType, typename std::enable_if<
16360 std::is_floating_point<NumberType>::value, int>::type = 0>
16361 void write_number_with_ubjson_prefix(const NumberType n,
16362 const bool add_prefix,
16363 const bool use_bjdata)
16364 {
16365 if (add_prefix)
16366 {
16367 oa->write_character(get_ubjson_float_prefix(n));
16368 }
16369 write_number(n, use_bjdata);
16370 }
16371
16372 // UBJSON: write number (unsigned integer)
16373 template<typename NumberType, typename std::enable_if<
16374 std::is_unsigned<NumberType>::value, int>::type = 0>
16375 void write_number_with_ubjson_prefix(const NumberType n,
16376 const bool add_prefix,
16377 const bool use_bjdata)
16378 {
16379 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16380 {
16381 if (add_prefix)
16382 {
16383 oa->write_character(to_char_type('i')); // int8
16384 }
16385 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16386 }
16387 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
16388 {
16389 if (add_prefix)
16390 {
16391 oa->write_character(to_char_type('U')); // uint8
16392 }
16393 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16394 }
16395 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16396 {
16397 if (add_prefix)
16398 {
16399 oa->write_character(to_char_type('I')); // int16
16400 }
16401 write_number(static_cast<std::int16_t>(n), use_bjdata);
16402 }
16403 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
16404 {
16405 if (add_prefix)
16406 {
16407 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16408 }
16409 write_number(static_cast<std::uint16_t>(n), use_bjdata);
16410 }
16411 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16412 {
16413 if (add_prefix)
16414 {
16415 oa->write_character(to_char_type('l')); // int32
16416 }
16417 write_number(static_cast<std::int32_t>(n), use_bjdata);
16418 }
16419 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
16420 {
16421 if (add_prefix)
16422 {
16423 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16424 }
16425 write_number(static_cast<std::uint32_t>(n), use_bjdata);
16426 }
16427 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16428 {
16429 if (add_prefix)
16430 {
16431 oa->write_character(to_char_type('L')); // int64
16432 }
16433 write_number(static_cast<std::int64_t>(n), use_bjdata);
16434 }
16435 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
16436 {
16437 if (add_prefix)
16438 {
16439 oa->write_character(to_char_type('M')); // uint64 - bjdata only
16440 }
16441 write_number(static_cast<std::uint64_t>(n), use_bjdata);
16442 }
16443 else
16444 {
16445 if (add_prefix)
16446 {
16447 oa->write_character(to_char_type('H')); // high-precision number
16448 }
16449
16450 const auto number = BasicJsonType(n).dump();
16451 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16452 for (std::size_t i = 0; i < number.size(); ++i)
16453 {
16454 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16455 }
16456 }
16457 }
16458
16459 // UBJSON: write number (signed integer)
16460 template < typename NumberType, typename std::enable_if <
16461 std::is_signed<NumberType>::value&&
16462 !std::is_floating_point<NumberType>::value, int >::type = 0 >
16463 void write_number_with_ubjson_prefix(const NumberType n,
16464 const bool add_prefix,
16465 const bool use_bjdata)
16466 {
16467 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
16468 {
16469 if (add_prefix)
16470 {
16471 oa->write_character(to_char_type('i')); // int8
16472 }
16473 write_number(static_cast<std::int8_t>(n), use_bjdata);
16474 }
16475 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)()))
16476 {
16477 if (add_prefix)
16478 {
16479 oa->write_character(to_char_type('U')); // uint8
16480 }
16481 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16482 }
16483 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
16484 {
16485 if (add_prefix)
16486 {
16487 oa->write_character(to_char_type('I')); // int16
16488 }
16489 write_number(static_cast<std::int16_t>(n), use_bjdata);
16490 }
16491 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)())))
16492 {
16493 if (add_prefix)
16494 {
16495 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16496 }
16497 write_number(static_cast<uint16_t>(n), use_bjdata);
16498 }
16499 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
16500 {
16501 if (add_prefix)
16502 {
16503 oa->write_character(to_char_type('l')); // int32
16504 }
16505 write_number(static_cast<std::int32_t>(n), use_bjdata);
16506 }
16507 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)())))
16508 {
16509 if (add_prefix)
16510 {
16511 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16512 }
16513 write_number(static_cast<uint32_t>(n), use_bjdata);
16514 }
16515 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
16516 {
16517 if (add_prefix)
16518 {
16519 oa->write_character(to_char_type('L')); // int64
16520 }
16521 write_number(static_cast<std::int64_t>(n), use_bjdata);
16522 }
16523 // LCOV_EXCL_START
16524 else
16525 {
16526 if (add_prefix)
16527 {
16528 oa->write_character(to_char_type('H')); // high-precision number
16529 }
16530
16531 const auto number = BasicJsonType(n).dump();
16532 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16533 for (std::size_t i = 0; i < number.size(); ++i)
16534 {
16535 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16536 }
16537 }
16538 // LCOV_EXCL_STOP
16539 }
16540
16544 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
16545 {
16546 switch (j.type())
16547 {
16548 case value_t::null:
16549 return 'Z';
16550
16551 case value_t::boolean:
16552 return j.m_data.m_value.boolean ? 'T' : 'F';
16553
16554 case value_t::number_integer:
16555 {
16556 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)())
16557 {
16558 return 'i';
16559 }
16560 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)())
16561 {
16562 return 'U';
16563 }
16564 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)())
16565 {
16566 return 'I';
16567 }
16568 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)()))
16569 {
16570 return 'u';
16571 }
16572 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)())
16573 {
16574 return 'l';
16575 }
16576 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)()))
16577 {
16578 return 'm';
16579 }
16580 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)())
16581 {
16582 return 'L';
16583 }
16584 // anything else is treated as high-precision number
16585 return 'H'; // LCOV_EXCL_LINE
16586 }
16587
16588 case value_t::number_unsigned:
16589 {
16590 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16591 {
16592 return 'i';
16593 }
16594 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
16595 {
16596 return 'U';
16597 }
16598 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16599 {
16600 return 'I';
16601 }
16602 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
16603 {
16604 return 'u';
16605 }
16606 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16607 {
16608 return 'l';
16609 }
16610 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
16611 {
16612 return 'm';
16613 }
16614 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16615 {
16616 return 'L';
16617 }
16618 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16619 {
16620 return 'M';
16621 }
16622 // anything else is treated as high-precision number
16623 return 'H'; // LCOV_EXCL_LINE
16624 }
16625
16626 case value_t::number_float:
16627 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
16628
16629 case value_t::string:
16630 return 'S';
16631
16632 case value_t::array: // fallthrough
16633 case value_t::binary:
16634 return '[';
16635
16636 case value_t::object:
16637 return '{';
16638
16639 case value_t::discarded:
16640 default: // discarded values
16641 return 'N';
16642 }
16643 }
16644
16645 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
16646 {
16647 return 'd'; // float 32
16648 }
16649
16650 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
16651 {
16652 return 'D'; // float 64
16653 }
16654
16658 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
16659 {
16660 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
16661 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
16662 };
16663
16664 string_t key = "_ArrayType_";
16665 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
16666 if (it == bjdtype.end())
16667 {
16668 return true;
16669 }
16670 CharType dtype = it->second;
16671
16672 key = "_ArraySize_";
16673 std::size_t len = (value.at(key).empty() ? 0 : 1);
16674 for (const auto& el : value.at(key))
16675 {
16676 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
16677 }
16678
16679 key = "_ArrayData_";
16680 if (value.at(key).size() != len)
16681 {
16682 return true;
16683 }
16684
16685 oa->write_character('[');
16686 oa->write_character('$');
16687 oa->write_character(dtype);
16688 oa->write_character('#');
16689
16690 key = "_ArraySize_";
16691 write_ubjson(value.at(key), use_count, use_type, true, true);
16692
16693 key = "_ArrayData_";
16694 if (dtype == 'U' || dtype == 'C')
16695 {
16696 for (const auto& el : value.at(key))
16697 {
16698 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
16699 }
16700 }
16701 else if (dtype == 'i')
16702 {
16703 for (const auto& el : value.at(key))
16704 {
16705 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
16706 }
16707 }
16708 else if (dtype == 'u')
16709 {
16710 for (const auto& el : value.at(key))
16711 {
16712 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
16713 }
16714 }
16715 else if (dtype == 'I')
16716 {
16717 for (const auto& el : value.at(key))
16718 {
16719 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
16720 }
16721 }
16722 else if (dtype == 'm')
16723 {
16724 for (const auto& el : value.at(key))
16725 {
16726 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
16727 }
16728 }
16729 else if (dtype == 'l')
16730 {
16731 for (const auto& el : value.at(key))
16732 {
16733 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
16734 }
16735 }
16736 else if (dtype == 'M')
16737 {
16738 for (const auto& el : value.at(key))
16739 {
16740 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
16741 }
16742 }
16743 else if (dtype == 'L')
16744 {
16745 for (const auto& el : value.at(key))
16746 {
16747 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
16748 }
16749 }
16750 else if (dtype == 'd')
16751 {
16752 for (const auto& el : value.at(key))
16753 {
16754 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
16755 }
16756 }
16757 else if (dtype == 'D')
16758 {
16759 for (const auto& el : value.at(key))
16760 {
16761 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
16762 }
16763 }
16764 return false;
16765 }
16766
16768 // Utility functions //
16770
16771 /*
16772 @brief write a number to output input
16773 @param[in] n number of type @a NumberType
16774 @param[in] OutputIsLittleEndian Set to true if output data is
16775 required to be little endian
16776 @tparam NumberType the type of the number
16777
16778 @note This function needs to respect the system's endianness, because bytes
16779 in CBOR, MessagePack, and UBJSON are stored in network order (big
16780 endian) and therefore need reordering on little endian systems.
16781 On the other hand, BSON and BJData use little endian and should reorder
16782 on big endian systems.
16783 */
16784 template<typename NumberType>
16785 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
16786 {
16787 // step 1: write number to array of length NumberType
16788 std::array<CharType, sizeof(NumberType)> vec{};
16789 std::memcpy(vec.data(), &n, sizeof(NumberType));
16790
16791 // step 2: write array to output (with possible reordering)
16792 if (is_little_endian != OutputIsLittleEndian)
16793 {
16794 // reverse byte order prior to conversion if necessary
16795 std::reverse(vec.begin(), vec.end());
16796 }
16797
16798 oa->write_characters(vec.data(), sizeof(NumberType));
16799 }
16800
16801 void write_compact_float(const number_float_t n, detail::input_format_t format)
16802 {
16803#ifdef __GNUC__
16804#pragma GCC diagnostic push
16805#pragma GCC diagnostic ignored "-Wfloat-equal"
16806#endif
16807 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
16808 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
16809 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
16810 {
16811 oa->write_character(format == detail::input_format_t::cbor
16812 ? get_cbor_float_prefix(static_cast<float>(n))
16813 : get_msgpack_float_prefix(static_cast<float>(n)));
16814 write_number(static_cast<float>(n));
16815 }
16816 else
16817 {
16818 oa->write_character(format == detail::input_format_t::cbor
16819 ? get_cbor_float_prefix(n)
16820 : get_msgpack_float_prefix(n));
16821 write_number(n);
16822 }
16823#ifdef __GNUC__
16824#pragma GCC diagnostic pop
16825#endif
16826 }
16827
16828 public:
16829 // The following to_char_type functions are implement the conversion
16830 // between uint8_t and CharType. In case CharType is not unsigned,
16831 // such a conversion is required to allow values greater than 128.
16832 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
16833 template < typename C = CharType,
16834 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
16835 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16836 {
16837 return *reinterpret_cast<char*>(&x);
16838 }
16839
16840 template < typename C = CharType,
16841 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
16842 static CharType to_char_type(std::uint8_t x) noexcept
16843 {
16844 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
16845 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
16846 CharType result;
16847 std::memcpy(&result, &x, sizeof(x));
16848 return result;
16849 }
16850
16851 template<typename C = CharType,
16852 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
16853 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16854 {
16855 return x;
16856 }
16857
16858 template < typename InputCharType, typename C = CharType,
16859 enable_if_t <
16860 std::is_signed<C>::value &&
16861 std::is_signed<char>::value &&
16862 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
16863 > * = nullptr >
16864 static constexpr CharType to_char_type(InputCharType x) noexcept
16865 {
16866 return x;
16867 }
16868
16869 private:
16871 const bool is_little_endian = little_endianness();
16872
16874 output_adapter_t<CharType> oa = nullptr;
16875};
16876
16877} // namespace detail
16878NLOHMANN_JSON_NAMESPACE_END
16879
16880// #include <nlohmann/detail/output/output_adapters.hpp>
16881
16882// #include <nlohmann/detail/output/serializer.hpp>
16883// __ _____ _____ _____
16884// __| | __| | | | JSON for Modern C++
16885// | | |__ | | | | | | version 3.11.3
16886// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16887//
16888// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de>
16889// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
16890// SPDX-License-Identifier: MIT
16891
16892
16893
16894#include <algorithm> // reverse, remove, fill, find, none_of
16895#include <array> // array
16896#include <clocale> // localeconv, lconv
16897#include <cmath> // labs, isfinite, isnan, signbit
16898#include <cstddef> // size_t, ptrdiff_t
16899#include <cstdint> // uint8_t
16900#include <cstdio> // snprintf
16901#include <limits> // numeric_limits
16902#include <string> // string, char_traits
16903#include <iomanip> // setfill, setw
16904#include <type_traits> // is_same
16905#include <utility> // move
16906
16907// #include <nlohmann/detail/conversions/to_chars.hpp>
16908// __ _____ _____ _____
16909// __| | __| | | | JSON for Modern C++
16910// | | |__ | | | | | | version 3.11.3
16911// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16912//
16913// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
16914// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
16915// SPDX-License-Identifier: MIT
16916
16917
16918
16919#include <array> // array
16920#include <cmath> // signbit, isfinite
16921#include <cstdint> // intN_t, uintN_t
16922#include <cstring> // memcpy, memmove
16923#include <limits> // numeric_limits
16924#include <type_traits> // conditional
16925
16926// #include <nlohmann/detail/macro_scope.hpp>
16927
16928
16929NLOHMANN_JSON_NAMESPACE_BEGIN
16930namespace detail
16931{
16932
16952namespace dtoa_impl
16953{
16954
16955template<typename Target, typename Source>
16956Target reinterpret_bits(const Source source)
16957{
16958 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
16959
16960 Target target;
16961 std::memcpy(&target, &source, sizeof(Source));
16962 return target;
16963}
16964
16965struct diyfp // f * 2^e
16966{
16967 static constexpr int kPrecision = 64; // = q
16968
16969 std::uint64_t f = 0;
16970 int e = 0;
16971
16972 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
16973
16978 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
16979 {
16980 JSON_ASSERT(x.e == y.e);
16981 JSON_ASSERT(x.f >= y.f);
16982
16983 return {x.f - y.f, x.e};
16984 }
16985
16990 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
16991 {
16992 static_assert(kPrecision == 64, "internal error");
16993
16994 // Computes:
16995 // f = round((x.f * y.f) / 2^q)
16996 // e = x.e + y.e + q
16997
16998 // Emulate the 64-bit * 64-bit multiplication:
16999 //
17000 // p = u * v
17001 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17002 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17003 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17004 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17005 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17006 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17007 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17008 //
17009 // (Since Q might be larger than 2^32 - 1)
17010 //
17011 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17012 //
17013 // (Q_hi + H does not overflow a 64-bit int)
17014 //
17015 // = p_lo + 2^64 p_hi
17016
17017 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17018 const std::uint64_t u_hi = x.f >> 32u;
17019 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17020 const std::uint64_t v_hi = y.f >> 32u;
17021
17022 const std::uint64_t p0 = u_lo * v_lo;
17023 const std::uint64_t p1 = u_lo * v_hi;
17024 const std::uint64_t p2 = u_hi * v_lo;
17025 const std::uint64_t p3 = u_hi * v_hi;
17026
17027 const std::uint64_t p0_hi = p0 >> 32u;
17028 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17029 const std::uint64_t p1_hi = p1 >> 32u;
17030 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17031 const std::uint64_t p2_hi = p2 >> 32u;
17032
17033 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17034
17035 // The full product might now be computed as
17036 //
17037 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17038 // p_lo = p0_lo + (Q << 32)
17039 //
17040 // But in this particular case here, the full p_lo is not required.
17041 // Effectively we only need to add the highest bit in p_lo to p_hi (and
17042 // Q_hi + 1 does not overflow).
17043
17044 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17045
17046 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17047
17048 return {h, x.e + y.e + 64};
17049 }
17050
17055 static diyfp normalize(diyfp x) noexcept
17056 {
17057 JSON_ASSERT(x.f != 0);
17058
17059 while ((x.f >> 63u) == 0)
17060 {
17061 x.f <<= 1u;
17062 x.e--;
17063 }
17064
17065 return x;
17066 }
17067
17072 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17073 {
17074 const int delta = x.e - target_exponent;
17075
17076 JSON_ASSERT(delta >= 0);
17077 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17078
17079 return {x.f << delta, target_exponent};
17080 }
17081};
17082
17083struct boundaries
17084{
17085 diyfp w;
17086 diyfp minus;
17087 diyfp plus;
17088};
17089
17096template<typename FloatType>
17098{
17099 JSON_ASSERT(std::isfinite(value));
17100 JSON_ASSERT(value > 0);
17101
17102 // Convert the IEEE representation into a diyfp.
17103 //
17104 // If v is denormal:
17105 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17106 // If v is normalized:
17107 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17108
17109 static_assert(std::numeric_limits<FloatType>::is_iec559,
17110 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17111
17112 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17113 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17114 constexpr int kMinExp = 1 - kBias;
17115 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17116
17117 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17118
17119 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17120 const std::uint64_t E = bits >> (kPrecision - 1);
17121 const std::uint64_t F = bits & (kHiddenBit - 1);
17122
17123 const bool is_denormal = E == 0;
17124 const diyfp v = is_denormal
17125 ? diyfp(F, kMinExp)
17126 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17127
17128 // Compute the boundaries m- and m+ of the floating-point value
17129 // v = f * 2^e.
17130 //
17131 // Determine v- and v+, the floating-point predecessor and successor if v,
17132 // respectively.
17133 //
17134 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17135 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17136 //
17137 // v+ = v + 2^e
17138 //
17139 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17140 // between m- and m+ round to v, regardless of how the input rounding
17141 // algorithm breaks ties.
17142 //
17143 // ---+-------------+-------------+-------------+-------------+--- (A)
17144 // v- m- v m+ v+
17145 //
17146 // -----------------+------+------+-------------+-------------+--- (B)
17147 // v- m- v m+ v+
17148
17149 const bool lower_boundary_is_closer = F == 0 && E > 1;
17150 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
17151 const diyfp m_minus = lower_boundary_is_closer
17152 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
17153 : diyfp(2 * v.f - 1, v.e - 1); // (A)
17154
17155 // Determine the normalized w+ = m+.
17156 const diyfp w_plus = diyfp::normalize(m_plus);
17157
17158 // Determine w- = m- such that e_(w-) = e_(w+).
17159 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17160
17161 return {diyfp::normalize(v), w_minus, w_plus};
17162}
17163
17164// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17165// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17166// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17167//
17168// alpha <= e = e_c + e_w + q <= gamma
17169//
17170// or
17171//
17172// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17173// <= f_c * f_w * 2^gamma
17174//
17175// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17176//
17177// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17178//
17179// or
17180//
17181// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17182//
17183// The choice of (alpha,gamma) determines the size of the table and the form of
17184// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17185// in practice:
17186//
17187// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17188// processed independently: An integral part p1, and a fractional part p2:
17189//
17190// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17191// = (f div 2^-e) + (f mod 2^-e) * 2^e
17192// = p1 + p2 * 2^e
17193//
17194// The conversion of p1 into decimal form requires a series of divisions and
17195// modulos by (a power of) 10. These operations are faster for 32-bit than for
17196// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17197// achieved by choosing
17198//
17199// -e >= 32 or e <= -32 := gamma
17200//
17201// In order to convert the fractional part
17202//
17203// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17204//
17205// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17206// d[-i] are extracted in order:
17207//
17208// (10 * p2) div 2^-e = d[-1]
17209// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17210//
17211// The multiplication by 10 must not overflow. It is sufficient to choose
17212//
17213// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17214//
17215// Since p2 = f mod 2^-e < 2^-e,
17216//
17217// -e <= 60 or e >= -60 := alpha
17218
17219constexpr int kAlpha = -60;
17220constexpr int kGamma = -32;
17221
17222struct cached_power // c = f * 2^e ~= 10^k
17223{
17224 std::uint64_t f;
17225 int e;
17226 int k;
17227};
17228
17237{
17238 // Now
17239 //
17240 // alpha <= e_c + e + q <= gamma (1)
17241 // ==> f_c * 2^alpha <= c * 2^e * 2^q
17242 //
17243 // and since the c's are normalized, 2^(q-1) <= f_c,
17244 //
17245 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
17246 // ==> 2^(alpha - e - 1) <= c
17247 //
17248 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
17249 //
17250 // k = ceil( log_10( 2^(alpha - e - 1) ) )
17251 // = ceil( (alpha - e - 1) * log_10(2) )
17252 //
17253 // From the paper:
17254 // "In theory the result of the procedure could be wrong since c is rounded,
17255 // and the computation itself is approximated [...]. In practice, however,
17256 // this simple function is sufficient."
17257 //
17258 // For IEEE double precision floating-point numbers converted into
17259 // normalized diyfp's w = f * 2^e, with q = 64,
17260 //
17261 // e >= -1022 (min IEEE exponent)
17262 // -52 (p - 1)
17263 // -52 (p - 1, possibly normalize denormal IEEE numbers)
17264 // -11 (normalize the diyfp)
17265 // = -1137
17266 //
17267 // and
17268 //
17269 // e <= +1023 (max IEEE exponent)
17270 // -52 (p - 1)
17271 // -11 (normalize the diyfp)
17272 // = 960
17273 //
17274 // This binary exponent range [-1137,960] results in a decimal exponent
17275 // range [-307,324]. One does not need to store a cached power for each
17276 // k in this range. For each such k it suffices to find a cached power
17277 // such that the exponent of the product lies in [alpha,gamma].
17278 // This implies that the difference of the decimal exponents of adjacent
17279 // table entries must be less than or equal to
17280 //
17281 // floor( (gamma - alpha) * log_10(2) ) = 8.
17282 //
17283 // (A smaller distance gamma-alpha would require a larger table.)
17284
17285 // NB:
17286 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
17287
17288 constexpr int kCachedPowersMinDecExp = -300;
17289 constexpr int kCachedPowersDecStep = 8;
17290
17291 static constexpr std::array<cached_power, 79> kCachedPowers =
17292 {
17293 {
17294 { 0xAB70FE17C79AC6CA, -1060, -300 },
17295 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
17296 { 0xBE5691EF416BD60C, -1007, -284 },
17297 { 0x8DD01FAD907FFC3C, -980, -276 },
17298 { 0xD3515C2831559A83, -954, -268 },
17299 { 0x9D71AC8FADA6C9B5, -927, -260 },
17300 { 0xEA9C227723EE8BCB, -901, -252 },
17301 { 0xAECC49914078536D, -874, -244 },
17302 { 0x823C12795DB6CE57, -847, -236 },
17303 { 0xC21094364DFB5637, -821, -228 },
17304 { 0x9096EA6F3848984F, -794, -220 },
17305 { 0xD77485CB25823AC7, -768, -212 },
17306 { 0xA086CFCD97BF97F4, -741, -204 },
17307 { 0xEF340A98172AACE5, -715, -196 },
17308 { 0xB23867FB2A35B28E, -688, -188 },
17309 { 0x84C8D4DFD2C63F3B, -661, -180 },
17310 { 0xC5DD44271AD3CDBA, -635, -172 },
17311 { 0x936B9FCEBB25C996, -608, -164 },
17312 { 0xDBAC6C247D62A584, -582, -156 },
17313 { 0xA3AB66580D5FDAF6, -555, -148 },
17314 { 0xF3E2F893DEC3F126, -529, -140 },
17315 { 0xB5B5ADA8AAFF80B8, -502, -132 },
17316 { 0x87625F056C7C4A8B, -475, -124 },
17317 { 0xC9BCFF6034C13053, -449, -116 },
17318 { 0x964E858C91BA2655, -422, -108 },
17319 { 0xDFF9772470297EBD, -396, -100 },
17320 { 0xA6DFBD9FB8E5B88F, -369, -92 },
17321 { 0xF8A95FCF88747D94, -343, -84 },
17322 { 0xB94470938FA89BCF, -316, -76 },
17323 { 0x8A08F0F8BF0F156B, -289, -68 },
17324 { 0xCDB02555653131B6, -263, -60 },
17325 { 0x993FE2C6D07B7FAC, -236, -52 },
17326 { 0xE45C10C42A2B3B06, -210, -44 },
17327 { 0xAA242499697392D3, -183, -36 },
17328 { 0xFD87B5F28300CA0E, -157, -28 },
17329 { 0xBCE5086492111AEB, -130, -20 },
17330 { 0x8CBCCC096F5088CC, -103, -12 },
17331 { 0xD1B71758E219652C, -77, -4 },
17332 { 0x9C40000000000000, -50, 4 },
17333 { 0xE8D4A51000000000, -24, 12 },
17334 { 0xAD78EBC5AC620000, 3, 20 },
17335 { 0x813F3978F8940984, 30, 28 },
17336 { 0xC097CE7BC90715B3, 56, 36 },
17337 { 0x8F7E32CE7BEA5C70, 83, 44 },
17338 { 0xD5D238A4ABE98068, 109, 52 },
17339 { 0x9F4F2726179A2245, 136, 60 },
17340 { 0xED63A231D4C4FB27, 162, 68 },
17341 { 0xB0DE65388CC8ADA8, 189, 76 },
17342 { 0x83C7088E1AAB65DB, 216, 84 },
17343 { 0xC45D1DF942711D9A, 242, 92 },
17344 { 0x924D692CA61BE758, 269, 100 },
17345 { 0xDA01EE641A708DEA, 295, 108 },
17346 { 0xA26DA3999AEF774A, 322, 116 },
17347 { 0xF209787BB47D6B85, 348, 124 },
17348 { 0xB454E4A179DD1877, 375, 132 },
17349 { 0x865B86925B9BC5C2, 402, 140 },
17350 { 0xC83553C5C8965D3D, 428, 148 },
17351 { 0x952AB45CFA97A0B3, 455, 156 },
17352 { 0xDE469FBD99A05FE3, 481, 164 },
17353 { 0xA59BC234DB398C25, 508, 172 },
17354 { 0xF6C69A72A3989F5C, 534, 180 },
17355 { 0xB7DCBF5354E9BECE, 561, 188 },
17356 { 0x88FCF317F22241E2, 588, 196 },
17357 { 0xCC20CE9BD35C78A5, 614, 204 },
17358 { 0x98165AF37B2153DF, 641, 212 },
17359 { 0xE2A0B5DC971F303A, 667, 220 },
17360 { 0xA8D9D1535CE3B396, 694, 228 },
17361 { 0xFB9B7CD9A4A7443C, 720, 236 },
17362 { 0xBB764C4CA7A44410, 747, 244 },
17363 { 0x8BAB8EEFB6409C1A, 774, 252 },
17364 { 0xD01FEF10A657842C, 800, 260 },
17365 { 0x9B10A4E5E9913129, 827, 268 },
17366 { 0xE7109BFBA19C0C9D, 853, 276 },
17367 { 0xAC2820D9623BF429, 880, 284 },
17368 { 0x80444B5E7AA7CF85, 907, 292 },
17369 { 0xBF21E44003ACDD2D, 933, 300 },
17370 { 0x8E679C2F5E44FF8F, 960, 308 },
17371 { 0xD433179D9C8CB841, 986, 316 },
17372 { 0x9E19DB92B4E31BA9, 1013, 324 },
17373 }
17374 };
17375
17376 // This computation gives exactly the same results for k as
17377 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
17378 // for |e| <= 1500, but doesn't require floating-point operations.
17379 // NB: log_10(2) ~= 78913 / 2^18
17380 JSON_ASSERT(e >= -1500);
17381 JSON_ASSERT(e <= 1500);
17382 const int f = kAlpha - e - 1;
17383 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
17384
17385 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
17386 JSON_ASSERT(index >= 0);
17387 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
17388
17389 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
17390 JSON_ASSERT(kAlpha <= cached.e + e + 64);
17391 JSON_ASSERT(kGamma >= cached.e + e + 64);
17392
17393 return cached;
17394}
17395
17400inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
17401{
17402 // LCOV_EXCL_START
17403 if (n >= 1000000000)
17404 {
17405 pow10 = 1000000000;
17406 return 10;
17407 }
17408 // LCOV_EXCL_STOP
17409 if (n >= 100000000)
17410 {
17411 pow10 = 100000000;
17412 return 9;
17413 }
17414 if (n >= 10000000)
17415 {
17416 pow10 = 10000000;
17417 return 8;
17418 }
17419 if (n >= 1000000)
17420 {
17421 pow10 = 1000000;
17422 return 7;
17423 }
17424 if (n >= 100000)
17425 {
17426 pow10 = 100000;
17427 return 6;
17428 }
17429 if (n >= 10000)
17430 {
17431 pow10 = 10000;
17432 return 5;
17433 }
17434 if (n >= 1000)
17435 {
17436 pow10 = 1000;
17437 return 4;
17438 }
17439 if (n >= 100)
17440 {
17441 pow10 = 100;
17442 return 3;
17443 }
17444 if (n >= 10)
17445 {
17446 pow10 = 10;
17447 return 2;
17448 }
17449
17450 pow10 = 1;
17451 return 1;
17452}
17453
17454inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
17455 std::uint64_t rest, std::uint64_t ten_k)
17456{
17457 JSON_ASSERT(len >= 1);
17458 JSON_ASSERT(dist <= delta);
17459 JSON_ASSERT(rest <= delta);
17460 JSON_ASSERT(ten_k > 0);
17461
17462 // <--------------------------- delta ---->
17463 // <---- dist --------->
17464 // --------------[------------------+-------------------]--------------
17465 // M- w M+
17466 //
17467 // ten_k
17468 // <------>
17469 // <---- rest ---->
17470 // --------------[------------------+----+--------------]--------------
17471 // w V
17472 // = buf * 10^k
17473 //
17474 // ten_k represents a unit-in-the-last-place in the decimal representation
17475 // stored in buf.
17476 // Decrement buf by ten_k while this takes buf closer to w.
17477
17478 // The tests are written in this order to avoid overflow in unsigned
17479 // integer arithmetic.
17480
17481 while (rest < dist
17482 && delta - rest >= ten_k
17483 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
17484 {
17485 JSON_ASSERT(buf[len - 1] != '0');
17486 buf[len - 1]--;
17487 rest += ten_k;
17488 }
17489}
17490
17495inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
17496 diyfp M_minus, diyfp w, diyfp M_plus)
17497{
17498 static_assert(kAlpha >= -60, "internal error");
17499 static_assert(kGamma <= -32, "internal error");
17500
17501 // Generates the digits (and the exponent) of a decimal floating-point
17502 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
17503 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
17504 //
17505 // <--------------------------- delta ---->
17506 // <---- dist --------->
17507 // --------------[------------------+-------------------]--------------
17508 // M- w M+
17509 //
17510 // Grisu2 generates the digits of M+ from left to right and stops as soon as
17511 // V is in [M-,M+].
17512
17513 JSON_ASSERT(M_plus.e >= kAlpha);
17514 JSON_ASSERT(M_plus.e <= kGamma);
17515
17516 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
17517 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
17518
17519 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
17520 //
17521 // M+ = f * 2^e
17522 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
17523 // = ((p1 ) * 2^-e + (p2 )) * 2^e
17524 // = p1 + p2 * 2^e
17525
17526 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
17527
17528 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.)
17529 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
17530
17531 // 1)
17532 //
17533 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
17534
17535 JSON_ASSERT(p1 > 0);
17536
17537 std::uint32_t pow10{};
17538 const int k = find_largest_pow10(p1, pow10);
17539
17540 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
17541 //
17542 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
17543 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
17544 //
17545 // M+ = p1 + p2 * 2^e
17546 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
17547 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
17548 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
17549 //
17550 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
17551 //
17552 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
17553 //
17554 // but stop as soon as
17555 //
17556 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
17557
17558 int n = k;
17559 while (n > 0)
17560 {
17561 // Invariants:
17562 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
17563 // pow10 = 10^(n-1) <= p1 < 10^n
17564 //
17565 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
17566 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
17567 //
17568 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
17569 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
17570 //
17571 JSON_ASSERT(d <= 9);
17572 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17573 //
17574 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
17575 //
17576 p1 = r;
17577 n--;
17578 //
17579 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
17580 // pow10 = 10^n
17581 //
17582
17583 // Now check if enough digits have been generated.
17584 // Compute
17585 //
17586 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
17587 //
17588 // Note:
17589 // Since rest and delta share the same exponent e, it suffices to
17590 // compare the significands.
17591 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
17592 if (rest <= delta)
17593 {
17594 // V = buffer * 10^n, with M- <= V <= M+.
17595
17596 decimal_exponent += n;
17597
17598 // We may now just stop. But instead look if the buffer could be
17599 // decremented to bring V closer to w.
17600 //
17601 // pow10 = 10^n is now 1 ulp in the decimal representation V.
17602 // The rounding procedure works with diyfp's with an implicit
17603 // exponent of e.
17604 //
17605 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
17606 //
17607 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
17608 grisu2_round(buffer, length, dist, delta, rest, ten_n);
17609
17610 return;
17611 }
17612
17613 pow10 /= 10;
17614 //
17615 // pow10 = 10^(n-1) <= p1 < 10^n
17616 // Invariants restored.
17617 }
17618
17619 // 2)
17620 //
17621 // The digits of the integral part have been generated:
17622 //
17623 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
17624 // = buffer + p2 * 2^e
17625 //
17626 // Now generate the digits of the fractional part p2 * 2^e.
17627 //
17628 // Note:
17629 // No decimal point is generated: the exponent is adjusted instead.
17630 //
17631 // p2 actually represents the fraction
17632 //
17633 // p2 * 2^e
17634 // = p2 / 2^-e
17635 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
17636 //
17637 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
17638 //
17639 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
17640 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
17641 //
17642 // using
17643 //
17644 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
17645 // = ( d) * 2^-e + ( r)
17646 //
17647 // or
17648 // 10^m * p2 * 2^e = d + r * 2^e
17649 //
17650 // i.e.
17651 //
17652 // M+ = buffer + p2 * 2^e
17653 // = buffer + 10^-m * (d + r * 2^e)
17654 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
17655 //
17656 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
17657
17658 JSON_ASSERT(p2 > delta);
17659
17660 int m = 0;
17661 for (;;)
17662 {
17663 // Invariant:
17664 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
17665 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
17666 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
17667 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
17668 //
17669 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
17670 p2 *= 10;
17671 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
17672 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
17673 //
17674 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
17675 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
17676 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
17677 //
17678 JSON_ASSERT(d <= 9);
17679 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17680 //
17681 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
17682 //
17683 p2 = r;
17684 m++;
17685 //
17686 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
17687 // Invariant restored.
17688
17689 // Check if enough digits have been generated.
17690 //
17691 // 10^-m * p2 * 2^e <= delta * 2^e
17692 // p2 * 2^e <= 10^m * delta * 2^e
17693 // p2 <= 10^m * delta
17694 delta *= 10;
17695 dist *= 10;
17696 if (p2 <= delta)
17697 {
17698 break;
17699 }
17700 }
17701
17702 // V = buffer * 10^-m, with M- <= V <= M+.
17703
17704 decimal_exponent -= m;
17705
17706 // 1 ulp in the decimal representation is now 10^-m.
17707 // Since delta and dist are now scaled by 10^m, we need to do the
17708 // same with ulp in order to keep the units in sync.
17709 //
17710 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
17711 //
17712 const std::uint64_t ten_m = one.f;
17713 grisu2_round(buffer, length, dist, delta, p2, ten_m);
17714
17715 // By construction this algorithm generates the shortest possible decimal
17716 // number (Loitsch, Theorem 6.2) which rounds back to w.
17717 // For an input number of precision p, at least
17718 //
17719 // N = 1 + ceil(p * log_10(2))
17720 //
17721 // decimal digits are sufficient to identify all binary floating-point
17722 // numbers (Matula, "In-and-Out conversions").
17723 // This implies that the algorithm does not produce more than N decimal
17724 // digits.
17725 //
17726 // N = 17 for p = 53 (IEEE double precision)
17727 // N = 9 for p = 24 (IEEE single precision)
17728}
17729
17735JSON_HEDLEY_NON_NULL(1)
17736inline void grisu2(char* buf, int& len, int& decimal_exponent,
17737 diyfp m_minus, diyfp v, diyfp m_plus)
17738{
17739 JSON_ASSERT(m_plus.e == m_minus.e);
17740 JSON_ASSERT(m_plus.e == v.e);
17741
17742 // --------(-----------------------+-----------------------)-------- (A)
17743 // m- v m+
17744 //
17745 // --------------------(-----------+-----------------------)-------- (B)
17746 // m- v m+
17747 //
17748 // First scale v (and m- and m+) such that the exponent is in the range
17749 // [alpha, gamma].
17750
17751 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
17752
17753 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
17754
17755 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
17756 const diyfp w = diyfp::mul(v, c_minus_k);
17757 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17758 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
17759
17760 // ----(---+---)---------------(---+---)---------------(---+---)----
17761 // w- w w+
17762 // = c*m- = c*v = c*m+
17763 //
17764 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
17765 // w+ are now off by a small amount.
17766 // In fact:
17767 //
17768 // w - v * 10^k < 1 ulp
17769 //
17770 // To account for this inaccuracy, add resp. subtract 1 ulp.
17771 //
17772 // --------+---[---------------(---+---)---------------]---+--------
17773 // w- M- w M+ w+
17774 //
17775 // Now any number in [M-, M+] (bounds included) will round to w when input,
17776 // regardless of how the input rounding algorithm breaks ties.
17777 //
17778 // And digit_gen generates the shortest possible such number in [M-, M+].
17779 // Note that this does not mean that Grisu2 always generates the shortest
17780 // possible number in the interval (m-, m+).
17781 const diyfp M_minus(w_minus.f + 1, w_minus.e);
17782 const diyfp M_plus (w_plus.f - 1, w_plus.e );
17783
17784 decimal_exponent = -cached.k; // = -(-k) = k
17785
17786 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
17787}
17788
17794template<typename FloatType>
17795JSON_HEDLEY_NON_NULL(1)
17796void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
17797{
17798 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17799 "internal error: not enough precision");
17800
17801 JSON_ASSERT(std::isfinite(value));
17802 JSON_ASSERT(value > 0);
17803
17804 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
17805 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
17806 // decimal representations are not exactly "short".
17807 //
17808 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
17809 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
17810 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
17811 // does.
17812 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
17813 // representation using the corresponding std::from_chars function recovers value exactly". That
17814 // indicates that single precision floating-point numbers should be recovered using
17815 // 'std::strtof'.
17816 //
17817 // NB: If the neighbors are computed for single-precision numbers, there is a single float
17818 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
17819 // value is off by 1 ulp.
17820#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
17821 const boundaries w = compute_boundaries(static_cast<double>(value));
17822#else
17823 const boundaries w = compute_boundaries(value);
17824#endif
17825
17826 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
17827}
17828
17834JSON_HEDLEY_NON_NULL(1)
17835JSON_HEDLEY_RETURNS_NON_NULL
17836inline char* append_exponent(char* buf, int e)
17837{
17838 JSON_ASSERT(e > -1000);
17839 JSON_ASSERT(e < 1000);
17840
17841 if (e < 0)
17842 {
17843 e = -e;
17844 *buf++ = '-';
17845 }
17846 else
17847 {
17848 *buf++ = '+';
17849 }
17850
17851 auto k = static_cast<std::uint32_t>(e);
17852 if (k < 10)
17853 {
17854 // Always print at least two digits in the exponent.
17855 // This is for compatibility with printf("%g").
17856 *buf++ = '0';
17857 *buf++ = static_cast<char>('0' + k);
17858 }
17859 else if (k < 100)
17860 {
17861 *buf++ = static_cast<char>('0' + k / 10);
17862 k %= 10;
17863 *buf++ = static_cast<char>('0' + k);
17864 }
17865 else
17866 {
17867 *buf++ = static_cast<char>('0' + k / 100);
17868 k %= 100;
17869 *buf++ = static_cast<char>('0' + k / 10);
17870 k %= 10;
17871 *buf++ = static_cast<char>('0' + k);
17872 }
17873
17874 return buf;
17875}
17876
17886JSON_HEDLEY_NON_NULL(1)
17887JSON_HEDLEY_RETURNS_NON_NULL
17888inline char* format_buffer(char* buf, int len, int decimal_exponent,
17889 int min_exp, int max_exp)
17890{
17891 JSON_ASSERT(min_exp < 0);
17892 JSON_ASSERT(max_exp > 0);
17893
17894 const int k = len;
17895 const int n = len + decimal_exponent;
17896
17897 // v = buf * 10^(n-k)
17898 // k is the length of the buffer (number of decimal digits)
17899 // n is the position of the decimal point relative to the start of the buffer.
17900
17901 if (k <= n && n <= max_exp)
17902 {
17903 // digits[000]
17904 // len <= max_exp + 2
17905
17906 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
17907 // Make it look like a floating-point number (#362, #378)
17908 buf[n + 0] = '.';
17909 buf[n + 1] = '0';
17910 return buf + (static_cast<size_t>(n) + 2);
17911 }
17912
17913 if (0 < n && n <= max_exp)
17914 {
17915 // dig.its
17916 // len <= max_digits10 + 1
17917
17918 JSON_ASSERT(k > n);
17919
17920 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
17921 buf[n] = '.';
17922 return buf + (static_cast<size_t>(k) + 1U);
17923 }
17924
17925 if (min_exp < n && n <= 0)
17926 {
17927 // 0.[000]digits
17928 // len <= 2 + (-min_exp - 1) + max_digits10
17929
17930 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
17931 buf[0] = '0';
17932 buf[1] = '.';
17933 std::memset(buf + 2, '0', static_cast<size_t>(-n));
17934 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
17935 }
17936
17937 if (k == 1)
17938 {
17939 // dE+123
17940 // len <= 1 + 5
17941
17942 buf += 1;
17943 }
17944 else
17945 {
17946 // d.igitsE+123
17947 // len <= max_digits10 + 1 + 5
17948
17949 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
17950 buf[1] = '.';
17951 buf += 1 + static_cast<size_t>(k);
17952 }
17953
17954 *buf++ = 'e';
17955 return append_exponent(buf, n - 1);
17956}
17957
17958} // namespace dtoa_impl
17959
17970template<typename FloatType>
17971JSON_HEDLEY_NON_NULL(1, 2)
17972JSON_HEDLEY_RETURNS_NON_NULL
17973char* to_chars(char* first, const char* last, FloatType value)
17974{
17975 static_cast<void>(last); // maybe unused - fix warning
17976 JSON_ASSERT(std::isfinite(value));
17977
17978 // Use signbit(value) instead of (value < 0) since signbit works for -0.
17979 if (std::signbit(value))
17980 {
17981 value = -value;
17982 *first++ = '-';
17983 }
17984
17985#ifdef __GNUC__
17986#pragma GCC diagnostic push
17987#pragma GCC diagnostic ignored "-Wfloat-equal"
17988#endif
17989 if (value == 0) // +-0
17990 {
17991 *first++ = '0';
17992 // Make it look like a floating-point number (#362, #378)
17993 *first++ = '.';
17994 *first++ = '0';
17995 return first;
17996 }
17997#ifdef __GNUC__
17998#pragma GCC diagnostic pop
17999#endif
18000
18001 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18002
18003 // Compute v = buffer * 10^decimal_exponent.
18004 // The decimal digits are stored in the buffer, which needs to be interpreted
18005 // as an unsigned decimal integer.
18006 // len is the length of the buffer, i.e. the number of decimal digits.
18007 int len = 0;
18008 int decimal_exponent = 0;
18009 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18010
18011 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18012
18013 // Format the buffer like printf("%.*g", prec, value)
18014 constexpr int kMinExp = -4;
18015 // Use digits10 here to increase compatibility with version 2.
18016 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18017
18018 JSON_ASSERT(last - first >= kMaxExp + 2);
18019 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18020 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18021
18022 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18023}
18024
18025} // namespace detail
18026NLOHMANN_JSON_NAMESPACE_END
18027
18028// #include <nlohmann/detail/exceptions.hpp>
18029
18030// #include <nlohmann/detail/macro_scope.hpp>
18031
18032// #include <nlohmann/detail/meta/cpp_future.hpp>
18033
18034// #include <nlohmann/detail/output/binary_writer.hpp>
18035
18036// #include <nlohmann/detail/output/output_adapters.hpp>
18037
18038// #include <nlohmann/detail/string_concat.hpp>
18039
18040// #include <nlohmann/detail/value_t.hpp>
18041
18042
18043NLOHMANN_JSON_NAMESPACE_BEGIN
18044namespace detail
18045{
18046
18048// serialization //
18050
18053{
18054 strict,
18055 replace,
18056 ignore
18057};
18058
18059template<typename BasicJsonType>
18060class serializer
18061{
18062 using string_t = typename BasicJsonType::string_t;
18063 using number_float_t = typename BasicJsonType::number_float_t;
18064 using number_integer_t = typename BasicJsonType::number_integer_t;
18065 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18066 using binary_char_t = typename BasicJsonType::binary_t::value_type;
18067 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18068 static constexpr std::uint8_t UTF8_REJECT = 1;
18069
18070 public:
18078 : o(std::move(s))
18079 , loc(std::localeconv())
18080 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18081 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18082 , indent_char(ichar)
18084 , error_handler(error_handler_)
18085 {}
18086
18087 // delete because of pointer members
18088 serializer(const serializer&) = delete;
18089 serializer& operator=(const serializer&) = delete;
18090 serializer(serializer&&) = delete;
18091 serializer& operator=(serializer&&) = delete;
18092 ~serializer() = default;
18093
18116 void dump(const BasicJsonType& val,
18117 const bool pretty_print,
18118 const bool ensure_ascii,
18119 const unsigned int indent_step,
18120 const unsigned int current_indent = 0)
18121 {
18122 switch (val.m_data.m_type)
18123 {
18124 case value_t::object:
18125 {
18126 if (val.m_data.m_value.object->empty())
18127 {
18128 o->write_characters("{}", 2);
18129 return;
18130 }
18131
18132 if (pretty_print)
18133 {
18134 o->write_characters("{\n", 2);
18135
18136 // variable to hold indentation for recursive calls
18137 const auto new_indent = current_indent + indent_step;
18138 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18139 {
18140 indent_string.resize(indent_string.size() * 2, ' ');
18141 }
18142
18143 // first n-1 elements
18144 auto i = val.m_data.m_value.object->cbegin();
18145 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18146 {
18147 o->write_characters(indent_string.c_str(), new_indent);
18148 o->write_character('\"');
18149 dump_escaped(i->first, ensure_ascii);
18150 o->write_characters("\": ", 3);
18151 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18152 o->write_characters(",\n", 2);
18153 }
18154
18155 // last element
18156 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18157 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18158 o->write_characters(indent_string.c_str(), new_indent);
18159 o->write_character('\"');
18160 dump_escaped(i->first, ensure_ascii);
18161 o->write_characters("\": ", 3);
18162 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18163
18164 o->write_character('\n');
18165 o->write_characters(indent_string.c_str(), current_indent);
18166 o->write_character('}');
18167 }
18168 else
18169 {
18170 o->write_character('{');
18171
18172 // first n-1 elements
18173 auto i = val.m_data.m_value.object->cbegin();
18174 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18175 {
18176 o->write_character('\"');
18177 dump_escaped(i->first, ensure_ascii);
18178 o->write_characters("\":", 2);
18179 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18180 o->write_character(',');
18181 }
18182
18183 // last element
18184 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18185 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18186 o->write_character('\"');
18187 dump_escaped(i->first, ensure_ascii);
18188 o->write_characters("\":", 2);
18189 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18190
18191 o->write_character('}');
18192 }
18193
18194 return;
18195 }
18196
18197 case value_t::array:
18198 {
18199 if (val.m_data.m_value.array->empty())
18200 {
18201 o->write_characters("[]", 2);
18202 return;
18203 }
18204
18205 if (pretty_print)
18206 {
18207 o->write_characters("[\n", 2);
18208
18209 // variable to hold indentation for recursive calls
18210 const auto new_indent = current_indent + indent_step;
18211 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18212 {
18213 indent_string.resize(indent_string.size() * 2, ' ');
18214 }
18215
18216 // first n-1 elements
18217 for (auto i = val.m_data.m_value.array->cbegin();
18218 i != val.m_data.m_value.array->cend() - 1; ++i)
18219 {
18220 o->write_characters(indent_string.c_str(), new_indent);
18221 dump(*i, true, ensure_ascii, indent_step, new_indent);
18222 o->write_characters(",\n", 2);
18223 }
18224
18225 // last element
18226 JSON_ASSERT(!val.m_data.m_value.array->empty());
18227 o->write_characters(indent_string.c_str(), new_indent);
18228 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18229
18230 o->write_character('\n');
18231 o->write_characters(indent_string.c_str(), current_indent);
18232 o->write_character(']');
18233 }
18234 else
18235 {
18236 o->write_character('[');
18237
18238 // first n-1 elements
18239 for (auto i = val.m_data.m_value.array->cbegin();
18240 i != val.m_data.m_value.array->cend() - 1; ++i)
18241 {
18242 dump(*i, false, ensure_ascii, indent_step, current_indent);
18243 o->write_character(',');
18244 }
18245
18246 // last element
18247 JSON_ASSERT(!val.m_data.m_value.array->empty());
18248 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
18249
18250 o->write_character(']');
18251 }
18252
18253 return;
18254 }
18255
18256 case value_t::string:
18257 {
18258 o->write_character('\"');
18259 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
18260 o->write_character('\"');
18261 return;
18262 }
18263
18264 case value_t::binary:
18265 {
18266 if (pretty_print)
18267 {
18268 o->write_characters("{\n", 2);
18269
18270 // variable to hold indentation for recursive calls
18271 const auto new_indent = current_indent + indent_step;
18272 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18273 {
18274 indent_string.resize(indent_string.size() * 2, ' ');
18275 }
18276
18277 o->write_characters(indent_string.c_str(), new_indent);
18278
18279 o->write_characters("\"bytes\": [", 10);
18280
18281 if (!val.m_data.m_value.binary->empty())
18282 {
18283 for (auto i = val.m_data.m_value.binary->cbegin();
18284 i != val.m_data.m_value.binary->cend() - 1; ++i)
18285 {
18286 dump_integer(*i);
18287 o->write_characters(", ", 2);
18288 }
18289 dump_integer(val.m_data.m_value.binary->back());
18290 }
18291
18292 o->write_characters("],\n", 3);
18293 o->write_characters(indent_string.c_str(), new_indent);
18294
18295 o->write_characters("\"subtype\": ", 11);
18296 if (val.m_data.m_value.binary->has_subtype())
18297 {
18298 dump_integer(val.m_data.m_value.binary->subtype());
18299 }
18300 else
18301 {
18302 o->write_characters("null", 4);
18303 }
18304 o->write_character('\n');
18305 o->write_characters(indent_string.c_str(), current_indent);
18306 o->write_character('}');
18307 }
18308 else
18309 {
18310 o->write_characters("{\"bytes\":[", 10);
18311
18312 if (!val.m_data.m_value.binary->empty())
18313 {
18314 for (auto i = val.m_data.m_value.binary->cbegin();
18315 i != val.m_data.m_value.binary->cend() - 1; ++i)
18316 {
18317 dump_integer(*i);
18318 o->write_character(',');
18319 }
18320 dump_integer(val.m_data.m_value.binary->back());
18321 }
18322
18323 o->write_characters("],\"subtype\":", 12);
18324 if (val.m_data.m_value.binary->has_subtype())
18325 {
18326 dump_integer(val.m_data.m_value.binary->subtype());
18327 o->write_character('}');
18328 }
18329 else
18330 {
18331 o->write_characters("null}", 5);
18332 }
18333 }
18334 return;
18335 }
18336
18337 case value_t::boolean:
18338 {
18339 if (val.m_data.m_value.boolean)
18340 {
18341 o->write_characters("true", 4);
18342 }
18343 else
18344 {
18345 o->write_characters("false", 5);
18346 }
18347 return;
18348 }
18349
18351 {
18352 dump_integer(val.m_data.m_value.number_integer);
18353 return;
18354 }
18355
18357 {
18358 dump_integer(val.m_data.m_value.number_unsigned);
18359 return;
18360 }
18361
18363 {
18364 dump_float(val.m_data.m_value.number_float);
18365 return;
18366 }
18367
18368 case value_t::discarded:
18369 {
18370 o->write_characters("<discarded>", 11);
18371 return;
18372 }
18373
18374 case value_t::null:
18375 {
18376 o->write_characters("null", 4);
18377 return;
18378 }
18379
18380 default: // LCOV_EXCL_LINE
18381 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18382 }
18383 }
18384
18385 JSON_PRIVATE_UNLESS_TESTED:
18400 void dump_escaped(const string_t& s, const bool ensure_ascii)
18401 {
18402 std::uint32_t codepoint{};
18403 std::uint8_t state = UTF8_ACCEPT;
18404 std::size_t bytes = 0; // number of bytes written to string_buffer
18405
18406 // number of bytes written at the point of the last valid byte
18407 std::size_t bytes_after_last_accept = 0;
18408 std::size_t undumped_chars = 0;
18409
18410 for (std::size_t i = 0; i < s.size(); ++i)
18411 {
18412 const auto byte = static_cast<std::uint8_t>(s[i]);
18413
18414 switch (decode(state, codepoint, byte))
18415 {
18416 case UTF8_ACCEPT: // decode found a new code point
18417 {
18418 switch (codepoint)
18419 {
18420 case 0x08: // backspace
18421 {
18422 string_buffer[bytes++] = '\\';
18423 string_buffer[bytes++] = 'b';
18424 break;
18425 }
18426
18427 case 0x09: // horizontal tab
18428 {
18429 string_buffer[bytes++] = '\\';
18430 string_buffer[bytes++] = 't';
18431 break;
18432 }
18433
18434 case 0x0A: // newline
18435 {
18436 string_buffer[bytes++] = '\\';
18437 string_buffer[bytes++] = 'n';
18438 break;
18439 }
18440
18441 case 0x0C: // formfeed
18442 {
18443 string_buffer[bytes++] = '\\';
18444 string_buffer[bytes++] = 'f';
18445 break;
18446 }
18447
18448 case 0x0D: // carriage return
18449 {
18450 string_buffer[bytes++] = '\\';
18451 string_buffer[bytes++] = 'r';
18452 break;
18453 }
18454
18455 case 0x22: // quotation mark
18456 {
18457 string_buffer[bytes++] = '\\';
18458 string_buffer[bytes++] = '\"';
18459 break;
18460 }
18461
18462 case 0x5C: // reverse solidus
18463 {
18464 string_buffer[bytes++] = '\\';
18465 string_buffer[bytes++] = '\\';
18466 break;
18467 }
18468
18469 default:
18470 {
18471 // escape control characters (0x00..0x1F) or, if
18472 // ensure_ascii parameter is used, non-ASCII characters
18473 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
18474 {
18475 if (codepoint <= 0xFFFF)
18476 {
18477 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18478 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
18479 static_cast<std::uint16_t>(codepoint)));
18480 bytes += 6;
18481 }
18482 else
18483 {
18484 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18485 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
18486 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
18487 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
18488 bytes += 12;
18489 }
18490 }
18491 else
18492 {
18493 // copy byte to buffer (all previous bytes
18494 // been copied have in default case above)
18495 string_buffer[bytes++] = s[i];
18496 }
18497 break;
18498 }
18499 }
18500
18501 // write buffer and reset index; there must be 13 bytes
18502 // left, as this is the maximal number of bytes to be
18503 // written ("\uxxxx\uxxxx\0") for one code point
18504 if (string_buffer.size() - bytes < 13)
18505 {
18506 o->write_characters(string_buffer.data(), bytes);
18507 bytes = 0;
18508 }
18509
18510 // remember the byte position of this accept
18511 bytes_after_last_accept = bytes;
18512 undumped_chars = 0;
18513 break;
18514 }
18515
18516 case UTF8_REJECT: // decode found invalid UTF-8 byte
18517 {
18518 switch (error_handler)
18519 {
18521 {
18522 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
18523 }
18524
18527 {
18528 // in case we saw this character the first time, we
18529 // would like to read it again, because the byte
18530 // may be OK for itself, but just not OK for the
18531 // previous sequence
18532 if (undumped_chars > 0)
18533 {
18534 --i;
18535 }
18536
18537 // reset length buffer to the last accepted index;
18538 // thus removing/ignoring the invalid characters
18539 bytes = bytes_after_last_accept;
18540
18542 {
18543 // add a replacement character
18544 if (ensure_ascii)
18545 {
18546 string_buffer[bytes++] = '\\';
18547 string_buffer[bytes++] = 'u';
18548 string_buffer[bytes++] = 'f';
18549 string_buffer[bytes++] = 'f';
18550 string_buffer[bytes++] = 'f';
18551 string_buffer[bytes++] = 'd';
18552 }
18553 else
18554 {
18558 }
18559
18560 // write buffer and reset index; there must be 13 bytes
18561 // left, as this is the maximal number of bytes to be
18562 // written ("\uxxxx\uxxxx\0") for one code point
18563 if (string_buffer.size() - bytes < 13)
18564 {
18565 o->write_characters(string_buffer.data(), bytes);
18566 bytes = 0;
18567 }
18568
18569 bytes_after_last_accept = bytes;
18570 }
18571
18572 undumped_chars = 0;
18573
18574 // continue processing the string
18575 state = UTF8_ACCEPT;
18576 break;
18577 }
18578
18579 default: // LCOV_EXCL_LINE
18580 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18581 }
18582 break;
18583 }
18584
18585 default: // decode found yet incomplete multi-byte code point
18586 {
18587 if (!ensure_ascii)
18588 {
18589 // code point will not be escaped - copy byte to buffer
18590 string_buffer[bytes++] = s[i];
18591 }
18592 ++undumped_chars;
18593 break;
18594 }
18595 }
18596 }
18597
18598 // we finished processing the string
18599 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
18600 {
18601 // write buffer
18602 if (bytes > 0)
18603 {
18604 o->write_characters(string_buffer.data(), bytes);
18605 }
18606 }
18607 else
18608 {
18609 // we finish reading, but do not accept: string was incomplete
18610 switch (error_handler)
18611 {
18613 {
18614 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));
18615 }
18616
18618 {
18619 // write all accepted bytes
18620 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18621 break;
18622 }
18623
18625 {
18626 // write all accepted bytes
18627 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18628 // add a replacement character
18629 if (ensure_ascii)
18630 {
18631 o->write_characters("\\ufffd", 6);
18632 }
18633 else
18634 {
18635 o->write_characters("\xEF\xBF\xBD", 3);
18636 }
18637 break;
18638 }
18639
18640 default: // LCOV_EXCL_LINE
18641 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18642 }
18643 }
18644 }
18645
18646 private:
18655 inline unsigned int count_digits(number_unsigned_t x) noexcept
18656 {
18657 unsigned int n_digits = 1;
18658 for (;;)
18659 {
18660 if (x < 10)
18661 {
18662 return n_digits;
18663 }
18664 if (x < 100)
18665 {
18666 return n_digits + 1;
18667 }
18668 if (x < 1000)
18669 {
18670 return n_digits + 2;
18671 }
18672 if (x < 10000)
18673 {
18674 return n_digits + 3;
18675 }
18676 x = x / 10000u;
18677 n_digits += 4;
18678 }
18679 }
18680
18686 static std::string hex_bytes(std::uint8_t byte)
18687 {
18688 std::string result = "FF";
18689 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
18690 result[0] = nibble_to_hex[byte / 16];
18691 result[1] = nibble_to_hex[byte % 16];
18692 return result;
18693 }
18694
18695 // templates to avoid warnings about useless casts
18696 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
18697 bool is_negative_number(NumberType x)
18698 {
18699 return x < 0;
18700 }
18701
18702 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
18703 bool is_negative_number(NumberType /*unused*/)
18704 {
18705 return false;
18706 }
18707
18717 template < typename NumberType, detail::enable_if_t <
18718 std::is_integral<NumberType>::value ||
18719 std::is_same<NumberType, number_unsigned_t>::value ||
18720 std::is_same<NumberType, number_integer_t>::value ||
18721 std::is_same<NumberType, binary_char_t>::value,
18722 int > = 0 >
18723 void dump_integer(NumberType x)
18724 {
18725 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18726 {
18727 {
18728 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
18729 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
18730 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
18731 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
18732 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
18733 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
18734 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
18735 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
18736 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
18737 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
18738 }
18739 };
18740
18741 // special case for "0"
18742 if (x == 0)
18743 {
18744 o->write_character('0');
18745 return;
18746 }
18747
18748 // use a pointer to fill the buffer
18749 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18750
18751 number_unsigned_t abs_value;
18752
18753 unsigned int n_chars{};
18754
18755 if (is_negative_number(x))
18756 {
18757 *buffer_ptr = '-';
18758 abs_value = remove_sign(static_cast<number_integer_t>(x));
18759
18760 // account one more byte for the minus sign
18761 n_chars = 1 + count_digits(abs_value);
18762 }
18763 else
18764 {
18765 abs_value = static_cast<number_unsigned_t>(x);
18766 n_chars = count_digits(abs_value);
18767 }
18768
18769 // spare 1 byte for '\0'
18770 JSON_ASSERT(n_chars < number_buffer.size() - 1);
18771
18772 // jump to the end to generate the string from backward,
18773 // so we later avoid reversing the result
18774 buffer_ptr += n_chars;
18775
18776 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
18777 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
18778 while (abs_value >= 100)
18779 {
18780 const auto digits_index = static_cast<unsigned>((abs_value % 100));
18781 abs_value /= 100;
18782 *(--buffer_ptr) = digits_to_99[digits_index][1];
18783 *(--buffer_ptr) = digits_to_99[digits_index][0];
18784 }
18785
18786 if (abs_value >= 10)
18787 {
18788 const auto digits_index = static_cast<unsigned>(abs_value);
18789 *(--buffer_ptr) = digits_to_99[digits_index][1];
18790 *(--buffer_ptr) = digits_to_99[digits_index][0];
18791 }
18792 else
18793 {
18794 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
18795 }
18796
18797 o->write_characters(number_buffer.data(), n_chars);
18798 }
18799
18808 void dump_float(number_float_t x)
18809 {
18810 // NaN / inf
18811 if (!std::isfinite(x))
18812 {
18813 o->write_characters("null", 4);
18814 return;
18815 }
18816
18817 // If number_float_t is an IEEE-754 single or double precision number,
18818 // use the Grisu2 algorithm to produce short numbers which are
18819 // guaranteed to round-trip, using strtof and strtod, resp.
18820 //
18821 // NB: The test below works if <long double> == <double>.
18822 static constexpr bool is_ieee_single_or_double
18823 = (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) ||
18824 (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);
18825
18826 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
18827 }
18828
18829 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
18830 {
18831 auto* begin = number_buffer.data();
18832 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
18833
18834 o->write_characters(begin, static_cast<size_t>(end - begin));
18835 }
18836
18837 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
18838 {
18839 // get number of digits for a float -> text -> float round-trip
18840 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
18841
18842 // the actual conversion
18843 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18844 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
18845
18846 // negative value indicates an error
18847 JSON_ASSERT(len > 0);
18848 // check if buffer was large enough
18849 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
18850
18851 // erase thousands separator
18852 if (thousands_sep != '\0')
18853 {
18854 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
18855 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
18856 std::fill(end, number_buffer.end(), '\0');
18857 JSON_ASSERT((end - number_buffer.begin()) <= len);
18858 len = (end - number_buffer.begin());
18859 }
18860
18861 // convert decimal point to '.'
18862 if (decimal_point != '\0' && decimal_point != '.')
18863 {
18864 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
18865 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
18866 if (dec_pos != number_buffer.end())
18867 {
18868 *dec_pos = '.';
18869 }
18870 }
18871
18872 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
18873
18874 // determine if we need to append ".0"
18875 const bool value_is_int_like =
18876 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
18877 [](char c)
18878 {
18879 return c == '.' || c == 'e';
18880 });
18881
18882 if (value_is_int_like)
18883 {
18884 o->write_characters(".0", 2);
18885 }
18886 }
18887
18909 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
18910 {
18911 static const std::array<std::uint8_t, 400> utf8d =
18912 {
18913 {
18914 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
18915 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
18916 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
18917 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
18918 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
18919 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
18920 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
18921 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
18922 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
18923 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
18924 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
18925 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
18926 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
18927 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
18928 }
18929 };
18930
18931 JSON_ASSERT(byte < utf8d.size());
18932 const std::uint8_t type = utf8d[byte];
18933
18934 codep = (state != UTF8_ACCEPT)
18935 ? (byte & 0x3fu) | (codep << 6u)
18936 : (0xFFu >> type) & (byte);
18937
18938 const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
18939 JSON_ASSERT(index < utf8d.size());
18940 state = utf8d[index];
18941 return state;
18942 }
18943
18944 /*
18945 * Overload to make the compiler happy while it is instantiating
18946 * dump_integer for number_unsigned_t.
18947 * Must never be called.
18948 */
18949 number_unsigned_t remove_sign(number_unsigned_t x)
18950 {
18951 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18952 return x; // LCOV_EXCL_LINE
18953 }
18954
18955 /*
18956 * Helper function for dump_integer
18957 *
18958 * This function takes a negative signed integer and returns its absolute
18959 * value as unsigned integer. The plus/minus shuffling is necessary as we can
18960 * not directly remove the sign of an arbitrary signed integer as the
18961 * absolute values of INT_MIN and INT_MAX are usually not the same. See
18962 * #1708 for details.
18963 */
18964 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
18965 {
18966 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
18967 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
18968 }
18969
18970 private:
18972 output_adapter_t<char> o = nullptr;
18973
18975 std::array<char, 64> number_buffer{{}};
18976
18978 const std::lconv* loc = nullptr;
18980 const char thousands_sep = '\0';
18982 const char decimal_point = '\0';
18983
18985 std::array<char, 512> string_buffer{{}};
18986
18988 const char indent_char;
18991
18994};
18995
18996} // namespace detail
18997NLOHMANN_JSON_NAMESPACE_END
18998
18999// #include <nlohmann/detail/value_t.hpp>
19000
19001// #include <nlohmann/json_fwd.hpp>
19002
19003// #include <nlohmann/ordered_map.hpp>
19004// __ _____ _____ _____
19005// __| | __| | | | JSON for Modern C++
19006// | | |__ | | | | | | version 3.11.3
19007// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19008//
19009// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
19010// SPDX-License-Identifier: MIT
19011
19012
19013
19014#include <functional> // equal_to, less
19015#include <initializer_list> // initializer_list
19016#include <iterator> // input_iterator_tag, iterator_traits
19017#include <memory> // allocator
19018#include <stdexcept> // for out_of_range
19019#include <type_traits> // enable_if, is_convertible
19020#include <utility> // pair
19021#include <vector> // vector
19022
19023// #include <nlohmann/detail/macro_scope.hpp>
19024
19025// #include <nlohmann/detail/meta/type_traits.hpp>
19026
19027
19028NLOHMANN_JSON_NAMESPACE_BEGIN
19029
19032template <class Key, class T, class IgnoredLess = std::less<Key>,
19033 class Allocator = std::allocator<std::pair<const Key, T>>>
19034 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19035{
19036 using key_type = Key;
19037 using mapped_type = T;
19038 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19039 using iterator = typename Container::iterator;
19040 using const_iterator = typename Container::const_iterator;
19041 using size_type = typename Container::size_type;
19042 using value_type = typename Container::value_type;
19043#ifdef JSON_HAS_CPP_14
19044 using key_compare = std::equal_to<>;
19045#else
19046 using key_compare = std::equal_to<Key>;
19047#endif
19048
19049 // Explicit constructors instead of `using Container::Container`
19050 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19051 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19052 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19053 template <class It>
19054 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19055 : Container{first, last, alloc} {}
19056 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19057 : Container{init, alloc} {}
19058
19059 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19060 {
19061 for (auto it = this->begin(); it != this->end(); ++it)
19062 {
19063 if (m_compare(it->first, key))
19064 {
19065 return {it, false};
19066 }
19067 }
19068 Container::emplace_back(key, std::forward<T>(t));
19069 return {std::prev(this->end()), true};
19070 }
19071
19072 template<class KeyType, detail::enable_if_t<
19073 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19074 std::pair<iterator, bool> emplace(KeyType && key, T && t)
19075 {
19076 for (auto it = this->begin(); it != this->end(); ++it)
19077 {
19078 if (m_compare(it->first, key))
19079 {
19080 return {it, false};
19081 }
19082 }
19083 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19084 return {std::prev(this->end()), true};
19085 }
19086
19087 T& operator[](const key_type& key)
19088 {
19089 return emplace(key, T{}).first->second;
19090 }
19091
19092 template<class KeyType, detail::enable_if_t<
19093 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19094 T & operator[](KeyType && key)
19095 {
19096 return emplace(std::forward<KeyType>(key), T{}).first->second;
19097 }
19098
19099 const T& operator[](const key_type& key) const
19100 {
19101 return at(key);
19102 }
19103
19104 template<class KeyType, detail::enable_if_t<
19105 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19106 const T & operator[](KeyType && key) const
19107 {
19108 return at(std::forward<KeyType>(key));
19109 }
19110
19111 T& at(const key_type& key)
19112 {
19113 for (auto it = this->begin(); it != this->end(); ++it)
19114 {
19115 if (m_compare(it->first, key))
19116 {
19117 return it->second;
19118 }
19119 }
19120
19121 JSON_THROW(std::out_of_range("key not found"));
19122 }
19123
19124 template<class KeyType, detail::enable_if_t<
19125 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19126 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19127 {
19128 for (auto it = this->begin(); it != this->end(); ++it)
19129 {
19130 if (m_compare(it->first, key))
19131 {
19132 return it->second;
19133 }
19134 }
19135
19136 JSON_THROW(std::out_of_range("key not found"));
19137 }
19138
19139 const T& at(const key_type& key) const
19140 {
19141 for (auto it = this->begin(); it != this->end(); ++it)
19142 {
19143 if (m_compare(it->first, key))
19144 {
19145 return it->second;
19146 }
19147 }
19148
19149 JSON_THROW(std::out_of_range("key not found"));
19150 }
19151
19152 template<class KeyType, detail::enable_if_t<
19153 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19154 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19155 {
19156 for (auto it = this->begin(); it != this->end(); ++it)
19157 {
19158 if (m_compare(it->first, key))
19159 {
19160 return it->second;
19161 }
19162 }
19163
19164 JSON_THROW(std::out_of_range("key not found"));
19165 }
19166
19167 size_type erase(const key_type& key)
19168 {
19169 for (auto it = this->begin(); it != this->end(); ++it)
19170 {
19171 if (m_compare(it->first, key))
19172 {
19173 // Since we cannot move const Keys, re-construct them in place
19174 for (auto next = it; ++next != this->end(); ++it)
19175 {
19176 it->~value_type(); // Destroy but keep allocation
19177 new (&*it) value_type{std::move(*next)};
19178 }
19179 Container::pop_back();
19180 return 1;
19181 }
19182 }
19183 return 0;
19184 }
19185
19186 template<class KeyType, detail::enable_if_t<
19187 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19188 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19189 {
19190 for (auto it = this->begin(); it != this->end(); ++it)
19191 {
19192 if (m_compare(it->first, key))
19193 {
19194 // Since we cannot move const Keys, re-construct them in place
19195 for (auto next = it; ++next != this->end(); ++it)
19196 {
19197 it->~value_type(); // Destroy but keep allocation
19198 new (&*it) value_type{std::move(*next)};
19199 }
19200 Container::pop_back();
19201 return 1;
19202 }
19203 }
19204 return 0;
19205 }
19206
19207 iterator erase(iterator pos)
19208 {
19209 return erase(pos, std::next(pos));
19210 }
19211
19212 iterator erase(iterator first, iterator last)
19213 {
19214 if (first == last)
19215 {
19216 return first;
19217 }
19218
19219 const auto elements_affected = std::distance(first, last);
19220 const auto offset = std::distance(Container::begin(), first);
19221
19222 // This is the start situation. We need to delete elements_affected
19223 // elements (3 in this example: e, f, g), and need to return an
19224 // iterator past the last deleted element (h in this example).
19225 // Note that offset is the distance from the start of the vector
19226 // to first. We will need this later.
19227
19228 // [ a, b, c, d, e, f, g, h, i, j ]
19229 // ^ ^
19230 // first last
19231
19232 // Since we cannot move const Keys, we re-construct them in place.
19233 // We start at first and re-construct (viz. copy) the elements from
19234 // the back of the vector. Example for first iteration:
19235
19236 // ,--------.
19237 // v | destroy e and re-construct with h
19238 // [ a, b, c, d, e, f, g, h, i, j ]
19239 // ^ ^
19240 // it it + elements_affected
19241
19242 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19243 {
19244 it->~value_type(); // destroy but keep allocation
19245 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
19246 }
19247
19248 // [ a, b, c, d, h, i, j, h, i, j ]
19249 // ^ ^
19250 // first last
19251
19252 // remove the unneeded elements at the end of the vector
19253 Container::resize(this->size() - static_cast<size_type>(elements_affected));
19254
19255 // [ a, b, c, d, h, i, j ]
19256 // ^ ^
19257 // first last
19258
19259 // first is now pointing past the last deleted element, but we cannot
19260 // use this iterator, because it may have been invalidated by the
19261 // resize call. Instead, we can return begin() + offset.
19262 return Container::begin() + offset;
19263 }
19264
19265 size_type count(const key_type& key) const
19266 {
19267 for (auto it = this->begin(); it != this->end(); ++it)
19268 {
19269 if (m_compare(it->first, key))
19270 {
19271 return 1;
19272 }
19273 }
19274 return 0;
19275 }
19276
19277 template<class KeyType, detail::enable_if_t<
19278 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19279 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19280 {
19281 for (auto it = this->begin(); it != this->end(); ++it)
19282 {
19283 if (m_compare(it->first, key))
19284 {
19285 return 1;
19286 }
19287 }
19288 return 0;
19289 }
19290
19291 iterator find(const key_type& key)
19292 {
19293 for (auto it = this->begin(); it != this->end(); ++it)
19294 {
19295 if (m_compare(it->first, key))
19296 {
19297 return it;
19298 }
19299 }
19300 return Container::end();
19301 }
19302
19303 template<class KeyType, detail::enable_if_t<
19304 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19305 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19306 {
19307 for (auto it = this->begin(); it != this->end(); ++it)
19308 {
19309 if (m_compare(it->first, key))
19310 {
19311 return it;
19312 }
19313 }
19314 return Container::end();
19315 }
19316
19317 const_iterator find(const key_type& key) const
19318 {
19319 for (auto it = this->begin(); it != this->end(); ++it)
19320 {
19321 if (m_compare(it->first, key))
19322 {
19323 return it;
19324 }
19325 }
19326 return Container::end();
19327 }
19328
19329 std::pair<iterator, bool> insert( value_type&& value )
19330 {
19331 return emplace(value.first, std::move(value.second));
19332 }
19333
19334 std::pair<iterator, bool> insert( const value_type& value )
19335 {
19336 for (auto it = this->begin(); it != this->end(); ++it)
19337 {
19338 if (m_compare(it->first, value.first))
19339 {
19340 return {it, false};
19341 }
19342 }
19343 Container::push_back(value);
19344 return {--this->end(), true};
19345 }
19346
19347 template<typename InputIt>
19348 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
19349 std::input_iterator_tag>::value>::type;
19350
19351 template<typename InputIt, typename = require_input_iter<InputIt>>
19352 void insert(InputIt first, InputIt last)
19353 {
19354 for (auto it = first; it != last; ++it)
19355 {
19356 insert(*it);
19357 }
19358 }
19359
19360private:
19361 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
19362};
19363
19364NLOHMANN_JSON_NAMESPACE_END
19365
19366
19367#if defined(JSON_HAS_CPP_17)
19368 #if JSON_HAS_STATIC_RTTI
19369 #include <any>
19370 #endif
19371 #include <string_view>
19372#endif
19373
19379NLOHMANN_JSON_NAMESPACE_BEGIN
19380
19399NLOHMANN_BASIC_JSON_TPL_DECLARATION
19400class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
19401 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
19402{
19403 private:
19404 template<detail::value_t> friend struct detail::external_constructor;
19405
19406 template<typename>
19407 friend class ::nlohmann::json_pointer;
19408 // can be restored when json_pointer backwards compatibility is removed
19409 // friend ::nlohmann::json_pointer<StringType>;
19410
19411 template<typename BasicJsonType, typename InputType>
19412 friend class ::nlohmann::detail::parser;
19413 friend ::nlohmann::detail::serializer<basic_json>;
19414 template<typename BasicJsonType>
19415 friend class ::nlohmann::detail::iter_impl;
19416 template<typename BasicJsonType, typename CharType>
19417 friend class ::nlohmann::detail::binary_writer;
19418 template<typename BasicJsonType, typename InputType, typename SAX>
19419 friend class ::nlohmann::detail::binary_reader;
19420 template<typename BasicJsonType>
19421 friend class ::nlohmann::detail::json_sax_dom_parser;
19422 template<typename BasicJsonType>
19423 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
19424 friend class ::nlohmann::detail::exception;
19425
19427 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
19428 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
19429
19430 JSON_PRIVATE_UNLESS_TESTED:
19431 // convenience aliases for types residing in namespace detail;
19432 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
19433
19434 template<typename InputAdapterType>
19435 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
19436 InputAdapterType adapter,
19437 detail::parser_callback_t<basic_json>cb = nullptr,
19438 const bool allow_exceptions = true,
19439 const bool ignore_comments = false
19440 )
19441 {
19442 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
19443 std::move(cb), allow_exceptions, ignore_comments);
19444 }
19445
19446 private:
19447 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
19448 template<typename BasicJsonType>
19449 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
19450 template<typename BasicJsonType>
19451 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
19452 template<typename Iterator>
19453 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
19454 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
19455
19456 template<typename CharType>
19457 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
19458
19459 template<typename InputType>
19460 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
19461 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
19462
19463 JSON_PRIVATE_UNLESS_TESTED:
19464 using serializer = ::nlohmann::detail::serializer<basic_json>;
19465
19466 public:
19467 using value_t = detail::value_t;
19469 using json_pointer = ::nlohmann::json_pointer<StringType>;
19470 template<typename T, typename SFINAE>
19471 using json_serializer = JSONSerializer<T, SFINAE>;
19477 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
19478
19482
19484 // exceptions //
19486
19490
19497
19499
19501 // container types //
19503
19508
19511
19516
19518 using difference_type = std::ptrdiff_t;
19520 using size_type = std::size_t;
19521
19523 using allocator_type = AllocatorType<basic_json>;
19524
19526 using pointer = typename std::allocator_traits<allocator_type>::pointer;
19528 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
19529
19531 using iterator = iter_impl<basic_json>;
19533 using const_iterator = iter_impl<const basic_json>;
19535 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
19537 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
19538
19540
19544 {
19545 return allocator_type();
19546 }
19547
19550 JSON_HEDLEY_WARN_UNUSED_RESULT
19552 {
19553 basic_json result;
19554
19555 result["copyright"] = "(C) 2013-2023 Niels Lohmann";
19556 result["name"] = "JSON for Modern C++";
19557 result["url"] = "https://github.com/nlohmann/json";
19558 result["version"]["string"] =
19559 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
19560 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
19561 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19562 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
19563 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
19564 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
19565
19566#ifdef _WIN32
19567 result["platform"] = "win32";
19568#elif defined __linux__
19569 result["platform"] = "linux";
19570#elif defined __APPLE__
19571 result["platform"] = "apple";
19572#elif defined __unix__
19573 result["platform"] = "unix";
19574#else
19575 result["platform"] = "unknown";
19576#endif
19577
19578#if defined(__ICC) || defined(__INTEL_COMPILER)
19579 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
19580#elif defined(__clang__)
19581 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
19582#elif defined(__GNUC__) || defined(__GNUG__)
19583 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
19584 std::to_string(__GNUC__), '.',
19585 std::to_string(__GNUC_MINOR__), '.',
19586 std::to_string(__GNUC_PATCHLEVEL__))
19587 }
19588 };
19589#elif defined(__HP_cc) || defined(__HP_aCC)
19590 result["compiler"] = "hp"
19591#elif defined(__IBMCPP__)
19592 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
19593#elif defined(_MSC_VER)
19594 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
19595#elif defined(__PGI)
19596 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
19597#elif defined(__SUNPRO_CC)
19598 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
19599#else
19600 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
19601#endif
19602
19603#if defined(_MSVC_LANG)
19604 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
19605#elif defined(__cplusplus)
19606 result["compiler"]["c++"] = std::to_string(__cplusplus);
19607#else
19608 result["compiler"]["c++"] = "unknown";
19609#endif
19610 return result;
19611 }
19612
19614 // JSON value data types //
19616
19621
19626#if defined(JSON_HAS_CPP_14)
19627 // use of transparent comparator avoids unnecessary repeated construction of temporaries
19628 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
19629 using default_object_comparator_t = std::less<>;
19630#else
19631 using default_object_comparator_t = std::less<StringType>;
19632#endif
19633
19636 using object_t = ObjectType<StringType,
19637 basic_json,
19639 AllocatorType<std::pair<const StringType,
19640 basic_json>>>;
19641
19644 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19645
19648 using string_t = StringType;
19649
19652 using boolean_t = BooleanType;
19653
19656 using number_integer_t = NumberIntegerType;
19657
19660 using number_unsigned_t = NumberUnsignedType;
19661
19664 using number_float_t = NumberFloatType;
19665
19668 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19669
19672 using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
19673
19675
19676 private:
19677
19679 template<typename T, typename... Args>
19680 JSON_HEDLEY_RETURNS_NON_NULL
19681 static T* create(Args&& ... args)
19682 {
19683 AllocatorType<T> alloc;
19684 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19685
19686 auto deleter = [&](T * obj)
19687 {
19688 AllocatorTraits::deallocate(alloc, obj, 1);
19689 };
19690 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19691 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19692 JSON_ASSERT(obj != nullptr);
19693 return obj.release();
19694 }
19695
19697 // JSON value storage //
19699
19700 JSON_PRIVATE_UNLESS_TESTED:
19726 union json_value
19727 {
19731 array_t* array;
19733 string_t* string;
19735 binary_t* binary;
19737 boolean_t boolean;
19739 number_integer_t number_integer;
19741 number_unsigned_t number_unsigned;
19743 number_float_t number_float;
19744
19746 json_value() = default;
19748 json_value(boolean_t v) noexcept : boolean(v) {}
19750 json_value(number_integer_t v) noexcept : number_integer(v) {}
19752 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19754 json_value(number_float_t v) noexcept : number_float(v) {}
19756 json_value(value_t t)
19757 {
19758 switch (t)
19759 {
19760 case value_t::object:
19761 {
19762 object = create<object_t>();
19763 break;
19764 }
19765
19766 case value_t::array:
19767 {
19768 array = create<array_t>();
19769 break;
19770 }
19771
19772 case value_t::string:
19773 {
19774 string = create<string_t>("");
19775 break;
19776 }
19777
19778 case value_t::binary:
19779 {
19780 binary = create<binary_t>();
19781 break;
19782 }
19783
19784 case value_t::boolean:
19785 {
19786 boolean = static_cast<boolean_t>(false);
19787 break;
19788 }
19789
19790 case value_t::number_integer:
19791 {
19792 number_integer = static_cast<number_integer_t>(0);
19793 break;
19794 }
19795
19796 case value_t::number_unsigned:
19797 {
19798 number_unsigned = static_cast<number_unsigned_t>(0);
19799 break;
19800 }
19801
19802 case value_t::number_float:
19803 {
19804 number_float = static_cast<number_float_t>(0.0);
19805 break;
19806 }
19807
19808 case value_t::null:
19809 {
19810 object = nullptr; // silence warning, see #821
19811 break;
19812 }
19813
19814 case value_t::discarded:
19815 default:
19816 {
19817 object = nullptr; // silence warning, see #821
19818 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
19819 {
19820 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE
19821 }
19822 break;
19823 }
19824 }
19825 }
19826
19828 json_value(const string_t& value) : string(create<string_t>(value)) {}
19829
19831 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
19832
19834 json_value(const object_t& value) : object(create<object_t>(value)) {}
19835
19837 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
19838
19840 json_value(const array_t& value) : array(create<array_t>(value)) {}
19841
19843 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
19844
19846 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
19847
19849 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
19850
19852 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
19853
19855 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
19856
19857 void destroy(value_t t)
19858 {
19859 if (
19860 (t == value_t::object && object == nullptr) ||
19861 (t == value_t::array && array == nullptr) ||
19862 (t == value_t::string && string == nullptr) ||
19863 (t == value_t::binary && binary == nullptr)
19864 )
19865 {
19866 //not initialized (e.g. due to exception in the ctor)
19867 return;
19868 }
19869 if (t == value_t::array || t == value_t::object)
19870 {
19871 // flatten the current json_value to a heap-allocated stack
19872 std::vector<basic_json> stack;
19873
19874 // move the top-level items to stack
19875 if (t == value_t::array)
19876 {
19877 stack.reserve(array->size());
19878 std::move(array->begin(), array->end(), std::back_inserter(stack));
19879 }
19880 else
19881 {
19882 stack.reserve(object->size());
19883 for (auto&& it : *object)
19884 {
19885 stack.push_back(std::move(it.second));
19886 }
19887 }
19888
19889 while (!stack.empty())
19890 {
19891 // move the last item to local variable to be processed
19892 basic_json current_item(std::move(stack.back()));
19893 stack.pop_back();
19894
19895 // if current_item is array/object, move
19896 // its children to the stack to be processed later
19897 if (current_item.is_array())
19898 {
19899 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
19900
19901 current_item.m_data.m_value.array->clear();
19902 }
19903 else if (current_item.is_object())
19904 {
19905 for (auto&& it : *current_item.m_data.m_value.object)
19906 {
19907 stack.push_back(std::move(it.second));
19908 }
19909
19910 current_item.m_data.m_value.object->clear();
19911 }
19912
19913 // it's now safe that current_item get destructed
19914 // since it doesn't have any children
19915 }
19916 }
19917
19918 switch (t)
19919 {
19920 case value_t::object:
19921 {
19922 AllocatorType<object_t> alloc;
19923 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
19924 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
19925 break;
19926 }
19927
19928 case value_t::array:
19929 {
19930 AllocatorType<array_t> alloc;
19931 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
19932 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
19933 break;
19934 }
19935
19936 case value_t::string:
19937 {
19938 AllocatorType<string_t> alloc;
19939 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
19940 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
19941 break;
19942 }
19943
19944 case value_t::binary:
19945 {
19946 AllocatorType<binary_t> alloc;
19947 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
19948 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
19949 break;
19950 }
19951
19952 case value_t::null:
19953 case value_t::boolean:
19954 case value_t::number_integer:
19955 case value_t::number_unsigned:
19956 case value_t::number_float:
19957 case value_t::discarded:
19958 default:
19959 {
19960 break;
19961 }
19962 }
19963 }
19964 };
19965
19966 private:
19985 void assert_invariant(bool check_parents = true) const noexcept
19986 {
19987 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
19988 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
19989 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
19990 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
19991
19992#if JSON_DIAGNOSTICS
19993 JSON_TRY
19994 {
19995 // cppcheck-suppress assertWithSideEffect
19996 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
19997 {
19998 return j.m_parent == this;
19999 }));
20000 }
20001 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20002#endif
20003 static_cast<void>(check_parents);
20004 }
20005
20006 void set_parents()
20007 {
20008#if JSON_DIAGNOSTICS
20009 switch (m_data.m_type)
20010 {
20011 case value_t::array:
20012 {
20013 for (auto& element : *m_data.m_value.array)
20014 {
20015 element.m_parent = this;
20016 }
20017 break;
20018 }
20019
20020 case value_t::object:
20021 {
20022 for (auto& element : *m_data.m_value.object)
20023 {
20024 element.second.m_parent = this;
20025 }
20026 break;
20027 }
20028
20029 case value_t::null:
20030 case value_t::string:
20031 case value_t::boolean:
20032 case value_t::number_integer:
20033 case value_t::number_unsigned:
20034 case value_t::number_float:
20035 case value_t::binary:
20036 case value_t::discarded:
20037 default:
20038 break;
20039 }
20040#endif
20041 }
20042
20043 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20044 {
20045#if JSON_DIAGNOSTICS
20046 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20047 {
20048 (it + i)->m_parent = this;
20049 }
20050#else
20051 static_cast<void>(count_set_parents);
20052#endif
20053 return it;
20054 }
20055
20056 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
20057 {
20058#if JSON_DIAGNOSTICS
20059 if (old_capacity != static_cast<std::size_t>(-1))
20060 {
20061 // see https://github.com/nlohmann/json/issues/2838
20062 JSON_ASSERT(type() == value_t::array);
20063 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20064 {
20065 // capacity has changed: update all parents
20066 set_parents();
20067 return j;
20068 }
20069 }
20070
20071 // ordered_json uses a vector internally, so pointers could have
20072 // been invalidated; see https://github.com/nlohmann/json/issues/2962
20073#ifdef JSON_HEDLEY_MSVC_VERSION
20074#pragma warning(push )
20075#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20076#endif
20078 {
20079 set_parents();
20080 return j;
20081 }
20082#ifdef JSON_HEDLEY_MSVC_VERSION
20083#pragma warning( pop )
20084#endif
20085
20086 j.m_parent = this;
20087#else
20088 static_cast<void>(j);
20089 static_cast<void>(old_capacity);
20090#endif
20091 return j;
20092 }
20093
20094 public:
20096 // JSON parser callback //
20098
20102
20105 using parser_callback_t = detail::parser_callback_t<basic_json>;
20106
20108 // constructors //
20110
20115
20119 : m_data(v)
20120 {
20121 assert_invariant();
20122 }
20123
20126 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20127 : basic_json(value_t::null)
20128 {
20129 assert_invariant();
20130 }
20131
20134 template < typename CompatibleType,
20135 typename U = detail::uncvref_t<CompatibleType>,
20136 detail::enable_if_t <
20138 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20139 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20140 std::forward<CompatibleType>(val))))
20141 {
20142 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20143 set_parents();
20144 assert_invariant();
20145 }
20146
20149 template < typename BasicJsonType,
20150 detail::enable_if_t <
20151 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20152 basic_json(const BasicJsonType& val)
20153 {
20154 using other_boolean_t = typename BasicJsonType::boolean_t;
20155 using other_number_float_t = typename BasicJsonType::number_float_t;
20156 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20157 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20158 using other_string_t = typename BasicJsonType::string_t;
20159 using other_object_t = typename BasicJsonType::object_t;
20160 using other_array_t = typename BasicJsonType::array_t;
20161 using other_binary_t = typename BasicJsonType::binary_t;
20162
20163 switch (val.type())
20164 {
20165 case value_t::boolean:
20166 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20167 break;
20168 case value_t::number_float:
20169 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20170 break;
20171 case value_t::number_integer:
20172 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20173 break;
20174 case value_t::number_unsigned:
20175 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20176 break;
20177 case value_t::string:
20178 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20179 break;
20180 case value_t::object:
20181 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20182 break;
20183 case value_t::array:
20184 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20185 break;
20186 case value_t::binary:
20187 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20188 break;
20189 case value_t::null:
20190 *this = nullptr;
20191 break;
20192 case value_t::discarded:
20193 m_data.m_type = value_t::discarded;
20194 break;
20195 default: // LCOV_EXCL_LINE
20196 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20197 }
20198 JSON_ASSERT(m_data.m_type == val.type());
20199 set_parents();
20200 assert_invariant();
20201 }
20202
20206 bool type_deduction = true,
20207 value_t manual_type = value_t::array)
20208 {
20209 // check if each element is an array with two elements whose first
20210 // element is a string
20211 bool is_an_object = std::all_of(init.begin(), init.end(),
20212 [](const detail::json_ref<basic_json>& element_ref)
20213 {
20214 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
20215 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
20216 // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
20217 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
20218 });
20219
20220 // adjust type if type deduction is not wanted
20221 if (!type_deduction)
20222 {
20223 // if array is wanted, do not create an object though possible
20224 if (manual_type == value_t::array)
20225 {
20226 is_an_object = false;
20227 }
20228
20229 // if object is wanted but impossible, throw an exception
20230 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20231 {
20232 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
20233 }
20234 }
20235
20236 if (is_an_object)
20237 {
20238 // the initializer list is a list of pairs -> create object
20239 m_data.m_type = value_t::object;
20240 m_data.m_value = value_t::object;
20241
20242 for (auto& element_ref : init)
20243 {
20244 auto element = element_ref.moved_or_copied();
20245 m_data.m_value.object->emplace(
20246 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
20247 std::move((*element.m_data.m_value.array)[1]));
20248 }
20249 }
20250 else
20251 {
20252 // the initializer list describes an array -> create array
20253 m_data.m_type = value_t::array;
20254 m_data.m_value.array = create<array_t>(init.begin(), init.end());
20255 }
20256
20257 set_parents();
20258 assert_invariant();
20259 }
20260
20263 JSON_HEDLEY_WARN_UNUSED_RESULT
20264 static basic_json binary(const typename binary_t::container_type& init)
20265 {
20266 auto res = basic_json();
20267 res.m_data.m_type = value_t::binary;
20268 res.m_data.m_value = init;
20269 return res;
20270 }
20271
20274 JSON_HEDLEY_WARN_UNUSED_RESULT
20275 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
20276 {
20277 auto res = basic_json();
20278 res.m_data.m_type = value_t::binary;
20279 res.m_data.m_value = binary_t(init, subtype);
20280 return res;
20281 }
20282
20285 JSON_HEDLEY_WARN_UNUSED_RESULT
20286 static basic_json binary(typename binary_t::container_type&& init)
20287 {
20288 auto res = basic_json();
20289 res.m_data.m_type = value_t::binary;
20290 res.m_data.m_value = std::move(init);
20291 return res;
20292 }
20293
20296 JSON_HEDLEY_WARN_UNUSED_RESULT
20297 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
20298 {
20299 auto res = basic_json();
20300 res.m_data.m_type = value_t::binary;
20301 res.m_data.m_value = binary_t(std::move(init), subtype);
20302 return res;
20303 }
20304
20307 JSON_HEDLEY_WARN_UNUSED_RESULT
20309 {
20310 return basic_json(init, false, value_t::array);
20311 }
20312
20315 JSON_HEDLEY_WARN_UNUSED_RESULT
20317 {
20318 return basic_json(init, false, value_t::object);
20319 }
20320
20324 m_data{cnt, val}
20325 {
20326 set_parents();
20327 assert_invariant();
20328 }
20329
20332 template < class InputIT, typename std::enable_if <
20333 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
20334 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
20335 basic_json(InputIT first, InputIT last)
20336 {
20337 JSON_ASSERT(first.m_object != nullptr);
20338 JSON_ASSERT(last.m_object != nullptr);
20339
20340 // make sure iterator fits the current value
20341 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20342 {
20343 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
20344 }
20345
20346 // copy type from first iterator
20347 m_data.m_type = first.m_object->m_data.m_type;
20348
20349 // check if iterator range is complete for primitive values
20350 switch (m_data.m_type)
20351 {
20352 case value_t::boolean:
20353 case value_t::number_float:
20354 case value_t::number_integer:
20355 case value_t::number_unsigned:
20356 case value_t::string:
20357 {
20358 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
20359 || !last.m_it.primitive_iterator.is_end()))
20360 {
20361 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
20362 }
20363 break;
20364 }
20365
20366 case value_t::null:
20367 case value_t::object:
20368 case value_t::array:
20369 case value_t::binary:
20370 case value_t::discarded:
20371 default:
20372 break;
20373 }
20374
20375 switch (m_data.m_type)
20376 {
20377 case value_t::number_integer:
20378 {
20379 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
20380 break;
20381 }
20382
20383 case value_t::number_unsigned:
20384 {
20385 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
20386 break;
20387 }
20388
20389 case value_t::number_float:
20390 {
20391 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
20392 break;
20393 }
20394
20395 case value_t::boolean:
20396 {
20397 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
20398 break;
20399 }
20400
20401 case value_t::string:
20402 {
20403 m_data.m_value = *first.m_object->m_data.m_value.string;
20404 break;
20405 }
20406
20407 case value_t::object:
20408 {
20409 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
20410 last.m_it.object_iterator);
20411 break;
20412 }
20413
20414 case value_t::array:
20415 {
20416 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
20417 last.m_it.array_iterator);
20418 break;
20419 }
20420
20421 case value_t::binary:
20422 {
20423 m_data.m_value = *first.m_object->m_data.m_value.binary;
20424 break;
20425 }
20426
20427 case value_t::null:
20428 case value_t::discarded:
20429 default:
20430 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
20431 }
20432
20433 set_parents();
20434 assert_invariant();
20435 }
20436
20438 // other constructors and destructor //
20440
20441 template<typename JsonRef,
20442 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
20443 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
20444 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
20445
20449 : json_base_class_t(other)
20450 {
20451 m_data.m_type = other.m_data.m_type;
20452 // check of passed value is valid
20453 other.assert_invariant();
20454
20455 switch (m_data.m_type)
20456 {
20457 case value_t::object:
20458 {
20459 m_data.m_value = *other.m_data.m_value.object;
20460 break;
20461 }
20462
20463 case value_t::array:
20464 {
20465 m_data.m_value = *other.m_data.m_value.array;
20466 break;
20467 }
20468
20469 case value_t::string:
20470 {
20471 m_data.m_value = *other.m_data.m_value.string;
20472 break;
20473 }
20474
20475 case value_t::boolean:
20476 {
20477 m_data.m_value = other.m_data.m_value.boolean;
20478 break;
20479 }
20480
20481 case value_t::number_integer:
20482 {
20483 m_data.m_value = other.m_data.m_value.number_integer;
20484 break;
20485 }
20486
20487 case value_t::number_unsigned:
20488 {
20489 m_data.m_value = other.m_data.m_value.number_unsigned;
20490 break;
20491 }
20492
20493 case value_t::number_float:
20494 {
20495 m_data.m_value = other.m_data.m_value.number_float;
20496 break;
20497 }
20498
20499 case value_t::binary:
20500 {
20501 m_data.m_value = *other.m_data.m_value.binary;
20502 break;
20503 }
20504
20505 case value_t::null:
20506 case value_t::discarded:
20507 default:
20508 break;
20509 }
20510
20511 set_parents();
20512 assert_invariant();
20513 }
20514
20517 basic_json(basic_json&& other) noexcept
20518 : json_base_class_t(std::forward<json_base_class_t>(other)),
20519 m_data(std::move(other.m_data))
20520 {
20521 // check that passed value is valid
20522 other.assert_invariant(false);
20523
20524 // invalidate payload
20525 other.m_data.m_type = value_t::null;
20526 other.m_data.m_value = {};
20527
20528 set_parents();
20529 assert_invariant();
20530 }
20531
20535 std::is_nothrow_move_constructible<value_t>::value&&
20536 std::is_nothrow_move_assignable<value_t>::value&&
20537 std::is_nothrow_move_constructible<json_value>::value&&
20538 std::is_nothrow_move_assignable<json_value>::value&&
20539 std::is_nothrow_move_assignable<json_base_class_t>::value
20540 )
20541 {
20542 // check that passed value is valid
20543 other.assert_invariant();
20544
20545 using std::swap;
20546 swap(m_data.m_type, other.m_data.m_type);
20547 swap(m_data.m_value, other.m_data.m_value);
20548 json_base_class_t::operator=(std::move(other));
20549
20550 set_parents();
20551 assert_invariant();
20552 return *this;
20553 }
20554
20557 ~basic_json() noexcept
20558 {
20559 assert_invariant(false);
20560 }
20561
20563
20564 public:
20566 // object inspection //
20568
20572
20575 string_t dump(const int indent = -1,
20576 const char indent_char = ' ',
20577 const bool ensure_ascii = false,
20578 const error_handler_t error_handler = error_handler_t::strict) const
20579 {
20580 string_t result;
20581 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
20582
20583 if (indent >= 0)
20584 {
20585 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
20586 }
20587 else
20588 {
20589 s.dump(*this, false, ensure_ascii, 0);
20590 }
20591
20592 return result;
20593 }
20594
20597 constexpr value_t type() const noexcept
20598 {
20599 return m_data.m_type;
20600 }
20601
20604 constexpr bool is_primitive() const noexcept
20605 {
20606 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20607 }
20608
20611 constexpr bool is_structured() const noexcept
20612 {
20613 return is_array() || is_object();
20614 }
20615
20618 constexpr bool is_null() const noexcept
20619 {
20620 return m_data.m_type == value_t::null;
20621 }
20622
20625 constexpr bool is_boolean() const noexcept
20626 {
20627 return m_data.m_type == value_t::boolean;
20628 }
20629
20632 constexpr bool is_number() const noexcept
20633 {
20634 return is_number_integer() || is_number_float();
20635 }
20636
20639 constexpr bool is_number_integer() const noexcept
20640 {
20641 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
20642 }
20643
20646 constexpr bool is_number_unsigned() const noexcept
20647 {
20648 return m_data.m_type == value_t::number_unsigned;
20649 }
20650
20653 constexpr bool is_number_float() const noexcept
20654 {
20655 return m_data.m_type == value_t::number_float;
20656 }
20657
20660 constexpr bool is_object() const noexcept
20661 {
20662 return m_data.m_type == value_t::object;
20663 }
20664
20667 constexpr bool is_array() const noexcept
20668 {
20669 return m_data.m_type == value_t::array;
20670 }
20671
20674 constexpr bool is_string() const noexcept
20675 {
20676 return m_data.m_type == value_t::string;
20677 }
20678
20681 constexpr bool is_binary() const noexcept
20682 {
20683 return m_data.m_type == value_t::binary;
20684 }
20685
20688 constexpr bool is_discarded() const noexcept
20689 {
20690 return m_data.m_type == value_t::discarded;
20691 }
20692
20695 constexpr operator value_t() const noexcept
20696 {
20697 return m_data.m_type;
20698 }
20699
20701
20702 private:
20704 // value access //
20706
20708 boolean_t get_impl(boolean_t* /*unused*/) const
20709 {
20710 if (JSON_HEDLEY_LIKELY(is_boolean()))
20711 {
20712 return m_data.m_value.boolean;
20713 }
20714
20715 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
20716 }
20717
20719 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
20720 {
20721 return is_object() ? m_data.m_value.object : nullptr;
20722 }
20723
20725 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
20726 {
20727 return is_object() ? m_data.m_value.object : nullptr;
20728 }
20729
20731 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
20732 {
20733 return is_array() ? m_data.m_value.array : nullptr;
20734 }
20735
20737 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
20738 {
20739 return is_array() ? m_data.m_value.array : nullptr;
20740 }
20741
20743 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
20744 {
20745 return is_string() ? m_data.m_value.string : nullptr;
20746 }
20747
20749 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
20750 {
20751 return is_string() ? m_data.m_value.string : nullptr;
20752 }
20753
20755 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
20756 {
20757 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20758 }
20759
20761 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
20762 {
20763 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20764 }
20765
20767 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
20768 {
20769 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20770 }
20771
20773 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
20774 {
20775 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20776 }
20777
20779 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
20780 {
20781 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20782 }
20783
20785 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
20786 {
20787 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20788 }
20789
20791 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
20792 {
20793 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20794 }
20795
20797 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
20798 {
20799 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20800 }
20801
20803 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
20804 {
20805 return is_binary() ? m_data.m_value.binary : nullptr;
20806 }
20807
20809 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
20810 {
20811 return is_binary() ? m_data.m_value.binary : nullptr;
20812 }
20813
20825 template<typename ReferenceType, typename ThisType>
20826 static ReferenceType get_ref_impl(ThisType& obj)
20827 {
20828 // delegate the call to get_ptr<>()
20829 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
20830
20831 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
20832 {
20833 return *ptr;
20834 }
20835
20836 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
20837 }
20838
20839 public:
20843
20846 template<typename PointerType, typename std::enable_if<
20847 std::is_pointer<PointerType>::value, int>::type = 0>
20848 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20849 {
20850 // delegate the call to get_impl_ptr<>()
20851 return get_impl_ptr(static_cast<PointerType>(nullptr));
20852 }
20853
20856 template < typename PointerType, typename std::enable_if <
20857 std::is_pointer<PointerType>::value&&
20858 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
20859 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20860 {
20861 // delegate the call to get_impl_ptr<>() const
20862 return get_impl_ptr(static_cast<PointerType>(nullptr));
20863 }
20864
20865 private:
20904 template < typename ValueType,
20905 detail::enable_if_t <
20908 int > = 0 >
20909 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
20910 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
20911 {
20912 auto ret = ValueType();
20913 JSONSerializer<ValueType>::from_json(*this, ret);
20914 return ret;
20915 }
20916
20947 template < typename ValueType,
20948 detail::enable_if_t <
20950 int > = 0 >
20951 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
20952 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
20953 {
20954 return JSONSerializer<ValueType>::from_json(*this);
20955 }
20956
20972 template < typename BasicJsonType,
20973 detail::enable_if_t <
20975 int > = 0 >
20976 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
20977 {
20978 return *this;
20979 }
20980
20995 template<typename BasicJsonType,
20996 detail::enable_if_t<
20997 std::is_same<BasicJsonType, basic_json_t>::value,
20998 int> = 0>
20999 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
21000 {
21001 return *this;
21002 }
21003
21008 template<typename PointerType,
21009 detail::enable_if_t<
21010 std::is_pointer<PointerType>::value,
21011 int> = 0>
21012 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21013 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21014 {
21015 // delegate the call to get_ptr
21016 return get_ptr<PointerType>();
21017 }
21018
21019 public:
21043 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21044#if defined(JSON_HAS_CPP_14)
21045 constexpr
21046#endif
21047 auto get() const noexcept(
21048 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21049 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21050 {
21051 // we cannot static_assert on ValueTypeCV being non-const, because
21052 // there is support for get<const basic_json_t>(), which is why we
21053 // still need the uncvref
21054 static_assert(!std::is_reference<ValueTypeCV>::value,
21055 "get() cannot be used with reference types, you might want to use get_ref()");
21056 return get_impl<ValueType>(detail::priority_tag<4> {});
21057 }
21058
21086 template<typename PointerType, typename std::enable_if<
21087 std::is_pointer<PointerType>::value, int>::type = 0>
21088 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21089 {
21090 // delegate the call to get_ptr
21091 return get_ptr<PointerType>();
21092 }
21093
21096 template < typename ValueType,
21097 detail::enable_if_t <
21100 int > = 0 >
21101 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21102 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21103 {
21104 JSONSerializer<ValueType>::from_json(*this, v);
21105 return v;
21106 }
21107
21108 // specialization to allow calling get_to with a basic_json value
21109 // see https://github.com/nlohmann/json/issues/2175
21110 template<typename ValueType,
21111 detail::enable_if_t <
21113 int> = 0>
21114 ValueType & get_to(ValueType& v) const
21115 {
21116 v = *this;
21117 return v;
21118 }
21119
21120 template <
21121 typename T, std::size_t N,
21122 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21123 detail::enable_if_t <
21125 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21126 noexcept(noexcept(JSONSerializer<Array>::from_json(
21127 std::declval<const basic_json_t&>(), v)))
21128 {
21129 JSONSerializer<Array>::from_json(*this, v);
21130 return v;
21131 }
21132
21135 template<typename ReferenceType, typename std::enable_if<
21136 std::is_reference<ReferenceType>::value, int>::type = 0>
21137 ReferenceType get_ref()
21138 {
21139 // delegate call to get_ref_impl
21140 return get_ref_impl<ReferenceType>(*this);
21141 }
21142
21145 template < typename ReferenceType, typename std::enable_if <
21146 std::is_reference<ReferenceType>::value&&
21147 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21148 ReferenceType get_ref() const
21149 {
21150 // delegate call to get_ref_impl
21151 return get_ref_impl<ReferenceType>(*this);
21152 }
21153
21183 template < typename ValueType, typename std::enable_if <
21191#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21193#endif
21194#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
21196#endif
21198 >::value, int >::type = 0 >
21199 JSON_EXPLICIT operator ValueType() const
21200 {
21201 // delegate the call to get<>() const
21202 return get<ValueType>();
21203 }
21204
21208 {
21209 if (!is_binary())
21210 {
21211 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21212 }
21213
21214 return *get_ptr<binary_t*>();
21215 }
21216
21219 const binary_t& get_binary() const
21220 {
21221 if (!is_binary())
21222 {
21223 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21224 }
21225
21226 return *get_ptr<const binary_t*>();
21227 }
21228
21230
21232 // element access //
21234
21238
21242 {
21243 // at only works for arrays
21244 if (JSON_HEDLEY_LIKELY(is_array()))
21245 {
21246 JSON_TRY
21247 {
21248 return set_parent(m_data.m_value.array->at(idx));
21249 }
21250 JSON_CATCH (std::out_of_range&)
21251 {
21252 // create better exception explanation
21253 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21254 }
21255 }
21256 else
21257 {
21258 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21259 }
21260 }
21261
21265 {
21266 // at only works for arrays
21267 if (JSON_HEDLEY_LIKELY(is_array()))
21268 {
21269 JSON_TRY
21270 {
21271 return m_data.m_value.array->at(idx);
21272 }
21273 JSON_CATCH (std::out_of_range&)
21274 {
21275 // create better exception explanation
21276 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21277 }
21278 }
21279 else
21280 {
21281 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21282 }
21283 }
21284
21287 reference at(const typename object_t::key_type& key)
21288 {
21289 // at only works for objects
21290 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21291 {
21292 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21293 }
21294
21295 auto it = m_data.m_value.object->find(key);
21296 if (it == m_data.m_value.object->end())
21297 {
21298 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21299 }
21300 return set_parent(it->second);
21301 }
21302
21305 template<class KeyType, detail::enable_if_t<
21306 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21307 reference at(KeyType && key)
21308 {
21309 // at only works for objects
21310 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21311 {
21312 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21313 }
21314
21315 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21316 if (it == m_data.m_value.object->end())
21317 {
21318 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21319 }
21320 return set_parent(it->second);
21321 }
21322
21325 const_reference at(const typename object_t::key_type& key) const
21326 {
21327 // at only works for objects
21328 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21329 {
21330 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21331 }
21332
21333 auto it = m_data.m_value.object->find(key);
21334 if (it == m_data.m_value.object->end())
21335 {
21336 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21337 }
21338 return it->second;
21339 }
21340
21343 template<class KeyType, detail::enable_if_t<
21344 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21345 const_reference at(KeyType && key) const
21346 {
21347 // at only works for objects
21348 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21349 {
21350 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21351 }
21352
21353 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21354 if (it == m_data.m_value.object->end())
21355 {
21356 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21357 }
21358 return it->second;
21359 }
21360
21364 {
21365 // implicitly convert null value to an empty array
21366 if (is_null())
21367 {
21368 m_data.m_type = value_t::array;
21369 m_data.m_value.array = create<array_t>();
21370 assert_invariant();
21371 }
21372
21373 // operator[] only works for arrays
21374 if (JSON_HEDLEY_LIKELY(is_array()))
21375 {
21376 // fill up array with null values if given idx is outside range
21377 if (idx >= m_data.m_value.array->size())
21378 {
21379#if JSON_DIAGNOSTICS
21380 // remember array size & capacity before resizing
21381 const auto old_size = m_data.m_value.array->size();
21382 const auto old_capacity = m_data.m_value.array->capacity();
21383#endif
21384 m_data.m_value.array->resize(idx + 1);
21385
21386#if JSON_DIAGNOSTICS
21387 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
21388 {
21389 // capacity has changed: update all parents
21390 set_parents();
21391 }
21392 else
21393 {
21394 // set parent for values added above
21395 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
21396 }
21397#endif
21398 assert_invariant();
21399 }
21400
21401 return m_data.m_value.array->operator[](idx);
21402 }
21403
21404 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21405 }
21406
21410 {
21411 // const operator[] only works for arrays
21412 if (JSON_HEDLEY_LIKELY(is_array()))
21413 {
21414 return m_data.m_value.array->operator[](idx);
21415 }
21416
21417 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21418 }
21419
21422 reference operator[](typename object_t::key_type key)
21423 {
21424 // implicitly convert null value to an empty object
21425 if (is_null())
21426 {
21427 m_data.m_type = value_t::object;
21428 m_data.m_value.object = create<object_t>();
21429 assert_invariant();
21430 }
21431
21432 // operator[] only works for objects
21433 if (JSON_HEDLEY_LIKELY(is_object()))
21434 {
21435 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
21436 return set_parent(result.first->second);
21437 }
21438
21439 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21440 }
21441
21444 const_reference operator[](const typename object_t::key_type& key) const
21445 {
21446 // const operator[] only works for objects
21447 if (JSON_HEDLEY_LIKELY(is_object()))
21448 {
21449 auto it = m_data.m_value.object->find(key);
21450 JSON_ASSERT(it != m_data.m_value.object->end());
21451 return it->second;
21452 }
21453
21454 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21455 }
21456
21457 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
21458 // (they seemingly cannot be constrained to resolve the ambiguity)
21459 template<typename T>
21460 reference operator[](T* key)
21461 {
21462 return operator[](typename object_t::key_type(key));
21463 }
21464
21465 template<typename T>
21466 const_reference operator[](T* key) const
21467 {
21468 return operator[](typename object_t::key_type(key));
21469 }
21470
21473 template<class KeyType, detail::enable_if_t<
21474 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
21475 reference operator[](KeyType && key)
21476 {
21477 // implicitly convert null value to an empty object
21478 if (is_null())
21479 {
21480 m_data.m_type = value_t::object;
21481 m_data.m_value.object = create<object_t>();
21482 assert_invariant();
21483 }
21484
21485 // operator[] only works for objects
21486 if (JSON_HEDLEY_LIKELY(is_object()))
21487 {
21488 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
21489 return set_parent(result.first->second);
21490 }
21491
21492 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21493 }
21494
21497 template<class KeyType, detail::enable_if_t<
21498 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
21499 const_reference operator[](KeyType && key) const
21500 {
21501 // const operator[] only works for objects
21502 if (JSON_HEDLEY_LIKELY(is_object()))
21503 {
21504 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21505 JSON_ASSERT(it != m_data.m_value.object->end());
21506 return it->second;
21507 }
21508
21509 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21510 }
21511
21512 private:
21513 template<typename KeyType>
21514 using is_comparable_with_object_key = detail::is_comparable <
21515 object_comparator_t, const typename object_t::key_type&, KeyType >;
21516
21517 template<typename ValueType>
21518 using value_return_type = std::conditional <
21520 string_t, typename std::decay<ValueType>::type >;
21521
21522 public:
21525 template < class ValueType, detail::enable_if_t <
21528 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21529 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
21530 {
21531 // value only works for objects
21532 if (JSON_HEDLEY_LIKELY(is_object()))
21533 {
21534 // if key is found, return value and given default value otherwise
21535 const auto it = find(key);
21536 if (it != end())
21537 {
21538 return it->template get<ValueType>();
21539 }
21540
21541 return default_value;
21542 }
21543
21544 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21545 }
21546
21549 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21550 detail::enable_if_t <
21553 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21554 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
21555 {
21556 // value only works for objects
21557 if (JSON_HEDLEY_LIKELY(is_object()))
21558 {
21559 // if key is found, return value and given default value otherwise
21560 const auto it = find(key);
21561 if (it != end())
21562 {
21563 return it->template get<ReturnType>();
21564 }
21565
21566 return std::forward<ValueType>(default_value);
21567 }
21568
21569 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21570 }
21571
21574 template < class ValueType, class KeyType, detail::enable_if_t <
21577 && is_comparable_with_object_key<KeyType>::value
21579 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21580 ValueType value(KeyType && key, const ValueType& default_value) const
21581 {
21582 // value only works for objects
21583 if (JSON_HEDLEY_LIKELY(is_object()))
21584 {
21585 // if key is found, return value and given default value otherwise
21586 const auto it = find(std::forward<KeyType>(key));
21587 if (it != end())
21588 {
21589 return it->template get<ValueType>();
21590 }
21591
21592 return default_value;
21593 }
21594
21595 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21596 }
21597
21600 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
21601 detail::enable_if_t <
21604 && is_comparable_with_object_key<KeyType>::value
21606 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21607 ReturnType value(KeyType && key, ValueType && default_value) const
21608 {
21609 // value only works for objects
21610 if (JSON_HEDLEY_LIKELY(is_object()))
21611 {
21612 // if key is found, return value and given default value otherwise
21613 const auto it = find(std::forward<KeyType>(key));
21614 if (it != end())
21615 {
21616 return it->template get<ReturnType>();
21617 }
21618
21619 return std::forward<ValueType>(default_value);
21620 }
21621
21622 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21623 }
21624
21627 template < class ValueType, detail::enable_if_t <
21629 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21630 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
21631 {
21632 // value only works for objects
21633 if (JSON_HEDLEY_LIKELY(is_object()))
21634 {
21635 // if pointer resolves a value, return it or use default value
21636 JSON_TRY
21637 {
21638 return ptr.get_checked(this).template get<ValueType>();
21639 }
21640 JSON_INTERNAL_CATCH (out_of_range&)
21641 {
21642 return default_value;
21643 }
21644 }
21645
21646 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21647 }
21648
21651 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21652 detail::enable_if_t <
21654 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21655 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
21656 {
21657 // value only works for objects
21658 if (JSON_HEDLEY_LIKELY(is_object()))
21659 {
21660 // if pointer resolves a value, return it or use default value
21661 JSON_TRY
21662 {
21663 return ptr.get_checked(this).template get<ReturnType>();
21664 }
21665 JSON_INTERNAL_CATCH (out_of_range&)
21666 {
21667 return std::forward<ValueType>(default_value);
21668 }
21669 }
21670
21671 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21672 }
21673
21674 template < class ValueType, class BasicJsonType, detail::enable_if_t <
21677 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21678 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21679 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
21680 {
21681 return value(ptr.convert(), default_value);
21682 }
21683
21684 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
21685 detail::enable_if_t <
21688 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21689 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21690 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
21691 {
21692 return value(ptr.convert(), std::forward<ValueType>(default_value));
21693 }
21694
21698 {
21699 return *begin();
21700 }
21701
21705 {
21706 return *cbegin();
21707 }
21708
21712 {
21713 auto tmp = end();
21714 --tmp;
21715 return *tmp;
21716 }
21717
21721 {
21722 auto tmp = cend();
21723 --tmp;
21724 return *tmp;
21725 }
21726
21729 template < class IteratorType, detail::enable_if_t <
21730 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21731 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21732 IteratorType erase(IteratorType pos)
21733 {
21734 // make sure iterator fits the current value
21735 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
21736 {
21737 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21738 }
21739
21740 IteratorType result = end();
21741
21742 switch (m_data.m_type)
21743 {
21744 case value_t::boolean:
21745 case value_t::number_float:
21746 case value_t::number_integer:
21747 case value_t::number_unsigned:
21748 case value_t::string:
21749 case value_t::binary:
21750 {
21751 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
21752 {
21753 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
21754 }
21755
21756 if (is_string())
21757 {
21758 AllocatorType<string_t> alloc;
21759 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21760 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21761 m_data.m_value.string = nullptr;
21762 }
21763 else if (is_binary())
21764 {
21765 AllocatorType<binary_t> alloc;
21766 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21767 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21768 m_data.m_value.binary = nullptr;
21769 }
21770
21771 m_data.m_type = value_t::null;
21772 assert_invariant();
21773 break;
21774 }
21775
21776 case value_t::object:
21777 {
21778 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
21779 break;
21780 }
21781
21782 case value_t::array:
21783 {
21784 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
21785 break;
21786 }
21787
21788 case value_t::null:
21789 case value_t::discarded:
21790 default:
21791 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21792 }
21793
21794 return result;
21795 }
21796
21799 template < class IteratorType, detail::enable_if_t <
21800 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21801 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21802 IteratorType erase(IteratorType first, IteratorType last)
21803 {
21804 // make sure iterator fits the current value
21805 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
21806 {
21807 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
21808 }
21809
21810 IteratorType result = end();
21811
21812 switch (m_data.m_type)
21813 {
21814 case value_t::boolean:
21815 case value_t::number_float:
21816 case value_t::number_integer:
21817 case value_t::number_unsigned:
21818 case value_t::string:
21819 case value_t::binary:
21820 {
21821 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
21822 || !last.m_it.primitive_iterator.is_end()))
21823 {
21824 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
21825 }
21826
21827 if (is_string())
21828 {
21829 AllocatorType<string_t> alloc;
21830 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21831 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21832 m_data.m_value.string = nullptr;
21833 }
21834 else if (is_binary())
21835 {
21836 AllocatorType<binary_t> alloc;
21837 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21838 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21839 m_data.m_value.binary = nullptr;
21840 }
21841
21842 m_data.m_type = value_t::null;
21843 assert_invariant();
21844 break;
21845 }
21846
21847 case value_t::object:
21848 {
21849 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
21850 last.m_it.object_iterator);
21851 break;
21852 }
21853
21854 case value_t::array:
21855 {
21856 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
21857 last.m_it.array_iterator);
21858 break;
21859 }
21860
21861 case value_t::null:
21862 case value_t::discarded:
21863 default:
21864 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21865 }
21866
21867 return result;
21868 }
21869
21870 private:
21871 template < typename KeyType, detail::enable_if_t <
21872 detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
21873 size_type erase_internal(KeyType && key)
21874 {
21875 // this erase only works for objects
21876 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21877 {
21878 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21879 }
21880
21881 return m_data.m_value.object->erase(std::forward<KeyType>(key));
21882 }
21883
21884 template < typename KeyType, detail::enable_if_t <
21885 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
21886 size_type erase_internal(KeyType && key)
21887 {
21888 // this erase only works for objects
21889 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21890 {
21891 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21892 }
21893
21894 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21895 if (it != m_data.m_value.object->end())
21896 {
21897 m_data.m_value.object->erase(it);
21898 return 1;
21899 }
21900 return 0;
21901 }
21902
21903 public:
21904
21907 size_type erase(const typename object_t::key_type& key)
21908 {
21909 // the indirection via erase_internal() is added to avoid making this
21910 // function a template and thus de-rank it during overload resolution
21911 return erase_internal(key);
21912 }
21913
21916 template<class KeyType, detail::enable_if_t<
21917 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21918 size_type erase(KeyType && key)
21919 {
21920 return erase_internal(std::forward<KeyType>(key));
21921 }
21922
21925 void erase(const size_type idx)
21926 {
21927 // this erase only works for arrays
21928 if (JSON_HEDLEY_LIKELY(is_array()))
21929 {
21930 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
21931 {
21932 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21933 }
21934
21935 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
21936 }
21937 else
21938 {
21939 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21940 }
21941 }
21942
21944
21946 // lookup //
21948
21951
21954 iterator find(const typename object_t::key_type& key)
21955 {
21956 auto result = end();
21957
21958 if (is_object())
21959 {
21960 result.m_it.object_iterator = m_data.m_value.object->find(key);
21961 }
21962
21963 return result;
21964 }
21965
21968 const_iterator find(const typename object_t::key_type& key) const
21969 {
21970 auto result = cend();
21971
21972 if (is_object())
21973 {
21974 result.m_it.object_iterator = m_data.m_value.object->find(key);
21975 }
21976
21977 return result;
21978 }
21979
21982 template<class KeyType, detail::enable_if_t<
21983 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21984 iterator find(KeyType && key)
21985 {
21986 auto result = end();
21987
21988 if (is_object())
21989 {
21990 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
21991 }
21992
21993 return result;
21994 }
21995
21998 template<class KeyType, detail::enable_if_t<
21999 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22000 const_iterator find(KeyType && key) const
22001 {
22002 auto result = cend();
22003
22004 if (is_object())
22005 {
22006 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22007 }
22008
22009 return result;
22010 }
22011
22014 size_type count(const typename object_t::key_type& key) const
22015 {
22016 // return 0 for all nonobject types
22017 return is_object() ? m_data.m_value.object->count(key) : 0;
22018 }
22019
22022 template<class KeyType, detail::enable_if_t<
22023 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22024 size_type count(KeyType && key) const
22025 {
22026 // return 0 for all nonobject types
22027 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22028 }
22029
22032 bool contains(const typename object_t::key_type& key) const
22033 {
22034 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22035 }
22036
22039 template<class KeyType, detail::enable_if_t<
22040 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22041 bool contains(KeyType && key) const
22042 {
22043 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22044 }
22045
22048 bool contains(const json_pointer& ptr) const
22049 {
22050 return ptr.contains(this);
22051 }
22052
22053 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22054 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22055 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22056 {
22057 return ptr.contains(this);
22058 }
22059
22061
22063 // iterators //
22065
22068
22071 iterator begin() noexcept
22072 {
22073 iterator result(this);
22074 result.set_begin();
22075 return result;
22076 }
22077
22080 const_iterator begin() const noexcept
22081 {
22082 return cbegin();
22083 }
22084
22087 const_iterator cbegin() const noexcept
22088 {
22089 const_iterator result(this);
22090 result.set_begin();
22091 return result;
22092 }
22093
22096 iterator end() noexcept
22097 {
22098 iterator result(this);
22099 result.set_end();
22100 return result;
22101 }
22102
22105 const_iterator end() const noexcept
22106 {
22107 return cend();
22108 }
22109
22112 const_iterator cend() const noexcept
22113 {
22114 const_iterator result(this);
22115 result.set_end();
22116 return result;
22117 }
22118
22122 {
22123 return reverse_iterator(end());
22124 }
22125
22129 {
22130 return crbegin();
22131 }
22132
22136 {
22137 return reverse_iterator(begin());
22138 }
22139
22143 {
22144 return crend();
22145 }
22146
22150 {
22151 return const_reverse_iterator(cend());
22152 }
22153
22157 {
22158 return const_reverse_iterator(cbegin());
22159 }
22160
22161 public:
22167 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22168 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22169 {
22170 return ref.items();
22171 }
22172
22178 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22179 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
22180 {
22181 return ref.items();
22182 }
22183
22186 iteration_proxy<iterator> items() noexcept
22187 {
22188 return iteration_proxy<iterator>(*this);
22189 }
22190
22193 iteration_proxy<const_iterator> items() const noexcept
22194 {
22195 return iteration_proxy<const_iterator>(*this);
22196 }
22197
22199
22201 // capacity //
22203
22206
22209 bool empty() const noexcept
22210 {
22211 switch (m_data.m_type)
22212 {
22213 case value_t::null:
22214 {
22215 // null values are empty
22216 return true;
22217 }
22218
22219 case value_t::array:
22220 {
22221 // delegate call to array_t::empty()
22222 return m_data.m_value.array->empty();
22223 }
22224
22225 case value_t::object:
22226 {
22227 // delegate call to object_t::empty()
22228 return m_data.m_value.object->empty();
22229 }
22230
22231 case value_t::string:
22232 case value_t::boolean:
22233 case value_t::number_integer:
22234 case value_t::number_unsigned:
22235 case value_t::number_float:
22236 case value_t::binary:
22237 case value_t::discarded:
22238 default:
22239 {
22240 // all other types are nonempty
22241 return false;
22242 }
22243 }
22244 }
22245
22248 size_type size() const noexcept
22249 {
22250 switch (m_data.m_type)
22251 {
22252 case value_t::null:
22253 {
22254 // null values are empty
22255 return 0;
22256 }
22257
22258 case value_t::array:
22259 {
22260 // delegate call to array_t::size()
22261 return m_data.m_value.array->size();
22262 }
22263
22264 case value_t::object:
22265 {
22266 // delegate call to object_t::size()
22267 return m_data.m_value.object->size();
22268 }
22269
22270 case value_t::string:
22271 case value_t::boolean:
22272 case value_t::number_integer:
22273 case value_t::number_unsigned:
22274 case value_t::number_float:
22275 case value_t::binary:
22276 case value_t::discarded:
22277 default:
22278 {
22279 // all other types have size 1
22280 return 1;
22281 }
22282 }
22283 }
22284
22287 size_type max_size() const noexcept
22288 {
22289 switch (m_data.m_type)
22290 {
22291 case value_t::array:
22292 {
22293 // delegate call to array_t::max_size()
22294 return m_data.m_value.array->max_size();
22295 }
22296
22297 case value_t::object:
22298 {
22299 // delegate call to object_t::max_size()
22300 return m_data.m_value.object->max_size();
22301 }
22302
22303 case value_t::null:
22304 case value_t::string:
22305 case value_t::boolean:
22306 case value_t::number_integer:
22307 case value_t::number_unsigned:
22308 case value_t::number_float:
22309 case value_t::binary:
22310 case value_t::discarded:
22311 default:
22312 {
22313 // all other types have max_size() == size()
22314 return size();
22315 }
22316 }
22317 }
22318
22320
22322 // modifiers //
22324
22327
22330 void clear() noexcept
22331 {
22332 switch (m_data.m_type)
22333 {
22334 case value_t::number_integer:
22335 {
22336 m_data.m_value.number_integer = 0;
22337 break;
22338 }
22339
22340 case value_t::number_unsigned:
22341 {
22342 m_data.m_value.number_unsigned = 0;
22343 break;
22344 }
22345
22346 case value_t::number_float:
22347 {
22348 m_data.m_value.number_float = 0.0;
22349 break;
22350 }
22351
22352 case value_t::boolean:
22353 {
22354 m_data.m_value.boolean = false;
22355 break;
22356 }
22357
22358 case value_t::string:
22359 {
22360 m_data.m_value.string->clear();
22361 break;
22362 }
22363
22364 case value_t::binary:
22365 {
22366 m_data.m_value.binary->clear();
22367 break;
22368 }
22369
22370 case value_t::array:
22371 {
22372 m_data.m_value.array->clear();
22373 break;
22374 }
22375
22376 case value_t::object:
22377 {
22378 m_data.m_value.object->clear();
22379 break;
22380 }
22381
22382 case value_t::null:
22383 case value_t::discarded:
22384 default:
22385 break;
22386 }
22387 }
22388
22392 {
22393 // push_back only works for null objects or arrays
22394 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22395 {
22396 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22397 }
22398
22399 // transform null object into an array
22400 if (is_null())
22401 {
22402 m_data.m_type = value_t::array;
22403 m_data.m_value = value_t::array;
22404 assert_invariant();
22405 }
22406
22407 // add element to array (move semantics)
22408 const auto old_capacity = m_data.m_value.array->capacity();
22409 m_data.m_value.array->push_back(std::move(val));
22410 set_parent(m_data.m_value.array->back(), old_capacity);
22411 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
22412 }
22413
22417 {
22418 push_back(std::move(val));
22419 return *this;
22420 }
22421
22424 void push_back(const basic_json& val)
22425 {
22426 // push_back only works for null objects or arrays
22427 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22428 {
22429 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22430 }
22431
22432 // transform null object into an array
22433 if (is_null())
22434 {
22435 m_data.m_type = value_t::array;
22436 m_data.m_value = value_t::array;
22437 assert_invariant();
22438 }
22439
22440 // add element to array
22441 const auto old_capacity = m_data.m_value.array->capacity();
22442 m_data.m_value.array->push_back(val);
22443 set_parent(m_data.m_value.array->back(), old_capacity);
22444 }
22445
22449 {
22450 push_back(val);
22451 return *this;
22452 }
22453
22456 void push_back(const typename object_t::value_type& val)
22457 {
22458 // push_back only works for null objects or objects
22459 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22460 {
22461 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22462 }
22463
22464 // transform null object into an object
22465 if (is_null())
22466 {
22467 m_data.m_type = value_t::object;
22468 m_data.m_value = value_t::object;
22469 assert_invariant();
22470 }
22471
22472 // add element to object
22473 auto res = m_data.m_value.object->insert(val);
22474 set_parent(res.first->second);
22475 }
22476
22479 reference operator+=(const typename object_t::value_type& val)
22480 {
22481 push_back(val);
22482 return *this;
22483 }
22484
22488 {
22489 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
22490 {
22491 basic_json&& key = init.begin()->moved_or_copied();
22492 push_back(typename object_t::value_type(
22493 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
22494 }
22495 else
22496 {
22497 push_back(basic_json(init));
22498 }
22499 }
22500
22504 {
22505 push_back(init);
22506 return *this;
22507 }
22508
22511 template<class... Args>
22512 reference emplace_back(Args&& ... args)
22513 {
22514 // emplace_back only works for null objects or arrays
22515 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22516 {
22517 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
22518 }
22519
22520 // transform null object into an array
22521 if (is_null())
22522 {
22523 m_data.m_type = value_t::array;
22524 m_data.m_value = value_t::array;
22525 assert_invariant();
22526 }
22527
22528 // add element to array (perfect forwarding)
22529 const auto old_capacity = m_data.m_value.array->capacity();
22530 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
22531 return set_parent(m_data.m_value.array->back(), old_capacity);
22532 }
22533
22536 template<class... Args>
22537 std::pair<iterator, bool> emplace(Args&& ... args)
22538 {
22539 // emplace only works for null objects or arrays
22540 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22541 {
22542 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
22543 }
22544
22545 // transform null object into an object
22546 if (is_null())
22547 {
22548 m_data.m_type = value_t::object;
22549 m_data.m_value = value_t::object;
22550 assert_invariant();
22551 }
22552
22553 // add element to array (perfect forwarding)
22554 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
22555 set_parent(res.first->second);
22556
22557 // create result iterator and set iterator to the result of emplace
22558 auto it = begin();
22559 it.m_it.object_iterator = res.first;
22560
22561 // return pair of iterator and boolean
22562 return {it, res.second};
22563 }
22564
22568 template<typename... Args>
22570 {
22571 iterator result(this);
22572 JSON_ASSERT(m_data.m_value.array != nullptr);
22573
22574 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
22575 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
22576 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
22577
22578 // This could have been written as:
22579 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
22580 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
22581
22582 set_parents();
22583 return result;
22584 }
22585
22589 {
22590 // insert only works for arrays
22591 if (JSON_HEDLEY_LIKELY(is_array()))
22592 {
22593 // check if iterator pos fits to this JSON value
22594 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22595 {
22596 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22597 }
22598
22599 // insert to array and return iterator
22600 return insert_iterator(pos, val);
22601 }
22602
22603 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22604 }
22605
22609 {
22610 return insert(pos, val);
22611 }
22612
22616 {
22617 // insert only works for arrays
22618 if (JSON_HEDLEY_LIKELY(is_array()))
22619 {
22620 // check if iterator pos fits to this JSON value
22621 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22622 {
22623 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22624 }
22625
22626 // insert to array and return iterator
22627 return insert_iterator(pos, cnt, val);
22628 }
22629
22630 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22631 }
22632
22636 {
22637 // insert only works for arrays
22638 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22639 {
22640 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22641 }
22642
22643 // check if iterator pos fits to this JSON value
22644 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22645 {
22646 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22647 }
22648
22649 // check if range iterators belong to the same JSON object
22650 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22651 {
22652 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22653 }
22654
22655 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
22656 {
22657 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
22658 }
22659
22660 // insert to array and return iterator
22661 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22662 }
22663
22667 {
22668 // insert only works for arrays
22669 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22670 {
22671 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22672 }
22673
22674 // check if iterator pos fits to this JSON value
22675 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22676 {
22677 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22678 }
22679
22680 // insert to array and return iterator
22681 return insert_iterator(pos, ilist.begin(), ilist.end());
22682 }
22683
22687 {
22688 // insert only works for objects
22689 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22690 {
22691 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22692 }
22693
22694 // check if range iterators belong to the same JSON object
22695 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22696 {
22697 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22698 }
22699
22700 // passed iterators must belong to objects
22701 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22702 {
22703 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
22704 }
22705
22706 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22707 }
22708
22711 void update(const_reference j, bool merge_objects = false)
22712 {
22713 update(j.begin(), j.end(), merge_objects);
22714 }
22715
22718 void update(const_iterator first, const_iterator last, bool merge_objects = false)
22719 {
22720 // implicitly convert null value to an empty object
22721 if (is_null())
22722 {
22723 m_data.m_type = value_t::object;
22724 m_data.m_value.object = create<object_t>();
22725 assert_invariant();
22726 }
22727
22728 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22729 {
22730 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
22731 }
22732
22733 // check if range iterators belong to the same JSON object
22734 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22735 {
22736 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22737 }
22738
22739 // passed iterators must belong to objects
22740 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22741 {
22742 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
22743 }
22744
22745 for (auto it = first; it != last; ++it)
22746 {
22747 if (merge_objects && it.value().is_object())
22748 {
22749 auto it2 = m_data.m_value.object->find(it.key());
22750 if (it2 != m_data.m_value.object->end())
22751 {
22752 it2->second.update(it.value(), true);
22753 continue;
22754 }
22755 }
22756 m_data.m_value.object->operator[](it.key()) = it.value();
22757#if JSON_DIAGNOSTICS
22758 m_data.m_value.object->operator[](it.key()).m_parent = this;
22759#endif
22760 }
22761 }
22762
22765 void swap(reference other) noexcept (
22766 std::is_nothrow_move_constructible<value_t>::value&&
22767 std::is_nothrow_move_assignable<value_t>::value&&
22768 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22769 std::is_nothrow_move_assignable<json_value>::value
22770 )
22771 {
22772 std::swap(m_data.m_type, other.m_data.m_type);
22773 std::swap(m_data.m_value, other.m_data.m_value);
22774
22775 set_parents();
22776 other.set_parents();
22777 assert_invariant();
22778 }
22779
22782 friend void swap(reference left, reference right) noexcept (
22783 std::is_nothrow_move_constructible<value_t>::value&&
22784 std::is_nothrow_move_assignable<value_t>::value&&
22785 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22786 std::is_nothrow_move_assignable<json_value>::value
22787 )
22788 {
22789 left.swap(right);
22790 }
22791
22794 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22795 {
22796 // swap only works for arrays
22797 if (JSON_HEDLEY_LIKELY(is_array()))
22798 {
22799 using std::swap;
22800 swap(*(m_data.m_value.array), other);
22801 }
22802 else
22803 {
22804 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
22805 }
22806 }
22807
22810 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22811 {
22812 // swap only works for objects
22813 if (JSON_HEDLEY_LIKELY(is_object()))
22814 {
22815 using std::swap;
22816 swap(*(m_data.m_value.object), other);
22817 }
22818 else
22819 {
22820 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
22821 }
22822 }
22823
22826 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22827 {
22828 // swap only works for strings
22829 if (JSON_HEDLEY_LIKELY(is_string()))
22830 {
22831 using std::swap;
22832 swap(*(m_data.m_value.string), other);
22833 }
22834 else
22835 {
22836 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
22837 }
22838 }
22839
22842 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22843 {
22844 // swap only works for strings
22845 if (JSON_HEDLEY_LIKELY(is_binary()))
22846 {
22847 using std::swap;
22848 swap(*(m_data.m_value.binary), other);
22849 }
22850 else
22851 {
22852 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
22853 }
22854 }
22855
22858 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
22859 {
22860 // swap only works for strings
22861 if (JSON_HEDLEY_LIKELY(is_binary()))
22862 {
22863 using std::swap;
22864 swap(*(m_data.m_value.binary), other);
22865 }
22866 else
22867 {
22868 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
22869 }
22870 }
22871
22873
22875 // lexicographical comparison operators //
22877
22880
22881 // note parentheses around operands are necessary; see
22882 // https://github.com/nlohmann/json/issues/1530
22883#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
22884 const auto lhs_type = lhs.type(); \
22885 const auto rhs_type = rhs.type(); \
22886 \
22887 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
22888 { \
22889 switch (lhs_type) \
22890 { \
22891 case value_t::array: \
22892 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
22893 \
22894 case value_t::object: \
22895 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
22896 \
22897 case value_t::null: \
22898 return (null_result); \
22899 \
22900 case value_t::string: \
22901 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
22902 \
22903 case value_t::boolean: \
22904 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
22905 \
22906 case value_t::number_integer: \
22907 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
22908 \
22909 case value_t::number_unsigned: \
22910 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
22911 \
22912 case value_t::number_float: \
22913 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
22914 \
22915 case value_t::binary: \
22916 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
22917 \
22918 case value_t::discarded: \
22919 default: \
22920 return (unordered_result); \
22921 } \
22922 } \
22923 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
22924 { \
22925 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
22926 } \
22927 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
22928 { \
22929 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
22930 } \
22931 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
22932 { \
22933 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
22934 } \
22935 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
22936 { \
22937 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
22938 } \
22939 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
22940 { \
22941 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
22942 } \
22943 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
22944 { \
22945 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
22946 } \
22947 else if(compares_unordered(lhs, rhs))\
22948 {\
22949 return (unordered_result);\
22950 }\
22951 \
22952 return (default_result);
22953
22954 JSON_PRIVATE_UNLESS_TESTED:
22955 // returns true if:
22956 // - any operand is NaN and the other operand is of number type
22957 // - any operand is discarded
22958 // in legacy mode, discarded values are considered ordered if
22959 // an operation is computed as an odd number of inverses of others
22960 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
22961 {
22962 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
22963 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
22964 {
22965 return true;
22966 }
22967#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22968 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
22969#else
22970 static_cast<void>(inverse);
22971 return lhs.is_discarded() || rhs.is_discarded();
22972#endif
22973 }
22974
22975 private:
22976 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
22977 {
22978 return compares_unordered(*this, rhs, inverse);
22979 }
22980
22981 public:
22982#if JSON_HAS_THREE_WAY_COMPARISON
22985 bool operator==(const_reference rhs) const noexcept
22986 {
22987#ifdef __GNUC__
22988#pragma GCC diagnostic push
22989#pragma GCC diagnostic ignored "-Wfloat-equal"
22990#endif
22991 const_reference lhs = *this;
22992 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
22993#ifdef __GNUC__
22994#pragma GCC diagnostic pop
22995#endif
22996 }
22997
23000 template<typename ScalarType>
23001 requires std::is_scalar_v<ScalarType>
23002 bool operator==(ScalarType rhs) const noexcept
23003 {
23004 return *this == basic_json(rhs);
23005 }
23006
23009 bool operator!=(const_reference rhs) const noexcept
23010 {
23011 if (compares_unordered(rhs, true))
23012 {
23013 return false;
23014 }
23015 return !operator==(rhs);
23016 }
23017
23020 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23021 {
23022 const_reference lhs = *this;
23023 // default_result is used if we cannot compare values. In that case,
23024 // we compare types.
23025 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23026 std::partial_ordering::equivalent,
23027 std::partial_ordering::unordered,
23028 lhs_type <=> rhs_type) // *NOPAD*
23029 }
23030
23033 template<typename ScalarType>
23034 requires std::is_scalar_v<ScalarType>
23035 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23036 {
23037 return *this <=> basic_json(rhs); // *NOPAD*
23038 }
23039
23040#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23041 // all operators that are computed as an odd number of inverses of others
23042 // need to be overloaded to emulate the legacy comparison behavior
23043
23046 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23047 bool operator<=(const_reference rhs) const noexcept
23048 {
23049 if (compares_unordered(rhs, true))
23050 {
23051 return false;
23052 }
23053 return !(rhs < *this);
23054 }
23055
23058 template<typename ScalarType>
23059 requires std::is_scalar_v<ScalarType>
23060 bool operator<=(ScalarType rhs) const noexcept
23061 {
23062 return *this <= basic_json(rhs);
23063 }
23064
23067 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23068 bool operator>=(const_reference rhs) const noexcept
23069 {
23070 if (compares_unordered(rhs, true))
23071 {
23072 return false;
23073 }
23074 return !(*this < rhs);
23075 }
23076
23079 template<typename ScalarType>
23080 requires std::is_scalar_v<ScalarType>
23081 bool operator>=(ScalarType rhs) const noexcept
23082 {
23083 return *this >= basic_json(rhs);
23084 }
23085#endif
23086#else
23089 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23090 {
23091#ifdef __GNUC__
23092#pragma GCC diagnostic push
23093#pragma GCC diagnostic ignored "-Wfloat-equal"
23094#endif
23095 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23096#ifdef __GNUC__
23097#pragma GCC diagnostic pop
23098#endif
23099 }
23100
23103 template<typename ScalarType, typename std::enable_if<
23104 std::is_scalar<ScalarType>::value, int>::type = 0>
23105 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23106 {
23107 return lhs == basic_json(rhs);
23108 }
23109
23112 template<typename ScalarType, typename std::enable_if<
23113 std::is_scalar<ScalarType>::value, int>::type = 0>
23114 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23115 {
23116 return basic_json(lhs) == rhs;
23117 }
23118
23121 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23122 {
23123 if (compares_unordered(lhs, rhs, true))
23124 {
23125 return false;
23126 }
23127 return !(lhs == rhs);
23128 }
23129
23132 template<typename ScalarType, typename std::enable_if<
23133 std::is_scalar<ScalarType>::value, int>::type = 0>
23134 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23135 {
23136 return lhs != basic_json(rhs);
23137 }
23138
23141 template<typename ScalarType, typename std::enable_if<
23142 std::is_scalar<ScalarType>::value, int>::type = 0>
23143 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23144 {
23145 return basic_json(lhs) != rhs;
23146 }
23147
23150 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23151 {
23152 // default_result is used if we cannot compare values. In that case,
23153 // we compare types. Note we have to call the operator explicitly,
23154 // because MSVC has problems otherwise.
23155 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23156 }
23157
23160 template<typename ScalarType, typename std::enable_if<
23161 std::is_scalar<ScalarType>::value, int>::type = 0>
23162 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23163 {
23164 return lhs < basic_json(rhs);
23165 }
23166
23169 template<typename ScalarType, typename std::enable_if<
23170 std::is_scalar<ScalarType>::value, int>::type = 0>
23171 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23172 {
23173 return basic_json(lhs) < rhs;
23174 }
23175
23178 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23179 {
23180 if (compares_unordered(lhs, rhs, true))
23181 {
23182 return false;
23183 }
23184 return !(rhs < lhs);
23185 }
23186
23189 template<typename ScalarType, typename std::enable_if<
23190 std::is_scalar<ScalarType>::value, int>::type = 0>
23191 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23192 {
23193 return lhs <= basic_json(rhs);
23194 }
23195
23198 template<typename ScalarType, typename std::enable_if<
23199 std::is_scalar<ScalarType>::value, int>::type = 0>
23200 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23201 {
23202 return basic_json(lhs) <= rhs;
23203 }
23204
23207 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
23208 {
23209 // double inverse
23210 if (compares_unordered(lhs, rhs))
23211 {
23212 return false;
23213 }
23214 return !(lhs <= rhs);
23215 }
23216
23219 template<typename ScalarType, typename std::enable_if<
23220 std::is_scalar<ScalarType>::value, int>::type = 0>
23221 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
23222 {
23223 return lhs > basic_json(rhs);
23224 }
23225
23228 template<typename ScalarType, typename std::enable_if<
23229 std::is_scalar<ScalarType>::value, int>::type = 0>
23230 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
23231 {
23232 return basic_json(lhs) > rhs;
23233 }
23234
23237 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
23238 {
23239 if (compares_unordered(lhs, rhs, true))
23240 {
23241 return false;
23242 }
23243 return !(lhs < rhs);
23244 }
23245
23248 template<typename ScalarType, typename std::enable_if<
23249 std::is_scalar<ScalarType>::value, int>::type = 0>
23250 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
23251 {
23252 return lhs >= basic_json(rhs);
23253 }
23254
23257 template<typename ScalarType, typename std::enable_if<
23258 std::is_scalar<ScalarType>::value, int>::type = 0>
23259 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
23260 {
23261 return basic_json(lhs) >= rhs;
23262 }
23263#endif
23264
23265#undef JSON_IMPLEMENT_OPERATOR
23266
23268
23270 // serialization //
23272
23275#ifndef JSON_NO_IO
23278 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
23279 {
23280 // read width member and use it as indentation parameter if nonzero
23281 const bool pretty_print = o.width() > 0;
23282 const auto indentation = pretty_print ? o.width() : 0;
23283
23284 // reset width to 0 for subsequent calls to this stream
23285 o.width(0);
23286
23287 // do the actual serialization
23288 serializer s(detail::output_adapter<char>(o), o.fill());
23289 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
23290 return o;
23291 }
23292
23299 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
23300 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
23301 {
23302 return o << j;
23303 }
23304#endif // JSON_NO_IO
23306
23308 // deserialization //
23310
23313
23316 template<typename InputType>
23317 JSON_HEDLEY_WARN_UNUSED_RESULT
23318 static basic_json parse(InputType&& i,
23319 const parser_callback_t cb = nullptr,
23320 const bool allow_exceptions = true,
23321 const bool ignore_comments = false)
23322 {
23323 basic_json result;
23324 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
23325 return result;
23326 }
23327
23330 template<typename IteratorType>
23331 JSON_HEDLEY_WARN_UNUSED_RESULT
23332 static basic_json parse(IteratorType first,
23333 IteratorType last,
23334 const parser_callback_t cb = nullptr,
23335 const bool allow_exceptions = true,
23336 const bool ignore_comments = false)
23337 {
23338 basic_json result;
23339 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
23340 return result;
23341 }
23342
23343 JSON_HEDLEY_WARN_UNUSED_RESULT
23344 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
23345 static basic_json parse(detail::span_input_adapter&& i,
23346 const parser_callback_t cb = nullptr,
23347 const bool allow_exceptions = true,
23348 const bool ignore_comments = false)
23349 {
23350 basic_json result;
23351 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
23352 return result;
23353 }
23354
23357 template<typename InputType>
23358 static bool accept(InputType&& i,
23359 const bool ignore_comments = false)
23360 {
23361 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
23362 }
23363
23366 template<typename IteratorType>
23367 static bool accept(IteratorType first, IteratorType last,
23368 const bool ignore_comments = false)
23369 {
23370 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
23371 }
23372
23373 JSON_HEDLEY_WARN_UNUSED_RESULT
23374 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
23375 static bool accept(detail::span_input_adapter&& i,
23376 const bool ignore_comments = false)
23377 {
23378 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
23379 }
23380
23383 template <typename InputType, typename SAX>
23384 JSON_HEDLEY_NON_NULL(2)
23385 static bool sax_parse(InputType&& i, SAX* sax,
23386 input_format_t format = input_format_t::json,
23387 const bool strict = true,
23388 const bool ignore_comments = false)
23389 {
23390 auto ia = detail::input_adapter(std::forward<InputType>(i));
23391 return format == input_format_t::json
23392 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23393 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23394 }
23395
23398 template<class IteratorType, class SAX>
23399 JSON_HEDLEY_NON_NULL(3)
23400 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23401 input_format_t format = input_format_t::json,
23402 const bool strict = true,
23403 const bool ignore_comments = false)
23404 {
23405 auto ia = detail::input_adapter(std::move(first), std::move(last));
23406 return format == input_format_t::json
23407 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23408 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23409 }
23410
23416 template <typename SAX>
23417 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23418 JSON_HEDLEY_NON_NULL(2)
23419 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
23420 input_format_t format = input_format_t::json,
23421 const bool strict = true,
23422 const bool ignore_comments = false)
23423 {
23424 auto ia = i.get();
23425 return format == input_format_t::json
23426 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23427 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23428 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23429 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23430 }
23431#ifndef JSON_NO_IO
23438 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
23439 friend std::istream& operator<<(basic_json& j, std::istream& i)
23440 {
23441 return operator>>(i, j);
23442 }
23443
23446 friend std::istream& operator>>(std::istream& i, basic_json& j)
23447 {
23448 parser(detail::input_adapter(i)).parse(false, j);
23449 return i;
23450 }
23451#endif // JSON_NO_IO
23453
23455 // convenience functions //
23457
23460 JSON_HEDLEY_RETURNS_NON_NULL
23461 const char* type_name() const noexcept
23462 {
23463 switch (m_data.m_type)
23464 {
23465 case value_t::null:
23466 return "null";
23467 case value_t::object:
23468 return "object";
23469 case value_t::array:
23470 return "array";
23471 case value_t::string:
23472 return "string";
23473 case value_t::boolean:
23474 return "boolean";
23475 case value_t::binary:
23476 return "binary";
23477 case value_t::discarded:
23478 return "discarded";
23479 case value_t::number_integer:
23480 case value_t::number_unsigned:
23481 case value_t::number_float:
23482 default:
23483 return "number";
23484 }
23485 }
23486
23487 JSON_PRIVATE_UNLESS_TESTED:
23489 // member variables //
23491
23492 struct data
23493 {
23495 value_t m_type = value_t::null;
23496
23498 json_value m_value = {};
23499
23500 data(const value_t v)
23501 : m_type(v), m_value(v)
23502 {
23503 }
23504
23505 data(size_type cnt, const basic_json& val)
23506 : m_type(value_t::array)
23507 {
23508 m_value.array = create<array_t>(cnt, val);
23509 }
23510
23511 data() noexcept = default;
23512 data(data&&) noexcept = default;
23513 data(const data&) noexcept = delete;
23514 data& operator=(data&&) noexcept = delete;
23515 data& operator=(const data&) noexcept = delete;
23516
23517 ~data() noexcept
23518 {
23519 m_value.destroy(m_type);
23520 }
23521 };
23522
23523 data m_data = {};
23524
23525#if JSON_DIAGNOSTICS
23527 basic_json* m_parent = nullptr;
23528#endif
23529
23531 // binary serialization/deserialization //
23533
23536
23537 public:
23540 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
23541 {
23542 std::vector<std::uint8_t> result;
23543 to_cbor(j, result);
23544 return result;
23545 }
23546
23550 {
23551 binary_writer<std::uint8_t>(o).write_cbor(j);
23552 }
23553
23557 {
23558 binary_writer<char>(o).write_cbor(j);
23559 }
23560
23563 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
23564 {
23565 std::vector<std::uint8_t> result;
23566 to_msgpack(j, result);
23567 return result;
23568 }
23569
23573 {
23574 binary_writer<std::uint8_t>(o).write_msgpack(j);
23575 }
23576
23580 {
23581 binary_writer<char>(o).write_msgpack(j);
23582 }
23583
23586 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
23587 const bool use_size = false,
23588 const bool use_type = false)
23589 {
23590 std::vector<std::uint8_t> result;
23591 to_ubjson(j, result, use_size, use_type);
23592 return result;
23593 }
23594
23598 const bool use_size = false, const bool use_type = false)
23599 {
23600 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
23601 }
23602
23606 const bool use_size = false, const bool use_type = false)
23607 {
23608 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23609 }
23610
23613 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
23614 const bool use_size = false,
23615 const bool use_type = false)
23616 {
23617 std::vector<std::uint8_t> result;
23618 to_bjdata(j, result, use_size, use_type);
23619 return result;
23620 }
23621
23625 const bool use_size = false, const bool use_type = false)
23626 {
23627 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
23628 }
23629
23633 const bool use_size = false, const bool use_type = false)
23634 {
23635 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
23636 }
23637
23640 static std::vector<std::uint8_t> to_bson(const basic_json& j)
23641 {
23642 std::vector<std::uint8_t> result;
23643 to_bson(j, result);
23644 return result;
23645 }
23646
23650 {
23651 binary_writer<std::uint8_t>(o).write_bson(j);
23652 }
23653
23657 {
23658 binary_writer<char>(o).write_bson(j);
23659 }
23660
23663 template<typename InputType>
23664 JSON_HEDLEY_WARN_UNUSED_RESULT
23665 static basic_json from_cbor(InputType&& i,
23666 const bool strict = true,
23667 const bool allow_exceptions = true,
23668 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23669 {
23670 basic_json result;
23671 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23672 auto ia = detail::input_adapter(std::forward<InputType>(i));
23673 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23674 return res ? result : basic_json(value_t::discarded);
23675 }
23676
23679 template<typename IteratorType>
23680 JSON_HEDLEY_WARN_UNUSED_RESULT
23681 static basic_json from_cbor(IteratorType first, IteratorType last,
23682 const bool strict = true,
23683 const bool allow_exceptions = true,
23684 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23685 {
23686 basic_json result;
23687 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23688 auto ia = detail::input_adapter(std::move(first), std::move(last));
23689 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23690 return res ? result : basic_json(value_t::discarded);
23691 }
23692
23693 template<typename T>
23694 JSON_HEDLEY_WARN_UNUSED_RESULT
23695 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23696 static basic_json from_cbor(const T* ptr, std::size_t len,
23697 const bool strict = true,
23698 const bool allow_exceptions = true,
23699 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23700 {
23701 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23702 }
23703
23704 JSON_HEDLEY_WARN_UNUSED_RESULT
23705 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23706 static basic_json from_cbor(detail::span_input_adapter&& i,
23707 const bool strict = true,
23708 const bool allow_exceptions = true,
23709 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23710 {
23711 basic_json result;
23712 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23713 auto ia = i.get();
23714 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23715 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23716 return res ? result : basic_json(value_t::discarded);
23717 }
23718
23721 template<typename InputType>
23722 JSON_HEDLEY_WARN_UNUSED_RESULT
23723 static basic_json from_msgpack(InputType&& i,
23724 const bool strict = true,
23725 const bool allow_exceptions = true)
23726 {
23727 basic_json result;
23728 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23729 auto ia = detail::input_adapter(std::forward<InputType>(i));
23730 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23731 return res ? result : basic_json(value_t::discarded);
23732 }
23733
23736 template<typename IteratorType>
23737 JSON_HEDLEY_WARN_UNUSED_RESULT
23738 static basic_json from_msgpack(IteratorType first, IteratorType last,
23739 const bool strict = true,
23740 const bool allow_exceptions = true)
23741 {
23742 basic_json result;
23743 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23744 auto ia = detail::input_adapter(std::move(first), std::move(last));
23745 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23746 return res ? result : basic_json(value_t::discarded);
23747 }
23748
23749 template<typename T>
23750 JSON_HEDLEY_WARN_UNUSED_RESULT
23751 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23752 static basic_json from_msgpack(const T* ptr, std::size_t len,
23753 const bool strict = true,
23754 const bool allow_exceptions = true)
23755 {
23756 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
23757 }
23758
23759 JSON_HEDLEY_WARN_UNUSED_RESULT
23760 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23761 static basic_json from_msgpack(detail::span_input_adapter&& i,
23762 const bool strict = true,
23763 const bool allow_exceptions = true)
23764 {
23765 basic_json result;
23766 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23767 auto ia = i.get();
23768 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23769 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23770 return res ? result : basic_json(value_t::discarded);
23771 }
23772
23775 template<typename InputType>
23776 JSON_HEDLEY_WARN_UNUSED_RESULT
23777 static basic_json from_ubjson(InputType&& i,
23778 const bool strict = true,
23779 const bool allow_exceptions = true)
23780 {
23781 basic_json result;
23782 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23783 auto ia = detail::input_adapter(std::forward<InputType>(i));
23784 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23785 return res ? result : basic_json(value_t::discarded);
23786 }
23787
23790 template<typename IteratorType>
23791 JSON_HEDLEY_WARN_UNUSED_RESULT
23792 static basic_json from_ubjson(IteratorType first, IteratorType last,
23793 const bool strict = true,
23794 const bool allow_exceptions = true)
23795 {
23796 basic_json result;
23797 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23798 auto ia = detail::input_adapter(std::move(first), std::move(last));
23799 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23800 return res ? result : basic_json(value_t::discarded);
23801 }
23802
23803 template<typename T>
23804 JSON_HEDLEY_WARN_UNUSED_RESULT
23805 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23806 static basic_json from_ubjson(const T* ptr, std::size_t len,
23807 const bool strict = true,
23808 const bool allow_exceptions = true)
23809 {
23810 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
23811 }
23812
23813 JSON_HEDLEY_WARN_UNUSED_RESULT
23814 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23815 static basic_json from_ubjson(detail::span_input_adapter&& i,
23816 const bool strict = true,
23817 const bool allow_exceptions = true)
23818 {
23819 basic_json result;
23820 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23821 auto ia = i.get();
23822 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23823 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23824 return res ? result : basic_json(value_t::discarded);
23825 }
23826
23829 template<typename InputType>
23830 JSON_HEDLEY_WARN_UNUSED_RESULT
23831 static basic_json from_bjdata(InputType&& i,
23832 const bool strict = true,
23833 const bool allow_exceptions = true)
23834 {
23835 basic_json result;
23836 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23837 auto ia = detail::input_adapter(std::forward<InputType>(i));
23838 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23839 return res ? result : basic_json(value_t::discarded);
23840 }
23841
23844 template<typename IteratorType>
23845 JSON_HEDLEY_WARN_UNUSED_RESULT
23846 static basic_json from_bjdata(IteratorType first, IteratorType last,
23847 const bool strict = true,
23848 const bool allow_exceptions = true)
23849 {
23850 basic_json result;
23851 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23852 auto ia = detail::input_adapter(std::move(first), std::move(last));
23853 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23854 return res ? result : basic_json(value_t::discarded);
23855 }
23856
23859 template<typename InputType>
23860 JSON_HEDLEY_WARN_UNUSED_RESULT
23861 static basic_json from_bson(InputType&& i,
23862 const bool strict = true,
23863 const bool allow_exceptions = true)
23864 {
23865 basic_json result;
23866 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23867 auto ia = detail::input_adapter(std::forward<InputType>(i));
23868 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23869 return res ? result : basic_json(value_t::discarded);
23870 }
23871
23874 template<typename IteratorType>
23875 JSON_HEDLEY_WARN_UNUSED_RESULT
23876 static basic_json from_bson(IteratorType first, IteratorType last,
23877 const bool strict = true,
23878 const bool allow_exceptions = true)
23879 {
23880 basic_json result;
23881 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23882 auto ia = detail::input_adapter(std::move(first), std::move(last));
23883 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23884 return res ? result : basic_json(value_t::discarded);
23885 }
23886
23887 template<typename T>
23888 JSON_HEDLEY_WARN_UNUSED_RESULT
23889 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23890 static basic_json from_bson(const T* ptr, std::size_t len,
23891 const bool strict = true,
23892 const bool allow_exceptions = true)
23893 {
23894 return from_bson(ptr, ptr + len, strict, allow_exceptions);
23895 }
23896
23897 JSON_HEDLEY_WARN_UNUSED_RESULT
23898 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23899 static basic_json from_bson(detail::span_input_adapter&& i,
23900 const bool strict = true,
23901 const bool allow_exceptions = true)
23902 {
23903 basic_json result;
23904 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23905 auto ia = i.get();
23906 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23907 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23908 return res ? result : basic_json(value_t::discarded);
23909 }
23911
23913 // JSON Pointer support //
23915
23918
23922 {
23923 return ptr.get_unchecked(this);
23924 }
23925
23926 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23927 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23928 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23929 {
23930 return ptr.get_unchecked(this);
23931 }
23932
23936 {
23937 return ptr.get_unchecked(this);
23938 }
23939
23940 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23941 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23942 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23943 {
23944 return ptr.get_unchecked(this);
23945 }
23946
23950 {
23951 return ptr.get_checked(this);
23952 }
23953
23954 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23955 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23956 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23957 {
23958 return ptr.get_checked(this);
23959 }
23960
23964 {
23965 return ptr.get_checked(this);
23966 }
23967
23968 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23969 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23970 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23971 {
23972 return ptr.get_checked(this);
23973 }
23974
23978 {
23979 basic_json result(value_t::object);
23980 json_pointer::flatten("", *this, result);
23981 return result;
23982 }
23983
23987 {
23988 return json_pointer::unflatten(*this);
23989 }
23990
23992
23994 // JSON Patch functions //
23996
23999
24002 void patch_inplace(const basic_json& json_patch)
24003 {
24004 basic_json& result = *this;
24005 // the valid JSON Patch operations
24006 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24007
24008 const auto get_op = [](const std::string & op)
24009 {
24010 if (op == "add")
24011 {
24012 return patch_operations::add;
24013 }
24014 if (op == "remove")
24015 {
24016 return patch_operations::remove;
24017 }
24018 if (op == "replace")
24019 {
24020 return patch_operations::replace;
24021 }
24022 if (op == "move")
24023 {
24024 return patch_operations::move;
24025 }
24026 if (op == "copy")
24027 {
24028 return patch_operations::copy;
24029 }
24030 if (op == "test")
24031 {
24032 return patch_operations::test;
24033 }
24034
24035 return patch_operations::invalid;
24036 };
24037
24038 // wrapper for "add" operation; add value at ptr
24039 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
24040 {
24041 // adding to the root of the target document means replacing it
24042 if (ptr.empty())
24043 {
24044 result = val;
24045 return;
24046 }
24047
24048 // make sure the top element of the pointer exists
24049 json_pointer const top_pointer = ptr.top();
24050 if (top_pointer != ptr)
24051 {
24052 result.at(top_pointer);
24053 }
24054
24055 // get reference to parent of JSON pointer ptr
24056 const auto last_path = ptr.back();
24057 ptr.pop_back();
24058 // parent must exist when performing patch add per RFC6902 specs
24059 basic_json& parent = result.at(ptr);
24060
24061 switch (parent.m_data.m_type)
24062 {
24063 case value_t::null:
24064 case value_t::object:
24065 {
24066 // use operator[] to add value
24067 parent[last_path] = val;
24068 break;
24069 }
24070
24071 case value_t::array:
24072 {
24073 if (last_path == "-")
24074 {
24075 // special case: append to back
24076 parent.push_back(val);
24077 }
24078 else
24079 {
24080 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24081 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24082 {
24083 // avoid undefined behavior
24084 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24085 }
24086
24087 // default case: insert add offset
24088 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24089 }
24090 break;
24091 }
24092
24093 // if there exists a parent it cannot be primitive
24094 case value_t::string: // LCOV_EXCL_LINE
24095 case value_t::boolean: // LCOV_EXCL_LINE
24096 case value_t::number_integer: // LCOV_EXCL_LINE
24097 case value_t::number_unsigned: // LCOV_EXCL_LINE
24098 case value_t::number_float: // LCOV_EXCL_LINE
24099 case value_t::binary: // LCOV_EXCL_LINE
24100 case value_t::discarded: // LCOV_EXCL_LINE
24101 default: // LCOV_EXCL_LINE
24102 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24103 }
24104 };
24105
24106 // wrapper for "remove" operation; remove value at ptr
24107 const auto operation_remove = [this, & result](json_pointer & ptr)
24108 {
24109 // get reference to parent of JSON pointer ptr
24110 const auto last_path = ptr.back();
24111 ptr.pop_back();
24112 basic_json& parent = result.at(ptr);
24113
24114 // remove child
24115 if (parent.is_object())
24116 {
24117 // perform range check
24118 auto it = parent.find(last_path);
24119 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24120 {
24121 parent.erase(it);
24122 }
24123 else
24124 {
24125 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24126 }
24127 }
24128 else if (parent.is_array())
24129 {
24130 // note erase performs range check
24131 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24132 }
24133 };
24134
24135 // type check: top level value must be an array
24136 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24137 {
24138 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24139 }
24140
24141 // iterate and apply the operations
24142 for (const auto& val : json_patch)
24143 {
24144 // wrapper to get a value for an operation
24145 const auto get_value = [&val](const std::string & op,
24146 const std::string & member,
24147 bool string_type) -> basic_json &
24148 {
24149 // find value
24150 auto it = val.m_data.m_value.object->find(member);
24151
24152 // context-sensitive error message
24153 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
24154
24155 // check if desired value is present
24156 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24157 {
24158 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24159 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24160 }
24161
24162 // check if result is of type string
24163 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24164 {
24165 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24166 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24167 }
24168
24169 // no error: return value
24170 return it->second;
24171 };
24172
24173 // type check: every element of the array must be an object
24174 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24175 {
24176 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24177 }
24178
24179 // collect mandatory members
24180 const auto op = get_value("op", "op", true).template get<std::string>();
24181 const auto path = get_value(op, "path", true).template get<std::string>();
24182 json_pointer ptr(path);
24183
24184 switch (get_op(op))
24185 {
24186 case patch_operations::add:
24187 {
24188 operation_add(ptr, get_value("add", "value", false));
24189 break;
24190 }
24191
24192 case patch_operations::remove:
24193 {
24194 operation_remove(ptr);
24195 break;
24196 }
24197
24198 case patch_operations::replace:
24199 {
24200 // the "path" location must exist - use at()
24201 result.at(ptr) = get_value("replace", "value", false);
24202 break;
24203 }
24204
24205 case patch_operations::move:
24206 {
24207 const auto from_path = get_value("move", "from", true).template get<std::string>();
24208 json_pointer from_ptr(from_path);
24209
24210 // the "from" location must exist - use at()
24211 basic_json const v = result.at(from_ptr);
24212
24213 // The move operation is functionally identical to a
24214 // "remove" operation on the "from" location, followed
24215 // immediately by an "add" operation at the target
24216 // location with the value that was just removed.
24217 operation_remove(from_ptr);
24218 operation_add(ptr, v);
24219 break;
24220 }
24221
24222 case patch_operations::copy:
24223 {
24224 const auto from_path = get_value("copy", "from", true).template get<std::string>();
24225 const json_pointer from_ptr(from_path);
24226
24227 // the "from" location must exist - use at()
24228 basic_json const v = result.at(from_ptr);
24229
24230 // The copy is functionally identical to an "add"
24231 // operation at the target location using the value
24232 // specified in the "from" member.
24233 operation_add(ptr, v);
24234 break;
24235 }
24236
24237 case patch_operations::test:
24238 {
24239 bool success = false;
24240 JSON_TRY
24241 {
24242 // check if "value" matches the one at "path"
24243 // the "path" location must exist - use at()
24244 success = (result.at(ptr) == get_value("test", "value", false));
24245 }
24246 JSON_INTERNAL_CATCH (out_of_range&)
24247 {
24248 // ignore out of range errors: success remains false
24249 }
24250
24251 // throw an exception if test fails
24252 if (JSON_HEDLEY_UNLIKELY(!success))
24253 {
24254 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
24255 }
24256
24257 break;
24258 }
24259
24260 case patch_operations::invalid:
24261 default:
24262 {
24263 // op must be "add", "remove", "replace", "move", "copy", or
24264 // "test"
24265 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
24266 }
24267 }
24268 }
24269 }
24270
24273 basic_json patch(const basic_json& json_patch) const
24274 {
24275 basic_json result = *this;
24276 result.patch_inplace(json_patch);
24277 return result;
24278 }
24279
24282 JSON_HEDLEY_WARN_UNUSED_RESULT
24283 static basic_json diff(const basic_json& source, const basic_json& target,
24284 const std::string& path = "")
24285 {
24286 // the patch
24287 basic_json result(value_t::array);
24288
24289 // if the values are the same, return empty patch
24290 if (source == target)
24291 {
24292 return result;
24293 }
24294
24295 if (source.type() != target.type())
24296 {
24297 // different types: replace value
24298 result.push_back(
24299 {
24300 {"op", "replace"}, {"path", path}, {"value", target}
24301 });
24302 return result;
24303 }
24304
24305 switch (source.type())
24306 {
24307 case value_t::array:
24308 {
24309 // first pass: traverse common elements
24310 std::size_t i = 0;
24311 while (i < source.size() && i < target.size())
24312 {
24313 // recursive call to compare array values at index i
24314 auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
24315 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24316 ++i;
24317 }
24318
24319 // We now reached the end of at least one array
24320 // in a second pass, traverse the remaining elements
24321
24322 // remove my remaining elements
24323 const auto end_index = static_cast<difference_type>(result.size());
24324 while (i < source.size())
24325 {
24326 // add operations in reverse order to avoid invalid
24327 // indices
24328 result.insert(result.begin() + end_index, object(
24329 {
24330 {"op", "remove"},
24331 {"path", detail::concat(path, '/', std::to_string(i))}
24332 }));
24333 ++i;
24334 }
24335
24336 // add other remaining elements
24337 while (i < target.size())
24338 {
24339 result.push_back(
24340 {
24341 {"op", "add"},
24342 {"path", detail::concat(path, "/-")},
24343 {"value", target[i]}
24344 });
24345 ++i;
24346 }
24347
24348 break;
24349 }
24350
24351 case value_t::object:
24352 {
24353 // first pass: traverse this object's elements
24354 for (auto it = source.cbegin(); it != source.cend(); ++it)
24355 {
24356 // escape the key name to be used in a JSON patch
24357 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24358
24359 if (target.find(it.key()) != target.end())
24360 {
24361 // recursive call to compare object values at key it
24362 auto temp_diff = diff(it.value(), target[it.key()], path_key);
24363 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24364 }
24365 else
24366 {
24367 // found a key that is not in o -> remove it
24368 result.push_back(object(
24369 {
24370 {"op", "remove"}, {"path", path_key}
24371 }));
24372 }
24373 }
24374
24375 // second pass: traverse other object's elements
24376 for (auto it = target.cbegin(); it != target.cend(); ++it)
24377 {
24378 if (source.find(it.key()) == source.end())
24379 {
24380 // found a key that is not in this -> add it
24381 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24382 result.push_back(
24383 {
24384 {"op", "add"}, {"path", path_key},
24385 {"value", it.value()}
24386 });
24387 }
24388 }
24389
24390 break;
24391 }
24392
24393 case value_t::null:
24394 case value_t::string:
24395 case value_t::boolean:
24396 case value_t::number_integer:
24397 case value_t::number_unsigned:
24398 case value_t::number_float:
24399 case value_t::binary:
24400 case value_t::discarded:
24401 default:
24402 {
24403 // both primitive type: replace value
24404 result.push_back(
24405 {
24406 {"op", "replace"}, {"path", path}, {"value", target}
24407 });
24408 break;
24409 }
24410 }
24411
24412 return result;
24413 }
24415
24417 // JSON Merge Patch functions //
24419
24422
24425 void merge_patch(const basic_json& apply_patch)
24426 {
24427 if (apply_patch.is_object())
24428 {
24429 if (!is_object())
24430 {
24431 *this = object();
24432 }
24433 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
24434 {
24435 if (it.value().is_null())
24436 {
24437 erase(it.key());
24438 }
24439 else
24440 {
24441 operator[](it.key()).merge_patch(it.value());
24442 }
24443 }
24444 }
24445 else
24446 {
24447 *this = apply_patch;
24448 }
24449 }
24450
24452};
24453
24456NLOHMANN_BASIC_JSON_TPL_DECLARATION
24457std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
24458{
24459 return j.dump();
24460}
24461
24462inline namespace literals
24463{
24464inline namespace json_literals
24465{
24466
24469JSON_HEDLEY_NON_NULL(1)
24470#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24471 inline nlohmann::json operator ""_json(const char* s, std::size_t n)
24472#else
24473 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
24474#endif
24475{
24476 return nlohmann::json::parse(s, s + n);
24477}
24478
24481JSON_HEDLEY_NON_NULL(1)
24482#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24483 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
24484#else
24485 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
24486#endif
24487{
24488 return nlohmann::json::json_pointer(std::string(s, n));
24489}
24490
24491} // namespace json_literals
24492} // namespace literals
24493NLOHMANN_JSON_NAMESPACE_END
24494
24496// nonmember support //
24498
24499namespace std // NOLINT(cert-dcl58-cpp)
24500{
24501
24504NLOHMANN_BASIC_JSON_TPL_DECLARATION
24505struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
24506{
24507 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
24508 {
24509 return nlohmann::detail::hash(j);
24510 }
24511};
24512
24513// specialization for std::less<value_t>
24514template<>
24515struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
24516{
24521 bool operator()(::nlohmann::detail::value_t lhs,
24522 ::nlohmann::detail::value_t rhs) const noexcept
24523 {
24524#if JSON_HAS_THREE_WAY_COMPARISON
24525 return std::is_lt(lhs <=> rhs); // *NOPAD*
24526#else
24527 return ::nlohmann::detail::operator<(lhs, rhs);
24528#endif
24529 }
24530};
24531
24532// C++20 prohibit function specialization in the std namespace.
24533#ifndef JSON_HAS_CPP_20
24534
24537NLOHMANN_BASIC_JSON_TPL_DECLARATION
24538inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
24539 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
24540 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
24541{
24542 j1.swap(j2);
24543}
24544
24545#endif
24546
24547} // namespace std
24548
24549#if JSON_USE_GLOBAL_UDLS
24550 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24551 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24552 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24553 #else
24554 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24555 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24556 #endif
24557#endif
24558
24559// #include <nlohmann/detail/macro_unscope.hpp>
24560// __ _____ _____ _____
24561// __| | __| | | | JSON for Modern C++
24562// | | |__ | | | | | | version 3.11.3
24563// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24564//
24565// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
24566// SPDX-License-Identifier: MIT
24567
24568
24569
24570// restore clang diagnostic settings
24571#if defined(__clang__)
24572 #pragma clang diagnostic pop
24573#endif
24574
24575// clean up
24576#undef JSON_ASSERT
24577#undef JSON_INTERNAL_CATCH
24578#undef JSON_THROW
24579#undef JSON_PRIVATE_UNLESS_TESTED
24580#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
24581#undef NLOHMANN_BASIC_JSON_TPL
24582#undef JSON_EXPLICIT
24583#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
24584#undef JSON_INLINE_VARIABLE
24585#undef JSON_NO_UNIQUE_ADDRESS
24586#undef JSON_DISABLE_ENUM_SERIALIZATION
24587#undef JSON_USE_GLOBAL_UDLS
24588
24589#ifndef JSON_TEST_KEEP_MACROS
24590 #undef JSON_CATCH
24591 #undef JSON_TRY
24592 #undef JSON_HAS_CPP_11
24593 #undef JSON_HAS_CPP_14
24594 #undef JSON_HAS_CPP_17
24595 #undef JSON_HAS_CPP_20
24596 #undef JSON_HAS_FILESYSTEM
24597 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
24598 #undef JSON_HAS_THREE_WAY_COMPARISON
24599 #undef JSON_HAS_RANGES
24600 #undef JSON_HAS_STATIC_RTTI
24601 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
24602#endif
24603
24604// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
24605// __ _____ _____ _____
24606// __| | __| | | | JSON for Modern C++
24607// | | |__ | | | | | | version 3.11.3
24608// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24609//
24610// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
24611// SPDX-License-Identifier: MIT
24612
24613
24614
24615#undef JSON_HEDLEY_ALWAYS_INLINE
24616#undef JSON_HEDLEY_ARM_VERSION
24617#undef JSON_HEDLEY_ARM_VERSION_CHECK
24618#undef JSON_HEDLEY_ARRAY_PARAM
24619#undef JSON_HEDLEY_ASSUME
24620#undef JSON_HEDLEY_BEGIN_C_DECLS
24621#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
24622#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
24623#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
24624#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
24625#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
24626#undef JSON_HEDLEY_CLANG_HAS_FEATURE
24627#undef JSON_HEDLEY_CLANG_HAS_WARNING
24628#undef JSON_HEDLEY_COMPCERT_VERSION
24629#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
24630#undef JSON_HEDLEY_CONCAT
24631#undef JSON_HEDLEY_CONCAT3
24632#undef JSON_HEDLEY_CONCAT3_EX
24633#undef JSON_HEDLEY_CONCAT_EX
24634#undef JSON_HEDLEY_CONST
24635#undef JSON_HEDLEY_CONSTEXPR
24636#undef JSON_HEDLEY_CONST_CAST
24637#undef JSON_HEDLEY_CPP_CAST
24638#undef JSON_HEDLEY_CRAY_VERSION
24639#undef JSON_HEDLEY_CRAY_VERSION_CHECK
24640#undef JSON_HEDLEY_C_DECL
24641#undef JSON_HEDLEY_DEPRECATED
24642#undef JSON_HEDLEY_DEPRECATED_FOR
24643#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
24644#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
24645#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
24646#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
24647#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
24648#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
24649#undef JSON_HEDLEY_DIAGNOSTIC_POP
24650#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
24651#undef JSON_HEDLEY_DMC_VERSION
24652#undef JSON_HEDLEY_DMC_VERSION_CHECK
24653#undef JSON_HEDLEY_EMPTY_BASES
24654#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
24655#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
24656#undef JSON_HEDLEY_END_C_DECLS
24657#undef JSON_HEDLEY_FLAGS
24658#undef JSON_HEDLEY_FLAGS_CAST
24659#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
24660#undef JSON_HEDLEY_GCC_HAS_BUILTIN
24661#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
24662#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
24663#undef JSON_HEDLEY_GCC_HAS_EXTENSION
24664#undef JSON_HEDLEY_GCC_HAS_FEATURE
24665#undef JSON_HEDLEY_GCC_HAS_WARNING
24666#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
24667#undef JSON_HEDLEY_GCC_VERSION
24668#undef JSON_HEDLEY_GCC_VERSION_CHECK
24669#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
24670#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
24671#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
24672#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
24673#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
24674#undef JSON_HEDLEY_GNUC_HAS_FEATURE
24675#undef JSON_HEDLEY_GNUC_HAS_WARNING
24676#undef JSON_HEDLEY_GNUC_VERSION
24677#undef JSON_HEDLEY_GNUC_VERSION_CHECK
24678#undef JSON_HEDLEY_HAS_ATTRIBUTE
24679#undef JSON_HEDLEY_HAS_BUILTIN
24680#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
24681#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
24682#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
24683#undef JSON_HEDLEY_HAS_EXTENSION
24684#undef JSON_HEDLEY_HAS_FEATURE
24685#undef JSON_HEDLEY_HAS_WARNING
24686#undef JSON_HEDLEY_IAR_VERSION
24687#undef JSON_HEDLEY_IAR_VERSION_CHECK
24688#undef JSON_HEDLEY_IBM_VERSION
24689#undef JSON_HEDLEY_IBM_VERSION_CHECK
24690#undef JSON_HEDLEY_IMPORT
24691#undef JSON_HEDLEY_INLINE
24692#undef JSON_HEDLEY_INTEL_CL_VERSION
24693#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
24694#undef JSON_HEDLEY_INTEL_VERSION
24695#undef JSON_HEDLEY_INTEL_VERSION_CHECK
24696#undef JSON_HEDLEY_IS_CONSTANT
24697#undef JSON_HEDLEY_IS_CONSTEXPR_
24698#undef JSON_HEDLEY_LIKELY
24699#undef JSON_HEDLEY_MALLOC
24700#undef JSON_HEDLEY_MCST_LCC_VERSION
24701#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
24702#undef JSON_HEDLEY_MESSAGE
24703#undef JSON_HEDLEY_MSVC_VERSION
24704#undef JSON_HEDLEY_MSVC_VERSION_CHECK
24705#undef JSON_HEDLEY_NEVER_INLINE
24706#undef JSON_HEDLEY_NON_NULL
24707#undef JSON_HEDLEY_NO_ESCAPE
24708#undef JSON_HEDLEY_NO_RETURN
24709#undef JSON_HEDLEY_NO_THROW
24710#undef JSON_HEDLEY_NULL
24711#undef JSON_HEDLEY_PELLES_VERSION
24712#undef JSON_HEDLEY_PELLES_VERSION_CHECK
24713#undef JSON_HEDLEY_PGI_VERSION
24714#undef JSON_HEDLEY_PGI_VERSION_CHECK
24715#undef JSON_HEDLEY_PREDICT
24716#undef JSON_HEDLEY_PRINTF_FORMAT
24717#undef JSON_HEDLEY_PRIVATE
24718#undef JSON_HEDLEY_PUBLIC
24719#undef JSON_HEDLEY_PURE
24720#undef JSON_HEDLEY_REINTERPRET_CAST
24721#undef JSON_HEDLEY_REQUIRE
24722#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
24723#undef JSON_HEDLEY_REQUIRE_MSG
24724#undef JSON_HEDLEY_RESTRICT
24725#undef JSON_HEDLEY_RETURNS_NON_NULL
24726#undef JSON_HEDLEY_SENTINEL
24727#undef JSON_HEDLEY_STATIC_ASSERT
24728#undef JSON_HEDLEY_STATIC_CAST
24729#undef JSON_HEDLEY_STRINGIFY
24730#undef JSON_HEDLEY_STRINGIFY_EX
24731#undef JSON_HEDLEY_SUNPRO_VERSION
24732#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
24733#undef JSON_HEDLEY_TINYC_VERSION
24734#undef JSON_HEDLEY_TINYC_VERSION_CHECK
24735#undef JSON_HEDLEY_TI_ARMCL_VERSION
24736#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
24737#undef JSON_HEDLEY_TI_CL2000_VERSION
24738#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
24739#undef JSON_HEDLEY_TI_CL430_VERSION
24740#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
24741#undef JSON_HEDLEY_TI_CL6X_VERSION
24742#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
24743#undef JSON_HEDLEY_TI_CL7X_VERSION
24744#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
24745#undef JSON_HEDLEY_TI_CLPRU_VERSION
24746#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
24747#undef JSON_HEDLEY_TI_VERSION
24748#undef JSON_HEDLEY_TI_VERSION_CHECK
24749#undef JSON_HEDLEY_UNAVAILABLE
24750#undef JSON_HEDLEY_UNLIKELY
24751#undef JSON_HEDLEY_UNPREDICTABLE
24752#undef JSON_HEDLEY_UNREACHABLE
24753#undef JSON_HEDLEY_UNREACHABLE_RETURN
24754#undef JSON_HEDLEY_VERSION
24755#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
24756#undef JSON_HEDLEY_VERSION_DECODE_MINOR
24757#undef JSON_HEDLEY_VERSION_DECODE_REVISION
24758#undef JSON_HEDLEY_VERSION_ENCODE
24759#undef JSON_HEDLEY_WARNING
24760#undef JSON_HEDLEY_WARN_UNUSED_RESULT
24761#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
24762#undef JSON_HEDLEY_FALL_THROUGH
24763
24764
24765
24766#endif // INCLUDE_NLOHMANN_JSON_HPP_
namespace for Niels Lohmann
Definition json.hpp:20114
constexpr bool is_string() const noexcept
return whether value is a string
Definition json.h:20674
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.h:21907
std::size_t size_type
a type to represent container sizes
Definition json.h:19520
reference operator[](KeyType &&key)
access specified object element
Definition json.h:21475
size_type size() const noexcept
returns the number of elements
Definition json.h:22248
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.h:23681
BooleanType boolean_t
a type for a boolean
Definition json.h:19652
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.h:23613
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
get a (pointer) value (explicit)
Definition json.h:21047
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition json.h:22105
reference back()
access the last element
Definition json.h:21711
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value from compatible types
Definition json.h:20138
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.h:22121
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition json.h:24273
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
Definition json.h:23461
const_reference front() const
access the first element
Definition json.h:21704
constexpr bool is_array() const noexcept
return whether value is an array
Definition json.h:20667
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.h:22765
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.h:21655
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.h:22024
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.h:23632
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition json.h:20639
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.h:23876
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.h:23624
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.h:23921
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.h:20611
const_reference operator[](KeyType &&key) const
access specified object element
Definition json.h:21499
void swap(binary_t &other)
exchanges the values
Definition json.h:22842
ReferenceType get_ref()
get a reference value (implicit)
Definition json.h:21137
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.h:22287
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.h:22711
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.h:21148
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.h:20688
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.h:22503
AllocatorType< basic_json > allocator_type
the allocator type
Definition json.h:19523
void push_back(basic_json &&val)
add an object to an array
Definition json.h:22391
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition json.h:21444
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.h:22193
const_reference back() const
access the last element
Definition json.h:21720
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.h:21802
reference operator+=(const basic_json &val)
add an object to an array
Definition json.h:22448
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.h:22782
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.h:23777
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.h:20275
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition json.h:22615
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.h:23861
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.h:19543
reference at(KeyType &&key)
access specified object element with bounds checking
Definition json.h:21307
iterator end() noexcept
returns an iterator to one past the last element
Definition json.h:22096
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.h:20646
void update(const_iterator first, const_iterator last, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.h:22718
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition json.h:23640
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition json.h:22128
void push_back(initializer_list_t init)
add an object to an object
Definition json.h:22487
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.h:20316
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
create a MessagePack serialization of a given JSON value
Definition json.h:23579
iterator begin() noexcept
returns an iterator to the first element
Definition json.h:22071
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition json.h:21554
const_iterator cend() const noexcept
returns an iterator to one past the last element
Definition json.h:22112
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.h:23831
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.h:23963
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition json.h:20286
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.h:20126
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.h:23665
basic_json flatten() const
return flattened JSON value
Definition json.h:23977
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.h:23792
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition json.h:21918
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition json.h:19644
ObjectType< StringType, basic_json, default_object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
Definition json.h:19636
const binary_t & get_binary() const
get a binary value
Definition json.h:21219
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition json.h:22635
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition json.h:24002
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.h:21607
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.h:24283
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.h:23935
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition json.h:19477
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition json.h:19535
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition json.h:22041
detail::actual_object_comparator_t< basic_json > object_comparator_t
object key comparator type
Definition json.h:19672
static void to_cbor(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a CBOR serialization of a given JSON value
Definition json.h:23549
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
create a BSON serialization of a given JSON value
Definition json.h:23656
iterator find(const typename object_t::key_type &key)
find an element in a JSON object
Definition json.h:21954
::nlohmann::json_pointer< StringType > json_pointer
JSON Pointer, see nlohmann::json_pointer.
Definition json.h:19469
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
Definition json.h:20264
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition json.h:21345
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.h:19551
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.h:20323
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition json.h:21968
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.h:23540
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.h:21732
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition json.h:19528
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition json.h:22588
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.h:21529
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition json.h:20575
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.h:24425
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition json.h:21101
reference at(size_type idx)
access specified array element with bounds checking
Definition json.h:21241
iterator find(KeyType &&key)
find an element in a JSON object
Definition json.h:21984
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition json.h:20653
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.h:22135
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.h:23586
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.h:23949
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.h:22479
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition json.h:22087
reference operator[](typename object_t::key_type key)
access specified object element
Definition json.h:21422
std::less< StringType > default_object_comparator_t
default object key comparator type The actual object key comparator type (object_comparator_t) may be...
Definition json.h:19631
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.h:20859
~basic_json() noexcept
destructor
Definition json.h:20557
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition json.h:19526
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition json.h:22156
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition json.h:19660
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition json.h:20205
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.h:22858
binary_t & get_binary()
get a binary value
Definition json.h:21207
iter_impl< const basic_json > const_iterator
a const iterator for a basic_json container
Definition json.h:19533
const_iterator begin() const noexcept
returns an iterator to the first element
Definition json.h:22080
constexpr bool is_number() const noexcept
return whether value is a number
Definition json.h:20632
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition json.h:22686
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.h:23723
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.h:21088
NumberIntegerType number_integer_t
a type for a number (integer)
Definition json.h:19656
reference operator[](size_type idx)
access specified array element
Definition json.h:21363
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value &&std::is_nothrow_move_assignable< json_base_class_t >::value)
copy assignment
Definition json.h:20534
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.h:23605
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.h:20848
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.h:21325
constexpr bool is_binary() const noexcept
return whether value is a binary array
Definition json.h:20681
void swap(object_t &other)
exchanges the values
Definition json.h:22810
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
Definition json.h:19668
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.h:23986
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition json.h:22666
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition json.h:19537
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.h:20297
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.h:22186
bool empty() const noexcept
checks whether the container is empty.
Definition json.h:22209
void swap(array_t &other)
exchanges the values
Definition json.h:22794
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.h:21925
StringType string_t
a type for a string
Definition json.h:19648
reference operator+=(basic_json &&val)
add an object to an array
Definition json.h:22416
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.h:22048
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.h:20597
reference emplace_back(Args &&... args)
add an object to an array
Definition json.h:22512
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.h:21630
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.h:20308
void push_back(const basic_json &val)
add an object to an array
Definition json.h:22424
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition json.h:21580
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.h:21287
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.h:23846
json_value m_value
the value of the current element
Definition json.h:23498
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.h:22149
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition json.h:20625
size_type count(const typename object_t::key_type &key) const
returns the number of occurrences of a key in a JSON object
Definition json.h:22014
iter_impl< basic_json > iterator
an iterator for a basic_json container
Definition json.h:19531
reference front()
access the first element
Definition json.h:21697
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.h:20604
constexpr bool is_null() const noexcept
return whether value is null
Definition json.h:20618
void clear() noexcept
clears the contents
Definition json.h:22330
static void to_ubjson(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.h:23597
basic_json(basic_json &&other) noexcept
move constructor
Definition json.h:20517
basic_json(const value_t v)
create an empty value with a given type
Definition json.h:20118
const_reference operator[](size_type idx) const
access specified array element
Definition json.h:21409
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
Definition json.h:20105
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition json.h:22608
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition json.h:22142
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition json.h:23446
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.h:23563
void swap(string_t &other)
exchanges the values
Definition json.h:22826
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.h:20152
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.h:21264
basic_json(const basic_json &other)
copy constructor
Definition json.h:20448
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.h:22456
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.h:22537
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition json.h:19518
NumberFloatType number_float_t
a type for a number (floating-point)
Definition json.h:19664
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
create a CBOR serialization of a given JSON value
Definition json.h:23556
constexpr bool is_object() const noexcept
return whether value is an object
Definition json.h:20660
static void to_msgpack(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a MessagePack serialization of a given JSON value
Definition json.h:23572
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.h:23738
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition json.h:22569
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.h:20335
value_type & reference
the type of an element reference
Definition json.h:19513
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition json.h:22032
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a BSON serialization of a given JSON value
Definition json.h:23649
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition json.h:22000
an internal type for a backed binary type
Definition json.h:5892
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.h:5898
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.h:5920
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.h:5908
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.h:5947
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.h:5913
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.h:5954
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.h:5903
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.h:5939
void clear_subtype() noexcept
clears the binary subtype
Definition json.h:5961
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:9846
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.h:9229
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
Definition json.h:9250
serialization to CBOR and MessagePack values
Definition json.hpp:15787
void write_bson(const BasicJsonType &j)
Definition json.h:15100
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition json.h:15091
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.h:15779
void write_msgpack(const BasicJsonType &j)
Definition json.h:15453
void write_cbor(const BasicJsonType &j)
Definition json.h:15129
general exception of the basic_json class
Definition json.hpp:4511
const int id
the id of the exception
Definition json.h:4381
const char * what() const noexcept override
returns the explanatory string
Definition json.h:4375
exception indicating errors with iterators
Definition json.hpp:4680
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition json.hpp:13606
iter_impl operator+(difference_type i) const
add to iterator
Definition json.h:13491
std::bidirectional_iterator_tag iterator_category
Definition json.h:12942
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition json.h:12953
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.h:13054
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.h:13436
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.h:13044
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition json.h:12945
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.h:13383
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.h:13418
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.h:13482
iter_impl & operator--()
pre-decrement (–it)
Definition json.h:13297
const object_t::key_type & key() const
return the key of an object iterator
Definition json.h:13591
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.h:13338
iter_impl operator++(int) &
post-increment (it++)
Definition json.h:13235
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.h:13445
reference operator[](difference_type n) const
access to successor
Definition json.h:13553
pointer operator->() const
dereference the iterator
Definition json.h:13193
difference_type operator-(const iter_impl &other) const
return difference
Definition json.h:13524
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.h:13502
reference value() const
return the value of an iterator
Definition json.h:13607
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.h:13427
iter_impl & operator++()
pre-increment (++it)
Definition json.h:13246
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.h:13149
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.h:13513
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition json.h:12949
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.h:13029
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition json.h:13374
iter_impl operator--(int) &
post-decrement (it–)
Definition json.h:13286
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition json.h:12947
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.h:13019
void set_end() noexcept
set the iterator past the last value
Definition json.h:13110
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
Definition json.h:13616
Definition json.hpp:13586
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.h:5251
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.h:5257
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.h:5234
IteratorType::reference value() const
return value of the iterator
Definition json.h:5299
const string_type & key() const
return key of the iterator
Definition json.h:5263
proxy class for the items() function
Definition json.hpp:13585
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.h:5332
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.h:5316
Definition json.hpp:15519
a template for a reverse iterator class
Definition json.hpp:14368
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition json.h:13686
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition json.h:13698
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.h:13674
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.h:13692
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.h:13710
reference operator[](difference_type n) const
access to successor
Definition json.h:13734
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.h:13740
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.h:13728
reference value() const
return the value of an iterator
Definition json.h:13747
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.h:13683
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.h:13704
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.h:13722
typename Base::reference reference
the reference type for the pointed-to element
Definition json.h:13676
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.h:13679
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.h:13716
Definition json.hpp:9561
Definition json.hpp:9124
SAX implementation to create a JSON value from SAX events.
Definition json.hpp:8818
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true)
Definition json.h:6814
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
Definition json.h:7435
token_type
token types for the parser
Definition json.h:7412
@ parse_error
indicating a parse error
lexical analysis
Definition json.hpp:7135
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.h:8859
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.h:8846
std::string get_token_string() const
Definition json.h:8821
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.h:8785
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.h:8813
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.h:8791
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.h:8803
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.h:8797
exception indicating other library errors
Definition json.hpp:4732
exception indicating access out of the defined range
Definition json.hpp:4715
Definition json.hpp:15738
output adapter for byte vectors
Definition json.hpp:15665
exception indicating a parse error
Definition json.hpp:4627
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
Definition json.h:4482
const std::size_t byte
byte index of the parse error
Definition json.h:4507
parser(InputAdapterType &&adapter, const 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.h:12240
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.h:12262
bool accept(const bool strict=true)
public accept interface
Definition json.h:12322
Definition json.hpp:13423
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition json.h:12763
void set_end() noexcept
set iterator to a defined past the end
Definition json.h:12757
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition json.h:12769
void set_begin() noexcept
set iterator to a defined beginning
Definition json.h:12751
Definition json.hpp:18773
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.h:18076
std::array< char, 64 > number_buffer
a (hopefully) large enough character buffer
Definition json.h:18975
const char thousands_sep
the locale's thousand separator character
Definition json.h:18980
const char decimal_point
the locale's decimal point character
Definition json.h:18982
const std::lconv * loc
the locale
Definition json.h:18978
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition json.h:18993
string_t indent_string
the indentation string
Definition json.h:18990
std::array< char, 512 > string_buffer
string buffer
Definition json.h:18985
const char indent_char
the indentation character
Definition json.h:18988
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition json.h:18116
Definition json.hpp:6969
exception indicating executing a member function with a wrong type
Definition json.hpp:4698
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition json.hpp:14540
friend json_pointer operator/(const json_pointer &lhs, string_t token)
create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
Definition json.h:13937
friend json_pointer operator/(const json_pointer &lhs, std::size_t array_idx)
create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
Definition json.h:13944
friend bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for equality
Definition json.h:14737
json_pointer(const string_t &s="")
create JSON pointer
Definition json.h:13868
bool empty() const noexcept
return whether pointer points to the root document
Definition json.h:14003
void pop_back()
remove last reference token
Definition json.h:13965
string_t to_string() const
return a string representation of the JSON pointer
Definition json.h:13874
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition json.h:13922
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition json.h:13996
friend bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointer for less-than
Definition json.h:14787
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition json.h:13904
friend json_pointer operator/(const json_pointer &lhs, const json_pointer &rhs)
create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
Definition json.h:13929
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition json.h:13951
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition json.h:13914
const string_t & back() const
return last reference token
Definition json.h:13977
friend bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for inequality
Definition json.h:14762
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition json.h:13895
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition json.h:13989
GLM_FUNC_QUALIFIER mat< C, R, T, Q > inverse(mat< C, R, T, Q > const &m)
Definition func_matrix.inl:388
GLM_FUNC_DECL GLM_CONSTEXPR genType e()
Definition constants.inl:102
uint64 uint64_t
Definition fwd.hpp:143
int64 int64_t
Definition fwd.hpp:85
uint32 uint32_t
Definition fwd.hpp:129
uint16 uint16_t
Definition fwd.hpp:115
detail::uint8 byte
Definition raw_data.hpp:34
GLM_FUNC_DECL std::string to_string(genType const &x)
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
Definition json.h:17400
cached_power get_cached_power_for_binary_exponent(int e)
Definition json.h:17236
boundaries compute_boundaries(FloatType value)
Definition json.h:17097
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition json.h:17736
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition json.h:17495
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition json.h:17836
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.h:17888
detail namespace with internal helper functions
Definition json.h:249
input_format_t
the supported input formats
Definition json.h:6177
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.h:17973
parse_event_t
Definition json.h:12204
@ 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
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition json.h:14960
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.h:2971
cbor_tag_handler_t
how to treat CBOR tags
Definition json.h:9186
@ store
store tags as binary type
@ error
throw a parse_error exception in case of a tag
value_t
the JSON type enumeration
Definition json.h:2873
@ 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::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition json.h:6023
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.h:2902
error_handler_t
how to treat decoding errors
Definition json.h:18053
@ 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
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.h:2990
namespace for Niels Lohmann
Definition json.hpp:6136
static auto to_json(BasicJsonType &j, TargetType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< TargetType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< TargetType >(val)), void())
convert any value type to a JSON value
Definition json.h:5858
static auto from_json(BasicJsonType &&j) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))
convert a JSON value to any value type
Definition json.h:5848
static auto from_json(BasicJsonType &&j, TargetType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
Definition json.h:5838
Definition json.hpp:3732
Definition json.hpp:3787
Definition json.hpp:17796
Definition json.hpp:17935
Definition json.hpp:17678
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition json.h:16990
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
Definition json.h:17072
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition json.h:17055
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition json.h:16978
Definition json.hpp:5693
Definition json.hpp:3654
Definition json.hpp:3679
Definition json.hpp:4776
an iterator value
Definition json.hpp:13539
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition json.h:12854
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition json.h:12856
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition json.h:12852
Definition json.hpp:3590
Definition json.hpp:4308
Definition json.hpp:4104
Definition json.hpp:4074
Definition json.hpp:3800
Definition json.hpp:311
Definition json.hpp:3662
Definition json.hpp:4161
Definition json.hpp:9751
Definition json.hpp:4094
Definition json.hpp:4330
Definition json.hpp:266
Definition json.hpp:3794
abstract output adapter interface
Definition json.hpp:15646
struct to capture the start position of the current token
Definition json.hpp:3163
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.h:3040
std::size_t lines_read
the number of lines read
Definition json.h:3042
std::size_t chars_read_total
the total number of characters read
Definition json.h:3038
Definition json.hpp:3333
Definition json.hpp:3339
SAX interface.
Definition json.h:6671
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
virtual bool end_array()=0
the end of an array was read
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
virtual bool null()=0
a null value was read
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
a minimal map-like container that preserves insertion order
Definition json.hpp:19747
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.h:24521