Template
json.hpp
Go to the documentation of this file.
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.11.2
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013-2022 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.2
38// |_____|_____|_____|_|___| https://github.com/nlohmann/json
39//
40// SPDX-FileCopyrightText: 2013-2022 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.2
51// |_____|_____|_____|_|___| https://github.com/nlohmann/json
52//
53// SPDX-FileCopyrightText: 2013-2022 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 != 2
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 2 // 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.2
153// |_____|_____|_____|_|___| https://github.com/nlohmann/json
154//
155// SPDX-FileCopyrightText: 2013-2022 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.2
176// |_____|_____|_____|_|___| https://github.com/nlohmann/json
177//
178// SPDX-FileCopyrightText: 2013-2022 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.2
196// |_____|_____|_____|_|___| https://github.com/nlohmann/json
197//
198// SPDX-FileCopyrightText: 2013-2022 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.2
212// |_____|_____|_____|_|___| https://github.com/nlohmann/json
213//
214// SPDX-FileCopyrightText: 2013-2022 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.2
224// |_____|_____|_____|_|___| https://github.com/nlohmann/json
225//
226// SPDX-FileCopyrightText: 2013-2022 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.2
237// |_____|_____|_____|_|___| https://github.com/nlohmann/json
238//
239// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
240// SPDX-License-Identifier: MIT
241
242
243
244// #include <nlohmann/detail/abi_macros.hpp>
245
246
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
259
260
262namespace detail
263{
264
265// https://en.cppreference.com/w/cpp/experimental/is_detected
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>
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>
313 std::is_convertible<detected_t<Op, Args...>, To>;
314
315} // namespace detail
317
318// #include <nlohmann/thirdparty/hedley/hedley.hpp>
319
320
321// __ _____ _____ _____
322// __| | __| | | | JSON for Modern C++
323// | | |__ | | | | | | version 3.11.2
324// |_____|_____|_____|_|___| https://github.com/nlohmann/json
325//
326// SPDX-FileCopyrightText: 2013-2022 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
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
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#ifdef JSON_HAS_CPP_17
2489 #define JSON_INLINE_VARIABLE inline
2490#else
2491 #define JSON_INLINE_VARIABLE
2492#endif
2493
2494#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2495 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2496#else
2497 #define JSON_NO_UNIQUE_ADDRESS
2498#endif
2499
2500// disable documentation warnings on clang
2501#if defined(__clang__)
2502 #pragma clang diagnostic push
2503 #pragma clang diagnostic ignored "-Wdocumentation"
2504 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2505#endif
2506
2507// allow disabling exceptions
2508#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2509 #define JSON_THROW(exception) throw exception
2510 #define JSON_TRY try
2511 #define JSON_CATCH(exception) catch(exception)
2512 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2513#else
2514 #include <cstdlib>
2515 #define JSON_THROW(exception) std::abort()
2516 #define JSON_TRY if(true)
2517 #define JSON_CATCH(exception) if(false)
2518 #define JSON_INTERNAL_CATCH(exception) if(false)
2519#endif
2520
2521// override exception macros
2522#if defined(JSON_THROW_USER)
2523 #undef JSON_THROW
2524 #define JSON_THROW JSON_THROW_USER
2525#endif
2526#if defined(JSON_TRY_USER)
2527 #undef JSON_TRY
2528 #define JSON_TRY JSON_TRY_USER
2529#endif
2530#if defined(JSON_CATCH_USER)
2531 #undef JSON_CATCH
2532 #define JSON_CATCH JSON_CATCH_USER
2533 #undef JSON_INTERNAL_CATCH
2534 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2535#endif
2536#if defined(JSON_INTERNAL_CATCH_USER)
2537 #undef JSON_INTERNAL_CATCH
2538 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2539#endif
2540
2541// allow overriding assert
2542#if !defined(JSON_ASSERT)
2543 #include <cassert> // assert
2544 #define JSON_ASSERT(x) assert(x)
2545#endif
2546
2547// allow to access some private functions (needed by the test suite)
2548#if defined(JSON_TESTS_PRIVATE)
2549 #define JSON_PRIVATE_UNLESS_TESTED public
2550#else
2551 #define JSON_PRIVATE_UNLESS_TESTED private
2552#endif
2553
2559#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2560 template<typename BasicJsonType> \
2561 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2562 { \
2563 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2564 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2565 auto it = std::find_if(std::begin(m), std::end(m), \
2566 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2567 { \
2568 return ej_pair.first == e; \
2569 }); \
2570 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2571 } \
2572 template<typename BasicJsonType> \
2573 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2574 { \
2575 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2576 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2577 auto it = std::find_if(std::begin(m), std::end(m), \
2578 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2579 { \
2580 return ej_pair.second == j; \
2581 }); \
2582 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2583 }
2584
2585// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2586// may be removed in the future once the class is split.
2587
2588#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2589 template<template<typename, typename, typename...> class ObjectType, \
2590 template<typename, typename...> class ArrayType, \
2591 class StringType, class BooleanType, class NumberIntegerType, \
2592 class NumberUnsignedType, class NumberFloatType, \
2593 template<typename> class AllocatorType, \
2594 template<typename, typename = void> class JSONSerializer, \
2595 class BinaryType, \
2596 class CustomBaseClass>
2597
2598#define NLOHMANN_BASIC_JSON_TPL \
2599 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2600 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2601 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2602
2603// Macros to simplify conversion from/to types
2604
2605#define NLOHMANN_JSON_EXPAND( x ) x
2606#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
2607#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2608 NLOHMANN_JSON_PASTE64, \
2609 NLOHMANN_JSON_PASTE63, \
2610 NLOHMANN_JSON_PASTE62, \
2611 NLOHMANN_JSON_PASTE61, \
2612 NLOHMANN_JSON_PASTE60, \
2613 NLOHMANN_JSON_PASTE59, \
2614 NLOHMANN_JSON_PASTE58, \
2615 NLOHMANN_JSON_PASTE57, \
2616 NLOHMANN_JSON_PASTE56, \
2617 NLOHMANN_JSON_PASTE55, \
2618 NLOHMANN_JSON_PASTE54, \
2619 NLOHMANN_JSON_PASTE53, \
2620 NLOHMANN_JSON_PASTE52, \
2621 NLOHMANN_JSON_PASTE51, \
2622 NLOHMANN_JSON_PASTE50, \
2623 NLOHMANN_JSON_PASTE49, \
2624 NLOHMANN_JSON_PASTE48, \
2625 NLOHMANN_JSON_PASTE47, \
2626 NLOHMANN_JSON_PASTE46, \
2627 NLOHMANN_JSON_PASTE45, \
2628 NLOHMANN_JSON_PASTE44, \
2629 NLOHMANN_JSON_PASTE43, \
2630 NLOHMANN_JSON_PASTE42, \
2631 NLOHMANN_JSON_PASTE41, \
2632 NLOHMANN_JSON_PASTE40, \
2633 NLOHMANN_JSON_PASTE39, \
2634 NLOHMANN_JSON_PASTE38, \
2635 NLOHMANN_JSON_PASTE37, \
2636 NLOHMANN_JSON_PASTE36, \
2637 NLOHMANN_JSON_PASTE35, \
2638 NLOHMANN_JSON_PASTE34, \
2639 NLOHMANN_JSON_PASTE33, \
2640 NLOHMANN_JSON_PASTE32, \
2641 NLOHMANN_JSON_PASTE31, \
2642 NLOHMANN_JSON_PASTE30, \
2643 NLOHMANN_JSON_PASTE29, \
2644 NLOHMANN_JSON_PASTE28, \
2645 NLOHMANN_JSON_PASTE27, \
2646 NLOHMANN_JSON_PASTE26, \
2647 NLOHMANN_JSON_PASTE25, \
2648 NLOHMANN_JSON_PASTE24, \
2649 NLOHMANN_JSON_PASTE23, \
2650 NLOHMANN_JSON_PASTE22, \
2651 NLOHMANN_JSON_PASTE21, \
2652 NLOHMANN_JSON_PASTE20, \
2653 NLOHMANN_JSON_PASTE19, \
2654 NLOHMANN_JSON_PASTE18, \
2655 NLOHMANN_JSON_PASTE17, \
2656 NLOHMANN_JSON_PASTE16, \
2657 NLOHMANN_JSON_PASTE15, \
2658 NLOHMANN_JSON_PASTE14, \
2659 NLOHMANN_JSON_PASTE13, \
2660 NLOHMANN_JSON_PASTE12, \
2661 NLOHMANN_JSON_PASTE11, \
2662 NLOHMANN_JSON_PASTE10, \
2663 NLOHMANN_JSON_PASTE9, \
2664 NLOHMANN_JSON_PASTE8, \
2665 NLOHMANN_JSON_PASTE7, \
2666 NLOHMANN_JSON_PASTE6, \
2667 NLOHMANN_JSON_PASTE5, \
2668 NLOHMANN_JSON_PASTE4, \
2669 NLOHMANN_JSON_PASTE3, \
2670 NLOHMANN_JSON_PASTE2, \
2671 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2672#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2673#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2674#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2675#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2676#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2677#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)
2678#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)
2679#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)
2680#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)
2681#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)
2682#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)
2683#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)
2684#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)
2685#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)
2686#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)
2687#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)
2688#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)
2689#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)
2690#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)
2691#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)
2692#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)
2693#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)
2694#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)
2695#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)
2696#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)
2697#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)
2698#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)
2699#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)
2700#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)
2701#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)
2702#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)
2703#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)
2704#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)
2705#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)
2706#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)
2707#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)
2708#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)
2709#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)
2710#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)
2711#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)
2712#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)
2713#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)
2714#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)
2715#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)
2716#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)
2717#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)
2718#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)
2719#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)
2720#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)
2721#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)
2722#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)
2723#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)
2724#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)
2725#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)
2726#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)
2727#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)
2728#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)
2729#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)
2730#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)
2731#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)
2732#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)
2733#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)
2734#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)
2735
2736#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2737#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2738#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2739
2745#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2746 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__)) } \
2747 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__)) }
2748
2749#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2750 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__)) } \
2751 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__)) }
2752
2758#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2759 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__)) } \
2760 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__)) }
2761
2762#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2763 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__)) } \
2764 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__)) }
2765
2766
2767// inspired from https://stackoverflow.com/a/26745591
2768// allows to call any std function as if (e.g. with begin):
2769// using std::begin; begin(x);
2770//
2771// it allows using the detected idiom to retrieve the return type
2772// of such an expression
2773#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2774 namespace detail { \
2775 using std::std_name; \
2776 \
2777 template<typename... T> \
2778 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2779 } \
2780 \
2781 namespace detail2 { \
2782 struct std_name##_tag \
2783 { \
2784 }; \
2785 \
2786 template<typename... T> \
2787 std_name##_tag std_name(T&&...); \
2788 \
2789 template<typename... T> \
2790 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2791 \
2792 template<typename... T> \
2793 struct would_call_std_##std_name \
2794 { \
2795 static constexpr auto const value = ::nlohmann::detail:: \
2796 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2797 }; \
2798 } /* namespace detail2 */ \
2799 \
2800 template<typename... T> \
2801 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2802 { \
2803 }
2804
2805#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2806 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2807#endif
2808
2809#if JSON_USE_IMPLICIT_CONVERSIONS
2810 #define JSON_EXPLICIT
2811#else
2812 #define JSON_EXPLICIT explicit
2813#endif
2814
2815#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2816 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2817#endif
2818
2819#ifndef JSON_USE_GLOBAL_UDLS
2820 #define JSON_USE_GLOBAL_UDLS 1
2821#endif
2822
2823#if JSON_HAS_THREE_WAY_COMPARISON
2824 #include <compare> // partial_ordering
2825#endif
2826
2828namespace detail
2829{
2830
2832// JSON type enumeration //
2834
2859enum class value_t : std::uint8_t
2860{
2861 null,
2862 object,
2863 array,
2864 string,
2865 boolean,
2868 number_float,
2869 binary,
2870 discarded
2871};
2872
2886#if JSON_HAS_THREE_WAY_COMPARISON
2887 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
2888#else
2889 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2890#endif
2891{
2892 static constexpr std::array<std::uint8_t, 9> order = {{
2893 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
2894 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
2895 6 /* binary */
2896 }
2897 };
2898
2899 const auto l_index = static_cast<std::size_t>(lhs);
2900 const auto r_index = static_cast<std::size_t>(rhs);
2901#if JSON_HAS_THREE_WAY_COMPARISON
2902 if (l_index < order.size() && r_index < order.size())
2903 {
2904 return order[l_index] <=> order[r_index]; // *NOPAD*
2905 }
2906 return std::partial_ordering::unordered;
2907#else
2908 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
2909#endif
2910}
2911
2912// GCC selects the built-in operator< over an operator rewritten from
2913// a user-defined spaceship operator
2914// Clang, MSVC, and ICC select the rewritten candidate
2915// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
2916#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
2917inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2918{
2919 return std::is_lt(lhs <=> rhs); // *NOPAD*
2920}
2921#endif
2922
2923} // namespace detail
2925
2926// #include <nlohmann/detail/string_escape.hpp>
2927// __ _____ _____ _____
2928// __| | __| | | | JSON for Modern C++
2929// | | |__ | | | | | | version 3.11.2
2930// |_____|_____|_____|_|___| https://github.com/nlohmann/json
2931//
2932// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
2933// SPDX-License-Identifier: MIT
2934
2935
2936
2937// #include <nlohmann/detail/abi_macros.hpp>
2938
2939
2941namespace detail
2942{
2943
2957template<typename StringType>
2958inline void replace_substring(StringType& s, const StringType& f,
2959 const StringType& t)
2960{
2961 JSON_ASSERT(!f.empty());
2962 for (auto pos = s.find(f); // find first occurrence of f
2963 pos != StringType::npos; // make sure f was found
2964 s.replace(pos, f.size(), t), // replace with t, and
2965 pos = s.find(f, pos + t.size())) // find next occurrence of f
2966 {}
2967}
2968
2976template<typename StringType>
2977inline StringType escape(StringType s)
2978{
2979 replace_substring(s, StringType{"~"}, StringType{"~0"});
2980 replace_substring(s, StringType{"/"}, StringType{"~1"});
2981 return s;
2982}
2983
2991template<typename StringType>
2992static void unescape(StringType& s)
2993{
2994 replace_substring(s, StringType{"~1"}, StringType{"/"});
2995 replace_substring(s, StringType{"~0"}, StringType{"~"});
2996}
2997
2998} // namespace detail
3000
3001// #include <nlohmann/detail/input/position_t.hpp>
3002// __ _____ _____ _____
3003// __| | __| | | | JSON for Modern C++
3004// | | |__ | | | | | | version 3.11.2
3005// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3006//
3007// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3008// SPDX-License-Identifier: MIT
3009
3010
3011
3012#include <cstddef> // size_t
3013
3014// #include <nlohmann/detail/abi_macros.hpp>
3015
3016
3018namespace detail
3019{
3020
3023{
3025 std::size_t chars_read_total = 0;
3029 std::size_t lines_read = 0;
3030
3032 constexpr operator size_t() const
3033 {
3034 return chars_read_total;
3035 }
3036};
3037
3038} // namespace detail
3040
3041// #include <nlohmann/detail/macro_scope.hpp>
3042
3043// #include <nlohmann/detail/meta/cpp_future.hpp>
3044// __ _____ _____ _____
3045// __| | __| | | | JSON for Modern C++
3046// | | |__ | | | | | | version 3.11.2
3047// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3048//
3049// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3050// SPDX-FileCopyrightText: 2018 The Abseil Authors
3051// SPDX-License-Identifier: MIT
3052
3053
3054
3055#include <array> // array
3056#include <cstddef> // size_t
3057#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3058#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3059
3060// #include <nlohmann/detail/macro_scope.hpp>
3061
3062
3064namespace detail
3065{
3066
3067template<typename T>
3068using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3069
3070#ifdef JSON_HAS_CPP_14
3071
3072// the following utilities are natively available in C++14
3073using std::enable_if_t;
3074using std::index_sequence;
3075using std::make_index_sequence;
3076using std::index_sequence_for;
3077
3078#else
3079
3080// alias templates to reduce boilerplate
3081template<bool B, typename T = void>
3082using enable_if_t = typename std::enable_if<B, T>::type;
3083
3084// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3085// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3086
3088
3089// integer_sequence
3090//
3091// Class template representing a compile-time integer sequence. An instantiation
3092// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3093// type through its template arguments (which is a common need when
3094// working with C++11 variadic templates). `absl::integer_sequence` is designed
3095// to be a drop-in replacement for C++14's `std::integer_sequence`.
3096//
3097// Example:
3098//
3099// template< class T, T... Ints >
3100// void user_function(integer_sequence<T, Ints...>);
3101//
3102// int main()
3103// {
3104// // user_function's `T` will be deduced to `int` and `Ints...`
3105// // will be deduced to `0, 1, 2, 3, 4`.
3106// user_function(make_integer_sequence<int, 5>());
3107// }
3108template <typename T, T... Ints>
3110{
3111 using value_type = T;
3112 static constexpr std::size_t size() noexcept
3113 {
3114 return sizeof...(Ints);
3115 }
3116};
3117
3118// index_sequence
3119//
3120// A helper template for an `integer_sequence` of `size_t`,
3121// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3122// `std::index_sequence`.
3123template <size_t... Ints>
3124using index_sequence = integer_sequence<size_t, Ints...>;
3125
3126namespace utility_internal
3127{
3128
3129template <typename Seq, size_t SeqSize, size_t Rem>
3130struct Extend;
3131
3132// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3133template <typename T, T... Ints, size_t SeqSize>
3134struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3135{
3136 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3137};
3138
3139template <typename T, T... Ints, size_t SeqSize>
3140struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3141{
3142 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3143};
3144
3145// Recursion helper for 'make_integer_sequence<T, N>'.
3146// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3147template <typename T, size_t N>
3148struct Gen
3149{
3150 using type =
3151 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3152};
3153
3154template <typename T>
3155struct Gen<T, 0>
3156{
3158};
3159
3160} // namespace utility_internal
3161
3162// Compile-time sequences of integers
3163
3164// make_integer_sequence
3165//
3166// This template alias is equivalent to
3167// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3168// replacement for C++14's `std::make_integer_sequence`.
3169template <typename T, T N>
3171
3172// make_index_sequence
3173//
3174// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3175// and is designed to be a drop-in replacement for C++14's
3176// `std::make_index_sequence`.
3177template <size_t N>
3179
3180// index_sequence_for
3181//
3182// Converts a typename pack into an index sequence of the same length, and
3183// is designed to be a drop-in replacement for C++14's
3184// `std::index_sequence_for()`
3185template <typename... Ts>
3187
3189
3190#endif
3191
3192// dispatch utility (taken from ranges-v3)
3193template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3194template<> struct priority_tag<0> {};
3195
3196// taken from ranges-v3
3197template<typename T>
3199{
3200 static JSON_INLINE_VARIABLE constexpr T value{};
3201};
3202
3203#ifndef JSON_HAS_CPP_17
3204 template<typename T>
3205 constexpr T static_const<T>::value;
3206#endif
3207
3208template<typename T, typename... Args>
3209inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3210{
3211 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3212}
3213
3214} // namespace detail
3216
3217// #include <nlohmann/detail/meta/type_traits.hpp>
3218// __ _____ _____ _____
3219// __| | __| | | | JSON for Modern C++
3220// | | |__ | | | | | | version 3.11.2
3221// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3222//
3223// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3224// SPDX-License-Identifier: MIT
3225
3226
3227
3228#include <limits> // numeric_limits
3229#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3230#include <utility> // declval
3231#include <tuple> // tuple
3232
3233// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3234// __ _____ _____ _____
3235// __| | __| | | | JSON for Modern C++
3236// | | |__ | | | | | | version 3.11.2
3237// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3238//
3239// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3240// SPDX-License-Identifier: MIT
3241
3242
3243
3244#include <iterator> // random_access_iterator_tag
3245
3246// #include <nlohmann/detail/abi_macros.hpp>
3247
3248// #include <nlohmann/detail/meta/void_t.hpp>
3249
3250// #include <nlohmann/detail/meta/cpp_future.hpp>
3251
3252
3254namespace detail
3255{
3256
3257template<typename It, typename = void>
3259
3260template<typename It>
3262 It,
3263 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3264 typename It::reference, typename It::iterator_category >>
3265{
3266 using difference_type = typename It::difference_type;
3267 using value_type = typename It::value_type;
3268 using pointer = typename It::pointer;
3269 using reference = typename It::reference;
3270 using iterator_category = typename It::iterator_category;
3271};
3272
3273// This is required as some compilers implement std::iterator_traits in a way that
3274// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3275template<typename T, typename = void>
3277{
3278};
3279
3280template<typename T>
3281struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3282 : iterator_types<T>
3283{
3284};
3285
3286template<typename T>
3288{
3289 using iterator_category = std::random_access_iterator_tag;
3290 using value_type = T;
3291 using difference_type = ptrdiff_t;
3292 using pointer = T*;
3293 using reference = T&;
3294};
3295
3296} // namespace detail
3298
3299// #include <nlohmann/detail/macro_scope.hpp>
3300
3301// #include <nlohmann/detail/meta/call_std/begin.hpp>
3302// __ _____ _____ _____
3303// __| | __| | | | JSON for Modern C++
3304// | | |__ | | | | | | version 3.11.2
3305// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3306//
3307// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3308// SPDX-License-Identifier: MIT
3309
3310
3311
3312// #include <nlohmann/detail/macro_scope.hpp>
3313
3314
3316
3318
3320
3321// #include <nlohmann/detail/meta/call_std/end.hpp>
3322// __ _____ _____ _____
3323// __| | __| | | | JSON for Modern C++
3324// | | |__ | | | | | | version 3.11.2
3325// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3326//
3327// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3328// SPDX-License-Identifier: MIT
3329
3330
3331
3332// #include <nlohmann/detail/macro_scope.hpp>
3333
3334
3336
3338
3340
3341// #include <nlohmann/detail/meta/cpp_future.hpp>
3342
3343// #include <nlohmann/detail/meta/detected.hpp>
3344
3345// #include <nlohmann/json_fwd.hpp>
3346// __ _____ _____ _____
3347// __| | __| | | | JSON for Modern C++
3348// | | |__ | | | | | | version 3.11.2
3349// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3350//
3351// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3352// SPDX-License-Identifier: MIT
3353
3354#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3355 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3356
3357 #include <cstdint> // int64_t, uint64_t
3358 #include <map> // map
3359 #include <memory> // allocator
3360 #include <string> // string
3361 #include <vector> // vector
3362
3363 // #include <nlohmann/detail/abi_macros.hpp>
3364
3365
3372
3380 template<typename T = void, typename SFINAE = void>
3381 struct adl_serializer;
3382
3385 template<template<typename U, typename V, typename... Args> class ObjectType =
3386 std::map,
3387 template<typename U, typename... Args> class ArrayType = std::vector,
3388 class StringType = std::string, class BooleanType = bool,
3389 class NumberIntegerType = std::int64_t,
3390 class NumberUnsignedType = std::uint64_t,
3391 class NumberFloatType = double,
3392 template<typename U> class AllocatorType = std::allocator,
3393 template<typename T, typename SFINAE = void> class JSONSerializer =
3395 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3396 class CustomBaseClass = void>
3397 class basic_json;
3398
3401 template<typename RefStringType>
3402 class json_pointer;
3403
3409
3412 template<class Key, class T, class IgnoredLess, class Allocator>
3413 struct ordered_map;
3414
3418
3420
3421#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3422
3423
3433namespace detail
3434{
3435
3437// helpers //
3439
3440// Note to maintainers:
3441//
3442// Every trait in this file expects a non CV-qualified type.
3443// The only exceptions are in the 'aliases for detected' section
3444// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3445//
3446// In this case, T has to be properly CV-qualified to constraint the function arguments
3447// (e.g. to_json(BasicJsonType&, const T&))
3448
3449template<typename> struct is_basic_json : std::false_type {};
3450
3452struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3453
3454// used by exceptions create() member functions
3455// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3456// false_type otherwise
3457template<typename BasicJsonContext>
3459 std::integral_constant < bool,
3460 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3461 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3462{};
3463
3465// json_ref helpers //
3467
3468template<typename>
3469class json_ref;
3470
3471template<typename>
3472struct is_json_ref : std::false_type {};
3473
3474template<typename T>
3475struct is_json_ref<json_ref<T>> : std::true_type {};
3476
3478// aliases for detected //
3480
3481template<typename T>
3482using mapped_type_t = typename T::mapped_type;
3483
3484template<typename T>
3485using key_type_t = typename T::key_type;
3486
3487template<typename T>
3488using value_type_t = typename T::value_type;
3489
3490template<typename T>
3491using difference_type_t = typename T::difference_type;
3492
3493template<typename T>
3494using pointer_t = typename T::pointer;
3495
3496template<typename T>
3497using reference_t = typename T::reference;
3498
3499template<typename T>
3500using iterator_category_t = typename T::iterator_category;
3501
3502template<typename T, typename... Args>
3503using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3504
3505template<typename T, typename... Args>
3506using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3507
3508template<typename T, typename U>
3509using get_template_function = decltype(std::declval<T>().template get<U>());
3510
3511// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3512template<typename BasicJsonType, typename T, typename = void>
3513struct has_from_json : std::false_type {};
3514
3515// trait checking if j.get<T> is valid
3516// use this trait instead of std::is_constructible or std::is_convertible,
3517// both rely on, or make use of implicit conversions, and thus fail when T
3518// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3519template <typename BasicJsonType, typename T>
3524
3525template<typename BasicJsonType, typename T>
3526struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3527{
3528 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3529
3530 static constexpr bool value =
3532 const BasicJsonType&, T&>::value;
3533};
3534
3535// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3536// this overload is used for non-default-constructible user-defined-types
3537template<typename BasicJsonType, typename T, typename = void>
3538struct has_non_default_from_json : std::false_type {};
3539
3540template<typename BasicJsonType, typename T>
3541struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3542{
3543 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3544
3545 static constexpr bool value =
3547 const BasicJsonType&>::value;
3548};
3549
3550// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3551// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3552template<typename BasicJsonType, typename T, typename = void>
3553struct has_to_json : std::false_type {};
3554
3555template<typename BasicJsonType, typename T>
3556struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3557{
3558 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3559
3560 static constexpr bool value =
3561 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3562 T>::value;
3563};
3564
3565template<typename T>
3566using detect_key_compare = typename T::key_compare;
3567
3568template<typename T>
3569struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3570
3571// obtains the actual object key comparator
3572template<typename BasicJsonType>
3574{
3575 using object_t = typename BasicJsonType::object_t;
3576 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3577 using type = typename std::conditional < has_key_compare<object_t>::value,
3578 typename object_t::key_compare, object_comparator_t>::type;
3579};
3580
3581template<typename BasicJsonType>
3583
3585// is_ functions //
3587
3588// https://en.cppreference.com/w/cpp/types/conjunction
3589template<class...> struct conjunction : std::true_type { };
3590template<class B> struct conjunction<B> : B { };
3591template<class B, class... Bn>
3592struct conjunction<B, Bn...>
3593: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3594
3595// https://en.cppreference.com/w/cpp/types/negation
3596template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3597
3598// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3599// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3600// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3601template <typename T>
3602struct is_default_constructible : std::is_default_constructible<T> {};
3603
3604template <typename T1, typename T2>
3605struct is_default_constructible<std::pair<T1, T2>>
3606 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3607
3608template <typename T1, typename T2>
3609struct is_default_constructible<const std::pair<T1, T2>>
3610 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3611
3612template <typename... Ts>
3613struct is_default_constructible<std::tuple<Ts...>>
3614 : conjunction<is_default_constructible<Ts>...> {};
3615
3616template <typename... Ts>
3617struct is_default_constructible<const std::tuple<Ts...>>
3618 : conjunction<is_default_constructible<Ts>...> {};
3619
3620
3621template <typename T, typename... Args>
3622struct is_constructible : std::is_constructible<T, Args...> {};
3623
3624template <typename T1, typename T2>
3625struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3626
3627template <typename T1, typename T2>
3628struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3629
3630template <typename... Ts>
3631struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3632
3633template <typename... Ts>
3634struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3635
3636
3637template<typename T, typename = void>
3638struct is_iterator_traits : std::false_type {};
3639
3640template<typename T>
3654
3655template<typename T>
3657{
3658 private:
3659 using t_ref = typename std::add_lvalue_reference<T>::type;
3660
3661 using iterator = detected_t<result_of_begin, t_ref>;
3662 using sentinel = detected_t<result_of_end, t_ref>;
3663
3664 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3665 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3666 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3667 static constexpr auto is_iterator_begin =
3669
3670 public:
3671 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3672};
3673
3674template<typename R>
3675using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3676
3677template<typename T>
3679
3680// The following implementation of is_complete_type is taken from
3681// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3682// and is written by Xiang Fan who agreed to using it in this library.
3683
3684template<typename T, typename = void>
3685struct is_complete_type : std::false_type {};
3686
3687template<typename T>
3688struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3689
3690template<typename BasicJsonType, typename CompatibleObjectType,
3691 typename = void>
3692struct is_compatible_object_type_impl : std::false_type {};
3693
3694template<typename BasicJsonType, typename CompatibleObjectType>
3696 BasicJsonType, CompatibleObjectType,
3697 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3698 is_detected<key_type_t, CompatibleObjectType>::value >>
3699{
3700 using object_t = typename BasicJsonType::object_t;
3701
3702 // macOS's is_constructible does not play well with nonesuch...
3703 static constexpr bool value =
3704 is_constructible<typename object_t::key_type,
3705 typename CompatibleObjectType::key_type>::value &&
3706 is_constructible<typename object_t::mapped_type,
3707 typename CompatibleObjectType::mapped_type>::value;
3708};
3709
3710template<typename BasicJsonType, typename CompatibleObjectType>
3712 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3713
3714template<typename BasicJsonType, typename ConstructibleObjectType,
3715 typename = void>
3716struct is_constructible_object_type_impl : std::false_type {};
3717
3718template<typename BasicJsonType, typename ConstructibleObjectType>
3720 BasicJsonType, ConstructibleObjectType,
3721 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3722 is_detected<key_type_t, ConstructibleObjectType>::value >>
3723{
3724 using object_t = typename BasicJsonType::object_t;
3725
3726 static constexpr bool value =
3728 (std::is_move_assignable<ConstructibleObjectType>::value ||
3729 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3730 (is_constructible<typename ConstructibleObjectType::key_type,
3731 typename object_t::key_type>::value &&
3732 std::is_same <
3733 typename object_t::mapped_type,
3734 typename ConstructibleObjectType::mapped_type >::value)) ||
3735 (has_from_json<BasicJsonType,
3736 typename ConstructibleObjectType::mapped_type>::value ||
3738 BasicJsonType,
3739 typename ConstructibleObjectType::mapped_type >::value);
3740};
3741
3742template<typename BasicJsonType, typename ConstructibleObjectType>
3744 : is_constructible_object_type_impl<BasicJsonType,
3745 ConstructibleObjectType> {};
3746
3747template<typename BasicJsonType, typename CompatibleStringType>
3753
3754template<typename BasicJsonType, typename ConstructibleStringType>
3756{
3757 // launder type through decltype() to fix compilation failure on ICPC
3758#ifdef __INTEL_COMPILER
3759 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3760#else
3761 using laundered_type = ConstructibleStringType;
3762#endif
3763
3764 static constexpr auto value =
3765 conjunction <
3767 is_detected_exact<typename BasicJsonType::string_t::value_type,
3769};
3770
3771template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3772struct is_compatible_array_type_impl : std::false_type {};
3773
3774template<typename BasicJsonType, typename CompatibleArrayType>
3776 BasicJsonType, CompatibleArrayType,
3777 enable_if_t <
3778 is_detected<iterator_t, CompatibleArrayType>::value&&
3779 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3780// special case for types like std::filesystem::path whose iterator's value_type are themselves
3781// c.f. https://github.com/nlohmann/json/pull/3073
3782 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3783{
3784 static constexpr bool value =
3785 is_constructible<BasicJsonType,
3787};
3788
3789template<typename BasicJsonType, typename CompatibleArrayType>
3791 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3792
3793template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3794struct is_constructible_array_type_impl : std::false_type {};
3795
3796template<typename BasicJsonType, typename ConstructibleArrayType>
3798 BasicJsonType, ConstructibleArrayType,
3799 enable_if_t<std::is_same<ConstructibleArrayType,
3800 typename BasicJsonType::value_type>::value >>
3801 : std::true_type {};
3802
3803template<typename BasicJsonType, typename ConstructibleArrayType>
3805 BasicJsonType, ConstructibleArrayType,
3806 enable_if_t < !std::is_same<ConstructibleArrayType,
3807 typename BasicJsonType::value_type>::value&&
3808 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3809 is_default_constructible<ConstructibleArrayType>::value&&
3810(std::is_move_assignable<ConstructibleArrayType>::value ||
3811 std::is_copy_assignable<ConstructibleArrayType>::value)&&
3812is_detected<iterator_t, ConstructibleArrayType>::value&&
3813is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3814is_detected<range_value_t, ConstructibleArrayType>::value&&
3815// special case for types like std::filesystem::path whose iterator's value_type are themselves
3816// c.f. https://github.com/nlohmann/json/pull/3073
3817!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3819 detected_t<range_value_t, ConstructibleArrayType >>::value >>
3820{
3822
3823 static constexpr bool value =
3824 std::is_same<value_type,
3825 typename BasicJsonType::array_t::value_type>::value ||
3826 has_from_json<BasicJsonType,
3827 value_type>::value ||
3829 BasicJsonType,
3830 value_type >::value;
3831};
3832
3833template<typename BasicJsonType, typename ConstructibleArrayType>
3835 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3836
3837template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3838 typename = void>
3839struct is_compatible_integer_type_impl : std::false_type {};
3840
3841template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3843 RealIntegerType, CompatibleNumberIntegerType,
3844 enable_if_t < std::is_integral<RealIntegerType>::value&&
3845 std::is_integral<CompatibleNumberIntegerType>::value&&
3846 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3847{
3848 // is there an assert somewhere on overflows?
3849 using RealLimits = std::numeric_limits<RealIntegerType>;
3850 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3851
3852 static constexpr auto value =
3853 is_constructible<RealIntegerType,
3854 CompatibleNumberIntegerType>::value &&
3855 CompatibleLimits::is_integer &&
3856 RealLimits::is_signed == CompatibleLimits::is_signed;
3857};
3858
3859template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3861 : is_compatible_integer_type_impl<RealIntegerType,
3862 CompatibleNumberIntegerType> {};
3863
3864template<typename BasicJsonType, typename CompatibleType, typename = void>
3865struct is_compatible_type_impl: std::false_type {};
3866
3867template<typename BasicJsonType, typename CompatibleType>
3869 BasicJsonType, CompatibleType,
3870 enable_if_t<is_complete_type<CompatibleType>::value >>
3871{
3872 static constexpr bool value =
3874};
3875
3876template<typename BasicJsonType, typename CompatibleType>
3878 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3879
3880template<typename T1, typename T2>
3881struct is_constructible_tuple : std::false_type {};
3882
3883template<typename T1, typename... Args>
3884struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3885
3886template<typename BasicJsonType, typename T>
3887struct is_json_iterator_of : std::false_type {};
3888
3889template<typename BasicJsonType>
3890struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
3891
3892template<typename BasicJsonType>
3893struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
3894{};
3895
3896// checks if a given type T is a template specialization of Primary
3897template<template <typename...> class Primary, typename T>
3898struct is_specialization_of : std::false_type {};
3899
3900template<template <typename...> class Primary, typename... Args>
3901struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
3902
3903template<typename T>
3905
3906// checks if A and B are comparable using Compare functor
3907template<typename Compare, typename A, typename B, typename = void>
3908struct is_comparable : std::false_type {};
3909
3910template<typename Compare, typename A, typename B>
3911struct is_comparable<Compare, A, B, void_t<
3912decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
3913decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
3914>> : std::true_type {};
3915
3916template<typename T>
3917using detect_is_transparent = typename T::is_transparent;
3918
3919// type trait to check if KeyType can be used as object key (without a BasicJsonType)
3920// see is_usable_as_basic_json_key_type below
3921template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
3922 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
3923using is_usable_as_key_type = typename std::conditional <
3925 && !(ExcludeObjectKeyType && std::is_same<KeyType,
3926 ObjectKeyType>::value)
3927 && (!RequireTransparentComparator
3928 || is_detected <detect_is_transparent, Comparator>::value)
3930 std::true_type,
3931 std::false_type >::type;
3932
3933// type trait to check if KeyType can be used as object key
3934// true if:
3935// - KeyType is comparable with BasicJsonType::object_t::key_type
3936// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
3937// - the comparator is transparent or RequireTransparentComparator is false
3938// - KeyType is not a JSON iterator or json_pointer
3939template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
3940 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
3941using is_usable_as_basic_json_key_type = typename std::conditional <
3942 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
3943 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
3944 RequireTransparentComparator, ExcludeObjectKeyType>::value
3946 std::true_type,
3947 std::false_type >::type;
3948
3949template<typename ObjectType, typename KeyType>
3950using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
3951
3952// type trait to check if object_t has an erase() member functions accepting KeyType
3953template<typename BasicJsonType, typename KeyType>
3954using has_erase_with_key_type = typename std::conditional <
3955 is_detected <
3957 typename BasicJsonType::object_t, KeyType >::value,
3958 std::true_type,
3959 std::false_type >::type;
3960
3961// a naive helper to check if a type is an ordered_map (exploits the fact that
3962// ordered_map inherits capacity() from std::vector)
3963template <typename T>
3965{
3966 using one = char;
3967
3968 struct two
3969 {
3970 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3971 };
3972
3973 template <typename C> static one test( decltype(&C::capacity) ) ;
3974 template <typename C> static two test(...);
3975
3976 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
3977};
3978
3979// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
3980template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
3982{
3983 return static_cast<T>(value);
3984}
3985
3986template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
3987T conditional_static_cast(U value)
3988{
3989 return value;
3990}
3991
3992template<typename... Types>
3994
3995template<typename... Types>
3997
3998template<typename... Types>
4000
4001// there's a disjunction trait in another PR; replace when merged
4002template<typename... Types>
4003using same_sign = std::integral_constant < bool,
4004 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4005
4006template<typename OfType, typename T>
4007using never_out_of_range = std::integral_constant < bool,
4008 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4009 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4010
4011template<typename OfType, typename T,
4012 bool OfTypeSigned = std::is_signed<OfType>::value,
4013 bool TSigned = std::is_signed<T>::value>
4015
4016template<typename OfType, typename T>
4017struct value_in_range_of_impl2<OfType, T, false, false>
4018{
4019 static constexpr bool test(T val)
4020 {
4021 using CommonType = typename std::common_type<OfType, T>::type;
4022 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4023 }
4024};
4025
4026template<typename OfType, typename T>
4027struct value_in_range_of_impl2<OfType, T, true, false>
4028{
4029 static constexpr bool test(T val)
4030 {
4031 using CommonType = typename std::common_type<OfType, T>::type;
4032 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4033 }
4034};
4035
4036template<typename OfType, typename T>
4037struct value_in_range_of_impl2<OfType, T, false, true>
4038{
4039 static constexpr bool test(T val)
4040 {
4041 using CommonType = typename std::common_type<OfType, T>::type;
4042 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4043 }
4044};
4045
4046
4047template<typename OfType, typename T>
4048struct value_in_range_of_impl2<OfType, T, true, true>
4049{
4050 static constexpr bool test(T val)
4051 {
4052 using CommonType = typename std::common_type<OfType, T>::type;
4053 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4054 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4055 }
4056};
4057
4058template<typename OfType, typename T,
4059 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4062
4063template<typename OfType, typename T>
4064struct value_in_range_of_impl1<OfType, T, false>
4065{
4066 static constexpr bool test(T val)
4067 {
4069 }
4070};
4071
4072template<typename OfType, typename T>
4073struct value_in_range_of_impl1<OfType, T, true>
4074{
4075 static constexpr bool test(T /*val*/)
4076 {
4077 return true;
4078 }
4079};
4080
4081template<typename OfType, typename T>
4082inline constexpr bool value_in_range_of(T val)
4083{
4085}
4086
4087template<bool Value>
4088using bool_constant = std::integral_constant<bool, Value>;
4089
4091// is_c_string
4093
4094namespace impl
4095{
4096
4097template<typename T>
4098inline constexpr bool is_c_string()
4099{
4100 using TUnExt = typename std::remove_extent<T>::type;
4101 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4102 using TUnPtr = typename std::remove_pointer<T>::type;
4103 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4104 return
4105 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4106 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4107}
4108
4109} // namespace impl
4110
4111// checks whether T is a [cv] char */[cv] char[] C string
4112template<typename T>
4113struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4114
4115template<typename T>
4117
4119// is_transparent
4121
4122namespace impl
4123{
4124
4125template<typename T>
4126inline constexpr bool is_transparent()
4127{
4129}
4130
4131} // namespace impl
4132
4133// checks whether T has a member named is_transparent
4134template<typename T>
4135struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4136
4138
4139} // namespace detail
4141
4142// #include <nlohmann/detail/string_concat.hpp>
4143// __ _____ _____ _____
4144// __| | __| | | | JSON for Modern C++
4145// | | |__ | | | | | | version 3.11.2
4146// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4147//
4148// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
4149// SPDX-License-Identifier: MIT
4150
4151
4152
4153#include <cstring> // strlen
4154#include <string> // string
4155#include <utility> // forward
4156
4157// #include <nlohmann/detail/meta/cpp_future.hpp>
4158
4159// #include <nlohmann/detail/meta/detected.hpp>
4160
4161
4163namespace detail
4164{
4165
4166inline std::size_t concat_length()
4167{
4168 return 0;
4169}
4170
4171template<typename... Args>
4172inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4173
4174template<typename StringType, typename... Args>
4175inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4176
4177template<typename... Args>
4178inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4179{
4180 return 1 + concat_length(rest...);
4181}
4182
4183template<typename... Args>
4184inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4185{
4186 // cppcheck-suppress ignoredReturnValue
4187 return ::strlen(cstr) + concat_length(rest...);
4188}
4189
4190template<typename StringType, typename... Args>
4191inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4192{
4193 return str.size() + concat_length(rest...);
4194}
4195
4196template<typename OutStringType>
4197inline void concat_into(OutStringType& /*out*/)
4198{}
4199
4200template<typename StringType, typename Arg>
4201using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4202
4203template<typename StringType, typename Arg>
4205
4206template<typename StringType, typename Arg>
4207using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4208
4209template<typename StringType, typename Arg>
4211
4212template<typename StringType, typename Arg>
4213using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4214
4215template<typename StringType, typename Arg>
4217
4218template<typename StringType, typename Arg>
4219using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4220
4221template<typename StringType, typename Arg>
4223
4224template < typename OutStringType, typename Arg, typename... Args,
4225 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4227inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4228
4229template < typename OutStringType, typename Arg, typename... Args,
4230 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4233inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4234
4235template < typename OutStringType, typename Arg, typename... Args,
4236 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4240inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4241
4242template<typename OutStringType, typename Arg, typename... Args,
4244inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4245{
4246 out.append(std::forward<Arg>(arg));
4247 concat_into(out, std::forward<Args>(rest)...);
4248}
4249
4250template < typename OutStringType, typename Arg, typename... Args,
4251 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4252 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4253inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4254{
4255 out += std::forward<Arg>(arg);
4256 concat_into(out, std::forward<Args>(rest)...);
4257}
4258
4259template < typename OutStringType, typename Arg, typename... Args,
4260 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4261 && !detect_string_can_append_op<OutStringType, Arg>::value
4262 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4263inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4264{
4265 out.append(arg.begin(), arg.end());
4266 concat_into(out, std::forward<Args>(rest)...);
4267}
4268
4269template < typename OutStringType, typename Arg, typename... Args,
4270 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4271 && !detect_string_can_append_op<OutStringType, Arg>::value
4272 && !detect_string_can_append_iter<OutStringType, Arg>::value
4273 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4274inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4275{
4276 out.append(arg.data(), arg.size());
4277 concat_into(out, std::forward<Args>(rest)...);
4278}
4279
4280template<typename OutStringType = std::string, typename... Args>
4281inline OutStringType concat(Args && ... args)
4282{
4283 OutStringType str;
4284 str.reserve(concat_length(args...));
4285 concat_into(str, std::forward<Args>(args)...);
4286 return str;
4287}
4288
4289} // namespace detail
4291
4292
4293
4295namespace detail
4296{
4297
4299// exceptions //
4301
4304class exception : public std::exception
4305{
4306 public:
4308 const char* what() const noexcept override
4309 {
4310 return m.what();
4311 }
4312
4314 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4315
4316 protected:
4318 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4319
4320 static std::string name(const std::string& ename, int id_)
4321 {
4322 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4323 }
4324
4325 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4326 {
4327 return "";
4328 }
4329
4330 template<typename BasicJsonType>
4331 static std::string diagnostics(const BasicJsonType* leaf_element)
4332 {
4333#if JSON_DIAGNOSTICS
4334 std::vector<std::string> tokens;
4335 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4336 {
4337 switch (current->m_parent->type())
4338 {
4339 case value_t::array:
4340 {
4341 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4342 {
4343 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4344 {
4345 tokens.emplace_back(std::to_string(i));
4346 break;
4347 }
4348 }
4349 break;
4350 }
4351
4352 case value_t::object:
4353 {
4354 for (const auto& element : *current->m_parent->m_data.m_value.object)
4355 {
4356 if (&element.second == current)
4357 {
4358 tokens.emplace_back(element.first.c_str());
4359 break;
4360 }
4361 }
4362 break;
4363 }
4364
4365 case value_t::null: // LCOV_EXCL_LINE
4366 case value_t::string: // LCOV_EXCL_LINE
4367 case value_t::boolean: // LCOV_EXCL_LINE
4368 case value_t::number_integer: // LCOV_EXCL_LINE
4369 case value_t::number_unsigned: // LCOV_EXCL_LINE
4370 case value_t::number_float: // LCOV_EXCL_LINE
4371 case value_t::binary: // LCOV_EXCL_LINE
4372 case value_t::discarded: // LCOV_EXCL_LINE
4373 default: // LCOV_EXCL_LINE
4374 break; // LCOV_EXCL_LINE
4375 }
4376 }
4377
4378 if (tokens.empty())
4379 {
4380 return "";
4381 }
4382
4383 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4384 [](const std::string & a, const std::string & b)
4385 {
4386 return concat(a, '/', detail::escape(b));
4387 });
4388 return concat('(', str, ") ");
4389#else
4390 static_cast<void>(leaf_element);
4391 return "";
4392#endif
4393 }
4394
4395 private:
4397 std::runtime_error m;
4398};
4399
4403{
4404 public:
4414 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4415 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4416 {
4417 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4418 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4419 return {id_, pos.chars_read_total, w.c_str()};
4420 }
4421
4422 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4423 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4424 {
4425 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4426 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4427 ": ", exception::diagnostics(context), what_arg);
4428 return {id_, byte_, w.c_str()};
4429 }
4430
4440 const std::size_t byte;
4441
4442 private:
4443 parse_error(int id_, std::size_t byte_, const char* what_arg)
4444 : exception(id_, what_arg), byte(byte_) {}
4445
4446 static std::string position_string(const position_t& pos)
4447 {
4448 return concat(" at line ", std::to_string(pos.lines_read + 1),
4449 ", column ", std::to_string(pos.chars_read_current_line));
4450 }
4451};
4452
4456{
4457 public:
4458 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4459 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4460 {
4461 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4462 return {id_, w.c_str()};
4463 }
4464
4465 private:
4467 invalid_iterator(int id_, const char* what_arg)
4468 : exception(id_, what_arg) {}
4469};
4470
4473class type_error : public exception
4474{
4475 public:
4476 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4477 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4478 {
4479 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4480 return {id_, w.c_str()};
4481 }
4482
4483 private:
4485 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4486};
4487
4491{
4492 public:
4493 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4494 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4495 {
4496 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4497 return {id_, w.c_str()};
4498 }
4499
4500 private:
4502 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4503};
4504
4508{
4509 public:
4510 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4511 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4512 {
4513 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4514 return {id_, w.c_str()};
4515 }
4516
4517 private:
4519 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4520};
4521
4522} // namespace detail
4524
4525// #include <nlohmann/detail/macro_scope.hpp>
4526
4527// #include <nlohmann/detail/meta/cpp_future.hpp>
4528
4529// #include <nlohmann/detail/meta/identity_tag.hpp>
4530// __ _____ _____ _____
4531// __| | __| | | | JSON for Modern C++
4532// | | |__ | | | | | | version 3.11.2
4533// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4534//
4535// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
4536// SPDX-License-Identifier: MIT
4537
4538
4539
4540// #include <nlohmann/detail/abi_macros.hpp>
4541
4542
4544namespace detail
4545{
4546
4547// dispatching helper struct
4548template <class T> struct identity_tag {};
4549
4550} // namespace detail
4552
4553// #include <nlohmann/detail/meta/std_fs.hpp>
4554// __ _____ _____ _____
4555// __| | __| | | | JSON for Modern C++
4556// | | |__ | | | | | | version 3.11.2
4557// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4558//
4559// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
4560// SPDX-License-Identifier: MIT
4561
4562
4563
4564// #include <nlohmann/detail/macro_scope.hpp>
4565
4566
4567#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4568#include <experimental/filesystem>
4570namespace detail
4571{
4572namespace std_fs = std::experimental::filesystem;
4573} // namespace detail
4575#elif JSON_HAS_FILESYSTEM
4576#include <filesystem>
4578namespace detail
4579{
4580namespace std_fs = std::filesystem;
4581} // namespace detail
4583#endif
4584
4585// #include <nlohmann/detail/meta/type_traits.hpp>
4586
4587// #include <nlohmann/detail/string_concat.hpp>
4588
4589// #include <nlohmann/detail/value_t.hpp>
4590
4591
4593namespace detail
4594{
4595
4596template<typename BasicJsonType>
4597inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4598{
4599 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4600 {
4601 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4602 }
4603 n = nullptr;
4604}
4605
4606// overloads for basic_json template parameters
4607template < typename BasicJsonType, typename ArithmeticType,
4608 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4609 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4610 int > = 0 >
4611void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4612{
4613 switch (static_cast<value_t>(j))
4614 {
4616 {
4617 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4618 break;
4619 }
4621 {
4622 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4623 break;
4624 }
4626 {
4627 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4628 break;
4629 }
4630
4631 case value_t::null:
4632 case value_t::object:
4633 case value_t::array:
4634 case value_t::string:
4635 case value_t::boolean:
4636 case value_t::binary:
4637 case value_t::discarded:
4638 default:
4639 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4640 }
4641}
4642
4643template<typename BasicJsonType>
4644inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4645{
4646 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4647 {
4648 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4649 }
4650 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4651}
4652
4653template<typename BasicJsonType>
4654inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4655{
4656 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4657 {
4658 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4659 }
4660 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4661}
4662
4663template <
4664 typename BasicJsonType, typename StringType,
4665 enable_if_t <
4666 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4667 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4668 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4669 && !is_json_ref<StringType>::value, int > = 0 >
4670inline void from_json(const BasicJsonType& j, StringType& s)
4671{
4672 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4673 {
4674 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4675 }
4676
4677 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4678}
4679
4680template<typename BasicJsonType>
4681inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4682{
4683 get_arithmetic_value(j, val);
4684}
4685
4686template<typename BasicJsonType>
4687inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4688{
4689 get_arithmetic_value(j, val);
4690}
4691
4692template<typename BasicJsonType>
4693inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4694{
4695 get_arithmetic_value(j, val);
4696}
4697
4698#if !JSON_DISABLE_ENUM_SERIALIZATION
4699template<typename BasicJsonType, typename EnumType,
4700 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4701inline void from_json(const BasicJsonType& j, EnumType& e)
4702{
4703 typename std::underlying_type<EnumType>::type val;
4704 get_arithmetic_value(j, val);
4705 e = static_cast<EnumType>(val);
4706}
4707#endif // JSON_DISABLE_ENUM_SERIALIZATION
4708
4709// forward_list doesn't have an insert method
4710template<typename BasicJsonType, typename T, typename Allocator,
4711 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4712inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4713{
4714 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4715 {
4716 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4717 }
4718 l.clear();
4719 std::transform(j.rbegin(), j.rend(),
4720 std::front_inserter(l), [](const BasicJsonType & i)
4721 {
4722 return i.template get<T>();
4723 });
4724}
4725
4726// valarray doesn't have an insert method
4727template<typename BasicJsonType, typename T,
4728 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4729inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4730{
4731 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4732 {
4733 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4734 }
4735 l.resize(j.size());
4736 std::transform(j.begin(), j.end(), std::begin(l),
4737 [](const BasicJsonType & elem)
4738 {
4739 return elem.template get<T>();
4740 });
4741}
4742
4743template<typename BasicJsonType, typename T, std::size_t N>
4744auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4745-> decltype(j.template get<T>(), void())
4746{
4747 for (std::size_t i = 0; i < N; ++i)
4748 {
4749 arr[i] = j.at(i).template get<T>();
4750 }
4751}
4752
4753template<typename BasicJsonType>
4754inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
4755{
4756 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4757}
4758
4759template<typename BasicJsonType, typename T, std::size_t N>
4760auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
4761 priority_tag<2> /*unused*/)
4762-> decltype(j.template get<T>(), void())
4763{
4764 for (std::size_t i = 0; i < N; ++i)
4765 {
4766 arr[i] = j.at(i).template get<T>();
4767 }
4768}
4769
4770template<typename BasicJsonType, typename ConstructibleArrayType,
4772 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4773 int> = 0>
4774auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4775-> decltype(
4776 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4777 j.template get<typename ConstructibleArrayType::value_type>(),
4778 void())
4779{
4780 using std::end;
4781
4782 ConstructibleArrayType ret;
4783 ret.reserve(j.size());
4784 std::transform(j.begin(), j.end(),
4785 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4786 {
4787 // get<BasicJsonType>() returns *this, this won't call a from_json
4788 // method when value_type is BasicJsonType
4789 return i.template get<typename ConstructibleArrayType::value_type>();
4790 });
4791 arr = std::move(ret);
4792}
4793
4794template<typename BasicJsonType, typename ConstructibleArrayType,
4796 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4797 int> = 0>
4798inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4799 priority_tag<0> /*unused*/)
4800{
4801 using std::end;
4802
4803 ConstructibleArrayType ret;
4804 std::transform(
4805 j.begin(), j.end(), std::inserter(ret, end(ret)),
4806 [](const BasicJsonType & i)
4807 {
4808 // get<BasicJsonType>() returns *this, this won't call a from_json
4809 // method when value_type is BasicJsonType
4810 return i.template get<typename ConstructibleArrayType::value_type>();
4811 });
4812 arr = std::move(ret);
4813}
4814
4815template < typename BasicJsonType, typename ConstructibleArrayType,
4816 enable_if_t <
4817 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4818 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4820 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4821 !is_basic_json<ConstructibleArrayType>::value,
4822 int > = 0 >
4823auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4824-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4825j.template get<typename ConstructibleArrayType::value_type>(),
4826void())
4827{
4828 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4829 {
4830 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4831 }
4832
4833 from_json_array_impl(j, arr, priority_tag<3> {});
4834}
4835
4836template < typename BasicJsonType, typename T, std::size_t... Idx >
4837std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4838 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4839{
4840 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4841}
4842
4843template < typename BasicJsonType, typename T, std::size_t N >
4844auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4845-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4846{
4847 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4848 {
4849 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4850 }
4851
4852 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4853}
4854
4855template<typename BasicJsonType>
4856inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4857{
4858 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4859 {
4860 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
4861 }
4862
4863 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4864}
4865
4866template<typename BasicJsonType, typename ConstructibleObjectType,
4867 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
4868inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4869{
4870 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4871 {
4872 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
4873 }
4874
4875 ConstructibleObjectType ret;
4876 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4877 using value_type = typename ConstructibleObjectType::value_type;
4878 std::transform(
4879 inner_object->begin(), inner_object->end(),
4880 std::inserter(ret, ret.begin()),
4881 [](typename BasicJsonType::object_t::value_type const & p)
4882 {
4883 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4884 });
4885 obj = std::move(ret);
4886}
4887
4888// overload for arithmetic types, not chosen for basic_json template arguments
4889// (BooleanType, etc..); note: Is it really necessary to provide explicit
4890// overloads for boolean_t etc. in case of a custom BooleanType which is not
4891// an arithmetic type?
4892template < typename BasicJsonType, typename ArithmeticType,
4893 enable_if_t <
4894 std::is_arithmetic<ArithmeticType>::value&&
4895 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
4896 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
4897 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
4898 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4899 int > = 0 >
4900inline void from_json(const BasicJsonType& j, ArithmeticType& val)
4901{
4902 switch (static_cast<value_t>(j))
4903 {
4905 {
4906 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4907 break;
4908 }
4910 {
4911 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4912 break;
4913 }
4915 {
4916 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4917 break;
4918 }
4919 case value_t::boolean:
4920 {
4921 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
4922 break;
4923 }
4924
4925 case value_t::null:
4926 case value_t::object:
4927 case value_t::array:
4928 case value_t::string:
4929 case value_t::binary:
4930 case value_t::discarded:
4931 default:
4932 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4933 }
4934}
4935
4936template<typename BasicJsonType, typename... Args, std::size_t... Idx>
4937std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
4938{
4939 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
4940}
4941
4942template < typename BasicJsonType, class A1, class A2 >
4943std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
4944{
4945 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
4946 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
4947}
4948
4949template<typename BasicJsonType, typename A1, typename A2>
4950inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
4951{
4952 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
4953}
4954
4955template<typename BasicJsonType, typename... Args>
4956std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
4957{
4958 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4959}
4960
4961template<typename BasicJsonType, typename... Args>
4962inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
4963{
4964 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4965}
4966
4967template<typename BasicJsonType, typename TupleRelated>
4968auto from_json(BasicJsonType&& j, TupleRelated&& t)
4969-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
4970{
4971 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4972 {
4973 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4974 }
4975
4976 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
4977}
4978
4979template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
4980 typename = enable_if_t < !std::is_constructible <
4981 typename BasicJsonType::string_t, Key >::value >>
4982inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
4983{
4984 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4985 {
4986 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4987 }
4988 m.clear();
4989 for (const auto& p : j)
4990 {
4991 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4992 {
4993 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
4994 }
4995 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4996 }
4997}
4998
4999template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5000 typename = enable_if_t < !std::is_constructible <
5001 typename BasicJsonType::string_t, Key >::value >>
5002inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5003{
5004 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5005 {
5006 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5007 }
5008 m.clear();
5009 for (const auto& p : j)
5010 {
5011 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5012 {
5013 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5014 }
5015 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5016 }
5017}
5018
5019#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5020template<typename BasicJsonType>
5021inline void from_json(const BasicJsonType& j, std_fs::path& p)
5022{
5023 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5024 {
5025 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5026 }
5027 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5028}
5029#endif
5030
5031struct from_json_fn
5032{
5033 template<typename BasicJsonType, typename T>
5034 auto operator()(const BasicJsonType& j, T&& val) const
5035 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5036 -> decltype(from_json(j, std::forward<T>(val)))
5037 {
5038 return from_json(j, std::forward<T>(val));
5039 }
5040};
5041
5042} // namespace detail
5043
5044#ifndef JSON_HAS_CPP_17
5048namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5049{
5050#endif
5051JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5053#ifndef JSON_HAS_CPP_17
5054} // namespace
5055#endif
5056
5058
5059// #include <nlohmann/detail/conversions/to_json.hpp>
5060// __ _____ _____ _____
5061// __| | __| | | | JSON for Modern C++
5062// | | |__ | | | | | | version 3.11.2
5063// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5064//
5065// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5066// SPDX-License-Identifier: MIT
5067
5068
5069
5070#include <algorithm> // copy
5071#include <iterator> // begin, end
5072#include <string> // string
5073#include <tuple> // tuple, get
5074#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5075#include <utility> // move, forward, declval, pair
5076#include <valarray> // valarray
5077#include <vector> // vector
5078
5079// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5080// __ _____ _____ _____
5081// __| | __| | | | JSON for Modern C++
5082// | | |__ | | | | | | version 3.11.2
5083// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5084//
5085// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5086// SPDX-License-Identifier: MIT
5087
5088
5089
5090#include <cstddef> // size_t
5091#include <iterator> // input_iterator_tag
5092#include <string> // string, to_string
5093#include <tuple> // tuple_size, get, tuple_element
5094#include <utility> // move
5095
5096#if JSON_HAS_RANGES
5097 #include <ranges> // enable_borrowed_range
5098#endif
5099
5100// #include <nlohmann/detail/abi_macros.hpp>
5101
5102// #include <nlohmann/detail/meta/type_traits.hpp>
5103
5104// #include <nlohmann/detail/value_t.hpp>
5105
5106
5108namespace detail
5109{
5110
5111template<typename string_type>
5112void int_to_string( string_type& target, std::size_t value )
5113{
5114 // For ADL
5115 using std::to_string;
5116 target = to_string(value);
5117}
5118template<typename IteratorType> class iteration_proxy_value
5119{
5120 public:
5121 using difference_type = std::ptrdiff_t;
5125 using iterator_category = std::input_iterator_tag;
5126 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5127
5128 private:
5130 IteratorType anchor{};
5132 std::size_t array_index = 0;
5134 mutable std::size_t array_index_last = 0;
5136 mutable string_type array_index_str = "0";
5138 string_type empty_str{};
5139
5140 public:
5141 explicit iteration_proxy_value() = default;
5142 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5143 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5144 && std::is_nothrow_default_constructible<string_type>::value)
5145 : anchor(std::move(it))
5146 , array_index(array_index_)
5147 {}
5148
5151 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5153 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5154 && std::is_nothrow_move_constructible<string_type>::value) = default;
5156 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5157 && std::is_nothrow_move_assignable<string_type>::value) = default;
5159
5161 const iteration_proxy_value& operator*() const
5162 {
5163 return *this;
5164 }
5165
5168 {
5169 ++anchor;
5170 ++array_index;
5171
5172 return *this;
5173 }
5174
5175 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5176 {
5177 auto tmp = iteration_proxy_value(anchor, array_index);
5178 ++anchor;
5179 ++array_index;
5180 return tmp;
5181 }
5182
5185 {
5186 return anchor == o.anchor;
5187 }
5188
5191 {
5192 return anchor != o.anchor;
5193 }
5194
5196 const string_type& key() const
5197 {
5198 JSON_ASSERT(anchor.m_object != nullptr);
5199
5200 switch (anchor.m_object->type())
5201 {
5202 // use integer array index as key
5203 case value_t::array:
5204 {
5205 if (array_index != array_index_last)
5206 {
5207 int_to_string( array_index_str, array_index );
5208 array_index_last = array_index;
5209 }
5210 return array_index_str;
5211 }
5212
5213 // use key from the object
5214 case value_t::object:
5215 return anchor.key();
5216
5217 // use an empty key for all primitive types
5218 case value_t::null:
5219 case value_t::string:
5220 case value_t::boolean:
5224 case value_t::binary:
5225 case value_t::discarded:
5226 default:
5227 return empty_str;
5228 }
5229 }
5230
5232 typename IteratorType::reference value() const
5233 {
5234 return anchor.value();
5235 }
5236};
5237
5239template<typename IteratorType> class iteration_proxy
5240{
5241 private:
5243 typename IteratorType::pointer container = nullptr;
5244
5245 public:
5246 explicit iteration_proxy() = default;
5247
5249 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5250 : container(&cont) {}
5251
5254 iteration_proxy(iteration_proxy&&) noexcept = default;
5255 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5256 ~iteration_proxy() = default;
5257
5259 iteration_proxy_value<IteratorType> begin() const noexcept
5260 {
5261 return iteration_proxy_value<IteratorType>(container->begin());
5262 }
5263
5266 {
5267 return iteration_proxy_value<IteratorType>(container->end());
5268 }
5269};
5270
5271// Structured Bindings Support
5272// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5273// And see https://github.com/nlohmann/json/pull/1391
5274template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5275auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5276{
5277 return i.key();
5278}
5279// Structured Bindings Support
5280// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5281// And see https://github.com/nlohmann/json/pull/1391
5282template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5283auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5284{
5285 return i.value();
5286}
5287
5288} // namespace detail
5290
5291// The Addition to the STD Namespace is required to add
5292// Structured Bindings Support to the iteration_proxy_value class
5293// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5294// And see https://github.com/nlohmann/json/pull/1391
5295namespace std
5296{
5297
5298#if defined(__clang__)
5299 // Fix: https://github.com/nlohmann/json/issues/1401
5300 #pragma clang diagnostic push
5301 #pragma clang diagnostic ignored "-Wmismatched-tags"
5302#endif
5303template<typename IteratorType>
5304class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5305 : public std::integral_constant<std::size_t, 2> {};
5306
5307template<std::size_t N, typename IteratorType>
5308class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5309{
5310 public:
5311 using type = decltype(
5312 get<N>(std::declval <
5313 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5314};
5315#if defined(__clang__)
5316 #pragma clang diagnostic pop
5317#endif
5318
5319} // namespace std
5320
5321#if JSON_HAS_RANGES
5322 template <typename IteratorType>
5323 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5324#endif
5325
5326// #include <nlohmann/detail/macro_scope.hpp>
5327
5328// #include <nlohmann/detail/meta/cpp_future.hpp>
5329
5330// #include <nlohmann/detail/meta/std_fs.hpp>
5331
5332// #include <nlohmann/detail/meta/type_traits.hpp>
5333
5334// #include <nlohmann/detail/value_t.hpp>
5335
5336
5338namespace detail
5339{
5340
5342// constructors //
5344
5345/*
5346 * Note all external_constructor<>::construct functions need to call
5347 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5348 * allocated value (e.g., a string). See bug issue
5349 * https://github.com/nlohmann/json/issues/2865 for more information.
5350 */
5351
5352template<value_t> struct external_constructor;
5353
5354template<>
5356{
5357 template<typename BasicJsonType>
5358 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5359 {
5360 j.m_data.m_value.destroy(j.m_data.m_type);
5361 j.m_data.m_type = value_t::boolean;
5362 j.m_data.m_value = b;
5363 j.assert_invariant();
5364 }
5365};
5366
5367template<>
5369{
5370 template<typename BasicJsonType>
5371 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5372 {
5373 j.m_data.m_value.destroy(j.m_data.m_type);
5374 j.m_data.m_type = value_t::string;
5375 j.m_data.m_value = s;
5376 j.assert_invariant();
5377 }
5378
5379 template<typename BasicJsonType>
5380 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5381 {
5382 j.m_data.m_value.destroy(j.m_data.m_type);
5383 j.m_data.m_type = value_t::string;
5384 j.m_data.m_value = std::move(s);
5385 j.assert_invariant();
5386 }
5387
5388 template < typename BasicJsonType, typename CompatibleStringType,
5389 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5390 int > = 0 >
5391 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5392 {
5393 j.m_data.m_value.destroy(j.m_data.m_type);
5394 j.m_data.m_type = value_t::string;
5395 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5396 j.assert_invariant();
5397 }
5398};
5399
5400template<>
5402{
5403 template<typename BasicJsonType>
5404 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5405 {
5406 j.m_data.m_value.destroy(j.m_data.m_type);
5407 j.m_data.m_type = value_t::binary;
5408 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5409 j.assert_invariant();
5410 }
5411
5412 template<typename BasicJsonType>
5413 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5414 {
5415 j.m_data.m_value.destroy(j.m_data.m_type);
5416 j.m_data.m_type = value_t::binary;
5417 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5418 j.assert_invariant();
5419 }
5420};
5421
5422template<>
5424{
5425 template<typename BasicJsonType>
5426 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5427 {
5428 j.m_data.m_value.destroy(j.m_data.m_type);
5429 j.m_data.m_type = value_t::number_float;
5430 j.m_data.m_value = val;
5431 j.assert_invariant();
5432 }
5433};
5434
5435template<>
5437{
5438 template<typename BasicJsonType>
5439 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5440 {
5441 j.m_data.m_value.destroy(j.m_data.m_type);
5442 j.m_data.m_type = value_t::number_unsigned;
5443 j.m_data.m_value = val;
5444 j.assert_invariant();
5445 }
5446};
5447
5448template<>
5450{
5451 template<typename BasicJsonType>
5452 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5453 {
5454 j.m_data.m_value.destroy(j.m_data.m_type);
5455 j.m_data.m_type = value_t::number_integer;
5456 j.m_data.m_value = val;
5457 j.assert_invariant();
5458 }
5459};
5460
5461template<>
5463{
5464 template<typename BasicJsonType>
5465 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5466 {
5467 j.m_data.m_value.destroy(j.m_data.m_type);
5468 j.m_data.m_type = value_t::array;
5469 j.m_data.m_value = arr;
5470 j.set_parents();
5471 j.assert_invariant();
5472 }
5473
5474 template<typename BasicJsonType>
5475 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5476 {
5477 j.m_data.m_value.destroy(j.m_data.m_type);
5478 j.m_data.m_type = value_t::array;
5479 j.m_data.m_value = std::move(arr);
5480 j.set_parents();
5481 j.assert_invariant();
5482 }
5483
5484 template < typename BasicJsonType, typename CompatibleArrayType,
5485 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5486 int > = 0 >
5487 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5488 {
5489 using std::begin;
5490 using std::end;
5491
5492 j.m_data.m_value.destroy(j.m_data.m_type);
5493 j.m_data.m_type = value_t::array;
5494 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5495 j.set_parents();
5496 j.assert_invariant();
5497 }
5498
5499 template<typename BasicJsonType>
5500 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5501 {
5502 j.m_data.m_value.destroy(j.m_data.m_type);
5503 j.m_data.m_type = value_t::array;
5504 j.m_data.m_value = value_t::array;
5505 j.m_data.m_value.array->reserve(arr.size());
5506 for (const bool x : arr)
5507 {
5508 j.m_data.m_value.array->push_back(x);
5509 j.set_parent(j.m_data.m_value.array->back());
5510 }
5511 j.assert_invariant();
5512 }
5513
5514 template<typename BasicJsonType, typename T,
5516 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5517 {
5518 j.m_data.m_value.destroy(j.m_data.m_type);
5519 j.m_data.m_type = value_t::array;
5520 j.m_data.m_value = value_t::array;
5521 j.m_data.m_value.array->resize(arr.size());
5522 if (arr.size() > 0)
5523 {
5524 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5525 }
5526 j.set_parents();
5527 j.assert_invariant();
5528 }
5529};
5530
5531template<>
5533{
5534 template<typename BasicJsonType>
5535 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5536 {
5537 j.m_data.m_value.destroy(j.m_data.m_type);
5538 j.m_data.m_type = value_t::object;
5539 j.m_data.m_value = obj;
5540 j.set_parents();
5541 j.assert_invariant();
5542 }
5543
5544 template<typename BasicJsonType>
5545 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5546 {
5547 j.m_data.m_value.destroy(j.m_data.m_type);
5548 j.m_data.m_type = value_t::object;
5549 j.m_data.m_value = std::move(obj);
5550 j.set_parents();
5551 j.assert_invariant();
5552 }
5553
5554 template < typename BasicJsonType, typename CompatibleObjectType,
5555 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5556 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5557 {
5558 using std::begin;
5559 using std::end;
5560
5561 j.m_data.m_value.destroy(j.m_data.m_type);
5562 j.m_data.m_type = value_t::object;
5563 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5564 j.set_parents();
5565 j.assert_invariant();
5566 }
5567};
5568
5570// to_json //
5572
5573template<typename BasicJsonType, typename T,
5574 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5575inline void to_json(BasicJsonType& j, T b) noexcept
5576{
5578}
5579
5580template < typename BasicJsonType, typename BoolRef,
5581 enable_if_t <
5582 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5583 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5584 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5585 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5586 typename BasicJsonType::boolean_t >::value))
5587 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5588inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5589{
5590 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5591}
5592
5593template<typename BasicJsonType, typename CompatibleString,
5594 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5595inline void to_json(BasicJsonType& j, const CompatibleString& s)
5596{
5598}
5599
5600template<typename BasicJsonType>
5601inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5602{
5604}
5605
5606template<typename BasicJsonType, typename FloatType,
5607 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5608inline void to_json(BasicJsonType& j, FloatType val) noexcept
5609{
5610 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5611}
5612
5613template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5614 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5615inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5616{
5617 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5618}
5619
5620template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5621 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5622inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5623{
5624 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5625}
5626
5627#if !JSON_DISABLE_ENUM_SERIALIZATION
5628template<typename BasicJsonType, typename EnumType,
5629 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5630inline void to_json(BasicJsonType& j, EnumType e) noexcept
5631{
5632 using underlying_type = typename std::underlying_type<EnumType>::type;
5633 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
5634}
5635#endif // JSON_DISABLE_ENUM_SERIALIZATION
5636
5637template<typename BasicJsonType>
5638inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5639{
5641}
5642
5643template < typename BasicJsonType, typename CompatibleArrayType,
5644 enable_if_t < is_compatible_array_type<BasicJsonType,
5645 CompatibleArrayType>::value&&
5646 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
5648 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
5649 !is_basic_json<CompatibleArrayType>::value,
5650 int > = 0 >
5651inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
5652{
5654}
5655
5656template<typename BasicJsonType>
5657inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
5658{
5660}
5661
5662template<typename BasicJsonType, typename T,
5663 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5664inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
5665{
5667}
5668
5669template<typename BasicJsonType>
5670inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5671{
5673}
5674
5675template < typename BasicJsonType, typename CompatibleObjectType,
5676 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
5677inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
5678{
5680}
5681
5682template<typename BasicJsonType>
5683inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5684{
5686}
5687
5688template <
5689 typename BasicJsonType, typename T, std::size_t N,
5690 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
5691 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5692 int > = 0 >
5693inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5694{
5696}
5697
5698template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
5699inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
5700{
5701 j = { p.first, p.second };
5702}
5703
5704// for https://github.com/nlohmann/json/pull/1134
5705template<typename BasicJsonType, typename T,
5706 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
5707inline void to_json(BasicJsonType& j, const T& b)
5708{
5709 j = { {b.key(), b.value()} };
5710}
5711
5712template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
5713inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
5714{
5715 j = { std::get<Idx>(t)... };
5716}
5717
5718template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
5719inline void to_json(BasicJsonType& j, const T& t)
5720{
5721 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5722}
5723
5724#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5725template<typename BasicJsonType>
5726inline void to_json(BasicJsonType& j, const std_fs::path& p)
5727{
5728 j = p.string();
5729}
5730#endif
5731
5733{
5734 template<typename BasicJsonType, typename T>
5735 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
5736 -> decltype(to_json(j, std::forward<T>(val)), void())
5737 {
5738 return to_json(j, std::forward<T>(val));
5739 }
5740};
5741} // namespace detail
5742
5743#ifndef JSON_HAS_CPP_17
5747namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5748{
5749#endif
5750JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
5752#ifndef JSON_HAS_CPP_17
5753} // namespace
5754#endif
5755
5757
5758// #include <nlohmann/detail/meta/identity_tag.hpp>
5759
5760
5762
5764template<typename ValueType, typename>
5766{
5769 template<typename BasicJsonType, typename TargetType = ValueType>
5770 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
5771 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5772 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
5773 {
5774 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5775 }
5776
5779 template<typename BasicJsonType, typename TargetType = ValueType>
5780 static auto from_json(BasicJsonType && j) noexcept(
5781 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
5782 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
5783 {
5784 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
5785 }
5786
5789 template<typename BasicJsonType, typename TargetType = ValueType>
5790 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
5791 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5792 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
5793 {
5794 ::nlohmann::to_json(j, std::forward<TargetType>(val));
5795 }
5796};
5797
5799
5800// #include <nlohmann/byte_container_with_subtype.hpp>
5801// __ _____ _____ _____
5802// __| | __| | | | JSON for Modern C++
5803// | | |__ | | | | | | version 3.11.2
5804// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5805//
5806// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5807// SPDX-License-Identifier: MIT
5808
5809
5810
5811#include <cstdint> // uint8_t, uint64_t
5812#include <tuple> // tie
5813#include <utility> // move
5814
5815// #include <nlohmann/detail/abi_macros.hpp>
5816
5817
5819
5822template<typename BinaryType>
5823class byte_container_with_subtype : public BinaryType
5824{
5825 public:
5826 using container_type = BinaryType;
5827 using subtype_type = std::uint64_t;
5828
5831 : container_type()
5832 {}
5833
5836 : container_type(b)
5837 {}
5838
5840 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
5841 : container_type(std::move(b))
5842 {}
5843
5846 : container_type(b)
5847 , m_subtype(subtype_)
5848 , m_has_subtype(true)
5849 {}
5850
5852 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
5853 : container_type(std::move(b))
5854 , m_subtype(subtype_)
5855 , m_has_subtype(true)
5856 {}
5857
5859 {
5860 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5861 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5862 }
5863
5865 {
5866 return !(rhs == *this);
5867 }
5868
5871 void set_subtype(subtype_type subtype_) noexcept
5872 {
5873 m_subtype = subtype_;
5874 m_has_subtype = true;
5875 }
5876
5879 constexpr subtype_type subtype() const noexcept
5880 {
5881 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5882 }
5883
5886 constexpr bool has_subtype() const noexcept
5887 {
5888 return m_has_subtype;
5889 }
5890
5893 void clear_subtype() noexcept
5894 {
5895 m_subtype = 0;
5896 m_has_subtype = false;
5897 }
5898
5899 private:
5900 subtype_type m_subtype = 0;
5901 bool m_has_subtype = false;
5902};
5903
5905
5906// #include <nlohmann/detail/conversions/from_json.hpp>
5907
5908// #include <nlohmann/detail/conversions/to_json.hpp>
5909
5910// #include <nlohmann/detail/exceptions.hpp>
5911
5912// #include <nlohmann/detail/hash.hpp>
5913// __ _____ _____ _____
5914// __| | __| | | | JSON for Modern C++
5915// | | |__ | | | | | | version 3.11.2
5916// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5917//
5918// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5919// SPDX-License-Identifier: MIT
5920
5921
5922
5923#include <cstdint> // uint8_t
5924#include <cstddef> // size_t
5925#include <functional> // hash
5926
5927// #include <nlohmann/detail/abi_macros.hpp>
5928
5929// #include <nlohmann/detail/value_t.hpp>
5930
5931
5933namespace detail
5934{
5935
5936// boost::hash_combine
5937inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
5938{
5939 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
5940 return seed;
5941}
5942
5954template<typename BasicJsonType>
5955std::size_t hash(const BasicJsonType& j)
5956{
5957 using string_t = typename BasicJsonType::string_t;
5958 using number_integer_t = typename BasicJsonType::number_integer_t;
5959 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5960 using number_float_t = typename BasicJsonType::number_float_t;
5961
5962 const auto type = static_cast<std::size_t>(j.type());
5963 switch (j.type())
5964 {
5965 case BasicJsonType::value_t::null:
5966 case BasicJsonType::value_t::discarded:
5967 {
5968 return combine(type, 0);
5969 }
5970
5971 case BasicJsonType::value_t::object:
5972 {
5973 auto seed = combine(type, j.size());
5974 for (const auto& element : j.items())
5975 {
5976 const auto h = std::hash<string_t> {}(element.key());
5977 seed = combine(seed, h);
5978 seed = combine(seed, hash(element.value()));
5979 }
5980 return seed;
5981 }
5982
5983 case BasicJsonType::value_t::array:
5984 {
5985 auto seed = combine(type, j.size());
5986 for (const auto& element : j)
5987 {
5988 seed = combine(seed, hash(element));
5989 }
5990 return seed;
5991 }
5992
5993 case BasicJsonType::value_t::string:
5994 {
5995 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
5996 return combine(type, h);
5997 }
5998
5999 case BasicJsonType::value_t::boolean:
6000 {
6001 const auto h = std::hash<bool> {}(j.template get<bool>());
6002 return combine(type, h);
6003 }
6004
6005 case BasicJsonType::value_t::number_integer:
6006 {
6007 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6008 return combine(type, h);
6009 }
6010
6011 case BasicJsonType::value_t::number_unsigned:
6012 {
6013 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6014 return combine(type, h);
6015 }
6016
6017 case BasicJsonType::value_t::number_float:
6018 {
6019 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6020 return combine(type, h);
6021 }
6022
6023 case BasicJsonType::value_t::binary:
6024 {
6025 auto seed = combine(type, j.get_binary().size());
6026 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6027 seed = combine(seed, h);
6028 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6029 for (const auto byte : j.get_binary())
6030 {
6031 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6032 }
6033 return seed;
6034 }
6035
6036 default: // LCOV_EXCL_LINE
6037 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6038 return 0; // LCOV_EXCL_LINE
6039 }
6040}
6041
6042} // namespace detail
6044
6045// #include <nlohmann/detail/input/binary_reader.hpp>
6046// __ _____ _____ _____
6047// __| | __| | | | JSON for Modern C++
6048// | | |__ | | | | | | version 3.11.2
6049// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6050//
6051// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
6052// SPDX-License-Identifier: MIT
6053
6054
6055
6056#include <algorithm> // generate_n
6057#include <array> // array
6058#include <cmath> // ldexp
6059#include <cstddef> // size_t
6060#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6061#include <cstdio> // snprintf
6062#include <cstring> // memcpy
6063#include <iterator> // back_inserter
6064#include <limits> // numeric_limits
6065#include <string> // char_traits, string
6066#include <utility> // make_pair, move
6067#include <vector> // vector
6068
6069// #include <nlohmann/detail/exceptions.hpp>
6070
6071// #include <nlohmann/detail/input/input_adapters.hpp>
6072// __ _____ _____ _____
6073// __| | __| | | | JSON for Modern C++
6074// | | |__ | | | | | | version 3.11.2
6075// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6076//
6077// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
6078// SPDX-License-Identifier: MIT
6079
6080
6081
6082#include <array> // array
6083#include <cstddef> // size_t
6084#include <cstring> // strlen
6085#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6086#include <memory> // shared_ptr, make_shared, addressof
6087#include <numeric> // accumulate
6088#include <string> // string, char_traits
6089#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6090#include <utility> // pair, declval
6091
6092#ifndef JSON_NO_IO
6093 #include <cstdio> // FILE *
6094 #include <istream> // istream
6095#endif // JSON_NO_IO
6096
6097// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6098
6099// #include <nlohmann/detail/macro_scope.hpp>
6100
6101
6103namespace detail
6104{
6105
6107enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
6108
6110// input adapters //
6112
6113#ifndef JSON_NO_IO
6118class file_input_adapter
6119{
6120 public:
6121 using char_type = char;
6122
6124 explicit file_input_adapter(std::FILE* f) noexcept
6125 : m_file(f)
6126 {
6127 JSON_ASSERT(m_file != nullptr);
6128 }
6129
6130 // make class move-only
6131 file_input_adapter(const file_input_adapter&) = delete;
6132 file_input_adapter(file_input_adapter&&) noexcept = default;
6133 file_input_adapter& operator=(const file_input_adapter&) = delete;
6134 file_input_adapter& operator=(file_input_adapter&&) = delete;
6135 ~file_input_adapter() = default;
6136
6137 std::char_traits<char>::int_type get_character() noexcept
6138 {
6139 return std::fgetc(m_file);
6140 }
6141
6142 private:
6144 std::FILE* m_file;
6145};
6146
6147
6157class input_stream_adapter
6158{
6159 public:
6160 using char_type = char;
6161
6162 ~input_stream_adapter()
6163 {
6164 // clear stream flags; we use underlying streambuf I/O, do not
6165 // maintain ifstream flags, except eof
6166 if (is != nullptr)
6167 {
6168 is->clear(is->rdstate() & std::ios::eofbit);
6169 }
6170 }
6171
6172 explicit input_stream_adapter(std::istream& i)
6173 : is(&i), sb(i.rdbuf())
6174 {}
6175
6176 // delete because of pointer members
6177 input_stream_adapter(const input_stream_adapter&) = delete;
6178 input_stream_adapter& operator=(input_stream_adapter&) = delete;
6179 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
6180
6181 input_stream_adapter(input_stream_adapter&& rhs) noexcept
6182 : is(rhs.is), sb(rhs.sb)
6183 {
6184 rhs.is = nullptr;
6185 rhs.sb = nullptr;
6186 }
6187
6188 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6189 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6190 // end up as the same value, e.g. 0xFFFFFFFF.
6191 std::char_traits<char>::int_type get_character()
6192 {
6193 auto res = sb->sbumpc();
6194 // set eof manually, as we don't use the istream interface.
6195 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6196 {
6197 is->clear(is->rdstate() | std::ios::eofbit);
6198 }
6199 return res;
6200 }
6201
6202 private:
6204 std::istream* is = nullptr;
6205 std::streambuf* sb = nullptr;
6206};
6207#endif // JSON_NO_IO
6208
6209// General-purpose iterator-based adapter. It might not be as fast as
6210// theoretically possible for some containers, but it is extremely versatile.
6211template<typename IteratorType>
6212class iterator_input_adapter
6213{
6214 public:
6215 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6216
6217 iterator_input_adapter(IteratorType first, IteratorType last)
6218 : current(std::move(first)), end(std::move(last))
6219 {}
6220
6221 typename std::char_traits<char_type>::int_type get_character()
6222 {
6223 if (JSON_HEDLEY_LIKELY(current != end))
6224 {
6225 auto result = std::char_traits<char_type>::to_int_type(*current);
6226 std::advance(current, 1);
6227 return result;
6228 }
6229
6230 return std::char_traits<char_type>::eof();
6231 }
6232
6233 private:
6234 IteratorType current;
6235 IteratorType end;
6236
6237 template<typename BaseInputAdapter, size_t T>
6238 friend struct wide_string_input_helper;
6239
6240 bool empty() const
6241 {
6242 return current == end;
6243 }
6244};
6245
6246
6247template<typename BaseInputAdapter, size_t T>
6248struct wide_string_input_helper;
6249
6250template<typename BaseInputAdapter>
6251struct wide_string_input_helper<BaseInputAdapter, 4>
6252{
6253 // UTF-32
6254 static void fill_buffer(BaseInputAdapter& input,
6255 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6256 size_t& utf8_bytes_index,
6257 size_t& utf8_bytes_filled)
6258 {
6259 utf8_bytes_index = 0;
6260
6261 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6262 {
6263 utf8_bytes[0] = std::char_traits<char>::eof();
6264 utf8_bytes_filled = 1;
6265 }
6266 else
6267 {
6268 // get the current character
6269 const auto wc = input.get_character();
6270
6271 // UTF-32 to UTF-8 encoding
6272 if (wc < 0x80)
6273 {
6274 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6275 utf8_bytes_filled = 1;
6276 }
6277 else if (wc <= 0x7FF)
6278 {
6279 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6280 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6281 utf8_bytes_filled = 2;
6282 }
6283 else if (wc <= 0xFFFF)
6284 {
6285 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6286 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6287 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6288 utf8_bytes_filled = 3;
6289 }
6290 else if (wc <= 0x10FFFF)
6291 {
6292 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6293 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6294 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6295 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6296 utf8_bytes_filled = 4;
6297 }
6298 else
6299 {
6300 // unknown character
6301 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6302 utf8_bytes_filled = 1;
6303 }
6304 }
6305 }
6306};
6307
6308template<typename BaseInputAdapter>
6309struct wide_string_input_helper<BaseInputAdapter, 2>
6310{
6311 // UTF-16
6312 static void fill_buffer(BaseInputAdapter& input,
6313 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6314 size_t& utf8_bytes_index,
6315 size_t& utf8_bytes_filled)
6316 {
6317 utf8_bytes_index = 0;
6318
6319 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6320 {
6321 utf8_bytes[0] = std::char_traits<char>::eof();
6322 utf8_bytes_filled = 1;
6323 }
6324 else
6325 {
6326 // get the current character
6327 const auto wc = input.get_character();
6328
6329 // UTF-16 to UTF-8 encoding
6330 if (wc < 0x80)
6331 {
6332 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6333 utf8_bytes_filled = 1;
6334 }
6335 else if (wc <= 0x7FF)
6336 {
6337 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6338 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6339 utf8_bytes_filled = 2;
6340 }
6341 else if (0xD800 > wc || wc >= 0xE000)
6342 {
6343 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6344 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6345 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6346 utf8_bytes_filled = 3;
6347 }
6348 else
6349 {
6350 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6351 {
6352 const auto wc2 = static_cast<unsigned int>(input.get_character());
6353 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6354 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6355 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6356 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6357 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6358 utf8_bytes_filled = 4;
6359 }
6360 else
6361 {
6362 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6363 utf8_bytes_filled = 1;
6364 }
6365 }
6366 }
6367 }
6368};
6369
6370// Wraps another input apdater to convert wide character types into individual bytes.
6371template<typename BaseInputAdapter, typename WideCharType>
6372class wide_string_input_adapter
6373{
6374 public:
6375 using char_type = char;
6376
6377 wide_string_input_adapter(BaseInputAdapter base)
6378 : base_adapter(base) {}
6379
6380 typename std::char_traits<char>::int_type get_character() noexcept
6381 {
6382 // check if buffer needs to be filled
6383 if (utf8_bytes_index == utf8_bytes_filled)
6384 {
6385 fill_buffer<sizeof(WideCharType)>();
6386
6387 JSON_ASSERT(utf8_bytes_filled > 0);
6388 JSON_ASSERT(utf8_bytes_index == 0);
6389 }
6390
6391 // use buffer
6392 JSON_ASSERT(utf8_bytes_filled > 0);
6393 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6394 return utf8_bytes[utf8_bytes_index++];
6395 }
6396
6397 private:
6398 BaseInputAdapter base_adapter;
6399
6400 template<size_t T>
6401 void fill_buffer()
6402 {
6403 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6404 }
6405
6407 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6408
6410 std::size_t utf8_bytes_index = 0;
6412 std::size_t utf8_bytes_filled = 0;
6413};
6414
6415
6416template<typename IteratorType, typename Enable = void>
6417struct iterator_input_adapter_factory
6418{
6419 using iterator_type = IteratorType;
6420 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6421 using adapter_type = iterator_input_adapter<iterator_type>;
6422
6423 static adapter_type create(IteratorType first, IteratorType last)
6424 {
6425 return adapter_type(std::move(first), std::move(last));
6426 }
6427};
6428
6429template<typename T>
6430struct is_iterator_of_multibyte
6431{
6432 using value_type = typename std::iterator_traits<T>::value_type;
6433 enum
6434 {
6435 value = sizeof(value_type) > 1
6436 };
6437};
6438
6439template<typename IteratorType>
6440struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
6441{
6442 using iterator_type = IteratorType;
6443 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6444 using base_adapter_type = iterator_input_adapter<iterator_type>;
6445 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
6446
6447 static adapter_type create(IteratorType first, IteratorType last)
6448 {
6449 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6450 }
6451};
6452
6453// General purpose iterator-based input
6454template<typename IteratorType>
6455typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
6456{
6457 using factory_type = iterator_input_adapter_factory<IteratorType>;
6458 return factory_type::create(first, last);
6459}
6460
6461// Convenience shorthand from container to iterator
6462// Enables ADL on begin(container) and end(container)
6463// Encloses the using declarations in namespace for not to leak them to outside scope
6464
6465namespace container_input_adapter_factory_impl
6466{
6467
6468using std::begin;
6469using std::end;
6470
6471template<typename ContainerType, typename Enable = void>
6473
6474template<typename ContainerType>
6476 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6477 {
6478 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6479
6480 static adapter_type create(const ContainerType& container)
6481{
6482 return input_adapter(begin(container), end(container));
6483}
6484 };
6485
6486} // namespace container_input_adapter_factory_impl
6487
6488template<typename ContainerType>
6489typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
6490{
6491 return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
6492}
6493
6494#ifndef JSON_NO_IO
6495// Special cases with fast paths
6496inline file_input_adapter input_adapter(std::FILE* file)
6497{
6498 return file_input_adapter(file);
6499}
6500
6501inline input_stream_adapter input_adapter(std::istream& stream)
6502{
6503 return input_stream_adapter(stream);
6504}
6505
6506inline input_stream_adapter input_adapter(std::istream&& stream)
6507{
6508 return input_stream_adapter(stream);
6509}
6510#endif // JSON_NO_IO
6511
6512using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6513
6514// Null-delimited strings, and the like.
6515template < typename CharT,
6516 typename std::enable_if <
6517 std::is_pointer<CharT>::value&&
6518 !std::is_array<CharT>::value&&
6519 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6520 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6521 int >::type = 0 >
6522contiguous_bytes_input_adapter input_adapter(CharT b)
6523{
6524 auto length = std::strlen(reinterpret_cast<const char*>(b));
6525 const auto* ptr = reinterpret_cast<const char*>(b);
6526 return input_adapter(ptr, ptr + length);
6527}
6528
6529template<typename T, std::size_t N>
6530auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6531{
6532 return input_adapter(array, array + N);
6533}
6534
6535// This class only handles inputs of input_buffer_adapter type.
6536// It's required so that expressions like {ptr, len} can be implicitly cast
6537// to the correct adapter.
6538class span_input_adapter
6539{
6540 public:
6541 template < typename CharT,
6542 typename std::enable_if <
6543 std::is_pointer<CharT>::value&&
6544 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6545 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6546 int >::type = 0 >
6547 span_input_adapter(CharT b, std::size_t l)
6548 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6549
6550 template<class IteratorType,
6551 typename std::enable_if<
6552 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6553 int>::type = 0>
6554 span_input_adapter(IteratorType first, IteratorType last)
6555 : ia(input_adapter(first, last)) {}
6556
6557 contiguous_bytes_input_adapter&& get()
6558 {
6559 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6560 }
6561
6562 private:
6563 contiguous_bytes_input_adapter ia;
6564};
6565
6566} // namespace detail
6568
6569// #include <nlohmann/detail/input/json_sax.hpp>
6570// __ _____ _____ _____
6571// __| | __| | | | JSON for Modern C++
6572// | | |__ | | | | | | version 3.11.2
6573// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6574//
6575// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
6576// SPDX-License-Identifier: MIT
6577
6578
6579
6580#include <cstddef>
6581#include <string> // string
6582#include <utility> // move
6583#include <vector> // vector
6584
6585// #include <nlohmann/detail/exceptions.hpp>
6586
6587// #include <nlohmann/detail/macro_scope.hpp>
6588
6589// #include <nlohmann/detail/string_concat.hpp>
6590
6591
6593
6602template<typename BasicJsonType>
6604{
6605 using number_integer_t = typename BasicJsonType::number_integer_t;
6606 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6607 using number_float_t = typename BasicJsonType::number_float_t;
6608 using string_t = typename BasicJsonType::string_t;
6609 using binary_t = typename BasicJsonType::binary_t;
6610
6615 virtual bool null() = 0;
6616
6622 virtual bool boolean(bool val) = 0;
6623
6629 virtual bool number_integer(number_integer_t val) = 0;
6630
6636 virtual bool number_unsigned(number_unsigned_t val) = 0;
6637
6644 virtual bool number_float(number_float_t val, const string_t& s) = 0;
6645
6652 virtual bool string(string_t& val) = 0;
6653
6660 virtual bool binary(binary_t& val) = 0;
6661
6668 virtual bool start_object(std::size_t elements) = 0;
6669
6676 virtual bool key(string_t& val) = 0;
6677
6682 virtual bool end_object() = 0;
6683
6690 virtual bool start_array(std::size_t elements) = 0;
6691
6696 virtual bool end_array() = 0;
6697
6705 virtual bool parse_error(std::size_t position,
6706 const std::string& last_token,
6707 const detail::exception& ex) = 0;
6708
6709 json_sax() = default;
6710 json_sax(const json_sax&) = default;
6711 json_sax(json_sax&&) noexcept = default;
6712 json_sax& operator=(const json_sax&) = default;
6713 json_sax& operator=(json_sax&&) noexcept = default;
6714 virtual ~json_sax() = default;
6715};
6716
6717
6718namespace detail
6719{
6733template<typename BasicJsonType>
6735{
6736 public:
6737 using number_integer_t = typename BasicJsonType::number_integer_t;
6738 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6739 using number_float_t = typename BasicJsonType::number_float_t;
6740 using string_t = typename BasicJsonType::string_t;
6741 using binary_t = typename BasicJsonType::binary_t;
6742
6748 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
6749 : root(r), allow_exceptions(allow_exceptions_)
6750 {}
6751
6752 // make class move-only
6754 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6756 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6758
6759 bool null()
6760 {
6761 handle_value(nullptr);
6762 return true;
6763 }
6764
6765 bool boolean(bool val)
6766 {
6767 handle_value(val);
6768 return true;
6769 }
6770
6772 {
6773 handle_value(val);
6774 return true;
6775 }
6776
6778 {
6779 handle_value(val);
6780 return true;
6781 }
6782
6783 bool number_float(number_float_t val, const string_t& /*unused*/)
6784 {
6785 handle_value(val);
6786 return true;
6787 }
6788
6789 bool string(string_t& val)
6790 {
6791 handle_value(val);
6792 return true;
6793 }
6794
6795 bool binary(binary_t& val)
6796 {
6797 handle_value(std::move(val));
6798 return true;
6799 }
6800
6801 bool start_object(std::size_t len)
6802 {
6803 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
6804
6805 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6806 {
6807 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6808 }
6809
6810 return true;
6811 }
6812
6813 bool key(string_t& val)
6814 {
6815 JSON_ASSERT(!ref_stack.empty());
6816 JSON_ASSERT(ref_stack.back()->is_object());
6817
6818 // add null at given key and store the reference for later
6819 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
6820 return true;
6821 }
6822
6824 {
6825 JSON_ASSERT(!ref_stack.empty());
6826 JSON_ASSERT(ref_stack.back()->is_object());
6827
6828 ref_stack.back()->set_parents();
6829 ref_stack.pop_back();
6830 return true;
6831 }
6832
6833 bool start_array(std::size_t len)
6834 {
6835 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
6836
6837 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6838 {
6839 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
6840 }
6841
6842 return true;
6843 }
6844
6846 {
6847 JSON_ASSERT(!ref_stack.empty());
6848 JSON_ASSERT(ref_stack.back()->is_array());
6849
6850 ref_stack.back()->set_parents();
6851 ref_stack.pop_back();
6852 return true;
6853 }
6854
6855 template<class Exception>
6856 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6857 const Exception& ex)
6858 {
6859 errored = true;
6860 static_cast<void>(ex);
6861 if (allow_exceptions)
6862 {
6863 JSON_THROW(ex);
6864 }
6865 return false;
6866 }
6867
6868 constexpr bool is_errored() const
6869 {
6870 return errored;
6871 }
6872
6873 private:
6880 template<typename Value>
6882 BasicJsonType* handle_value(Value&& v)
6883 {
6884 if (ref_stack.empty())
6885 {
6886 root = BasicJsonType(std::forward<Value>(v));
6887 return &root;
6888 }
6889
6890 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6891
6892 if (ref_stack.back()->is_array())
6893 {
6894 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
6895 return &(ref_stack.back()->m_data.m_value.array->back());
6896 }
6897
6898 JSON_ASSERT(ref_stack.back()->is_object());
6899 JSON_ASSERT(object_element);
6900 *object_element = BasicJsonType(std::forward<Value>(v));
6901 return object_element;
6902 }
6903
6905 BasicJsonType& root;
6907 std::vector<BasicJsonType*> ref_stack {};
6909 BasicJsonType* object_element = nullptr;
6911 bool errored = false;
6913 const bool allow_exceptions = true;
6914};
6915
6916template<typename BasicJsonType>
6918{
6919 public:
6920 using number_integer_t = typename BasicJsonType::number_integer_t;
6921 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6922 using number_float_t = typename BasicJsonType::number_float_t;
6923 using string_t = typename BasicJsonType::string_t;
6924 using binary_t = typename BasicJsonType::binary_t;
6925 using parser_callback_t = typename BasicJsonType::parser_callback_t;
6926 using parse_event_t = typename BasicJsonType::parse_event_t;
6927
6929 const parser_callback_t cb,
6930 const bool allow_exceptions_ = true)
6931 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
6932 {
6933 keep_stack.push_back(true);
6934 }
6935
6936 // make class move-only
6938 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6940 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6942
6943 bool null()
6944 {
6945 handle_value(nullptr);
6946 return true;
6947 }
6948
6949 bool boolean(bool val)
6950 {
6951 handle_value(val);
6952 return true;
6953 }
6954
6956 {
6957 handle_value(val);
6958 return true;
6959 }
6960
6962 {
6963 handle_value(val);
6964 return true;
6965 }
6966
6967 bool number_float(number_float_t val, const string_t& /*unused*/)
6968 {
6969 handle_value(val);
6970 return true;
6971 }
6972
6973 bool string(string_t& val)
6974 {
6975 handle_value(val);
6976 return true;
6977 }
6978
6979 bool binary(binary_t& val)
6980 {
6981 handle_value(std::move(val));
6982 return true;
6983 }
6984
6985 bool start_object(std::size_t len)
6986 {
6987 // check callback for object start
6988 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
6989 keep_stack.push_back(keep);
6990
6991 auto val = handle_value(BasicJsonType::value_t::object, true);
6992 ref_stack.push_back(val.second);
6993
6994 // check object limit
6995 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6996 {
6997 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6998 }
6999
7000 return true;
7001 }
7002
7003 bool key(string_t& val)
7004 {
7005 BasicJsonType k = BasicJsonType(val);
7006
7007 // check callback for key
7008 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
7009 key_keep_stack.push_back(keep);
7010
7011 // add discarded value at given key and store the reference for later
7012 if (keep && ref_stack.back())
7013 {
7014 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
7015 }
7016
7017 return true;
7018 }
7019
7021 {
7022 if (ref_stack.back())
7023 {
7024 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
7025 {
7026 // discard object
7027 *ref_stack.back() = discarded;
7028 }
7029 else
7030 {
7031 ref_stack.back()->set_parents();
7032 }
7033 }
7034
7035 JSON_ASSERT(!ref_stack.empty());
7036 JSON_ASSERT(!keep_stack.empty());
7037 ref_stack.pop_back();
7038 keep_stack.pop_back();
7039
7040 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
7041 {
7042 // remove discarded value
7043 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
7044 {
7045 if (it->is_discarded())
7046 {
7047 ref_stack.back()->erase(it);
7048 break;
7049 }
7050 }
7051 }
7052
7053 return true;
7054 }
7055
7056 bool start_array(std::size_t len)
7057 {
7058 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
7059 keep_stack.push_back(keep);
7060
7061 auto val = handle_value(BasicJsonType::value_t::array, true);
7062 ref_stack.push_back(val.second);
7063
7064 // check array limit
7065 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7066 {
7067 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
7068 }
7069
7070 return true;
7071 }
7072
7074 {
7075 bool keep = true;
7076
7077 if (ref_stack.back())
7078 {
7079 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
7080 if (keep)
7081 {
7082 ref_stack.back()->set_parents();
7083 }
7084 else
7085 {
7086 // discard array
7087 *ref_stack.back() = discarded;
7088 }
7089 }
7090
7091 JSON_ASSERT(!ref_stack.empty());
7092 JSON_ASSERT(!keep_stack.empty());
7093 ref_stack.pop_back();
7094 keep_stack.pop_back();
7095
7096 // remove discarded value
7097 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
7098 {
7099 ref_stack.back()->m_data.m_value.array->pop_back();
7100 }
7101
7102 return true;
7103 }
7104
7105 template<class Exception>
7106 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7107 const Exception& ex)
7108 {
7109 errored = true;
7110 static_cast<void>(ex);
7111 if (allow_exceptions)
7112 {
7113 JSON_THROW(ex);
7114 }
7115 return false;
7116 }
7117
7118 constexpr bool is_errored() const
7119 {
7120 return errored;
7121 }
7122
7123 private:
7139 template<typename Value>
7140 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
7141 {
7142 JSON_ASSERT(!keep_stack.empty());
7143
7144 // do not handle this value if we know it would be added to a discarded
7145 // container
7146 if (!keep_stack.back())
7147 {
7148 return {false, nullptr};
7149 }
7150
7151 // create value
7152 auto value = BasicJsonType(std::forward<Value>(v));
7153
7154 // check callback
7155 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
7156
7157 // do not handle this value if we just learnt it shall be discarded
7158 if (!keep)
7159 {
7160 return {false, nullptr};
7161 }
7162
7163 if (ref_stack.empty())
7164 {
7165 root = std::move(value);
7166 return {true, &root};
7167 }
7168
7169 // skip this value if we already decided to skip the parent
7170 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
7171 if (!ref_stack.back())
7172 {
7173 return {false, nullptr};
7174 }
7175
7176 // we now only expect arrays and objects
7177 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7178
7179 // array
7180 if (ref_stack.back()->is_array())
7181 {
7182 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
7183 return {true, &(ref_stack.back()->m_data.m_value.array->back())};
7184 }
7185
7186 // object
7187 JSON_ASSERT(ref_stack.back()->is_object());
7188 // check if we should store an element for the current key
7189 JSON_ASSERT(!key_keep_stack.empty());
7190 const bool store_element = key_keep_stack.back();
7191 key_keep_stack.pop_back();
7192
7193 if (!store_element)
7194 {
7195 return {false, nullptr};
7196 }
7197
7198 JSON_ASSERT(object_element);
7199 *object_element = std::move(value);
7200 return {true, object_element};
7201 }
7202
7204 BasicJsonType& root;
7206 std::vector<BasicJsonType*> ref_stack {};
7208 std::vector<bool> keep_stack {};
7210 std::vector<bool> key_keep_stack {};
7212 BasicJsonType* object_element = nullptr;
7214 bool errored = false;
7216 const parser_callback_t callback = nullptr;
7218 const bool allow_exceptions = true;
7220 BasicJsonType discarded = BasicJsonType::value_t::discarded;
7221};
7222
7223template<typename BasicJsonType>
7225{
7226 public:
7227 using number_integer_t = typename BasicJsonType::number_integer_t;
7228 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7229 using number_float_t = typename BasicJsonType::number_float_t;
7230 using string_t = typename BasicJsonType::string_t;
7231 using binary_t = typename BasicJsonType::binary_t;
7232
7233 bool null()
7234 {
7235 return true;
7236 }
7237
7238 bool boolean(bool /*unused*/)
7239 {
7240 return true;
7241 }
7242
7244 {
7245 return true;
7246 }
7247
7249 {
7250 return true;
7251 }
7252
7253 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
7254 {
7255 return true;
7256 }
7257
7258 bool string(string_t& /*unused*/)
7259 {
7260 return true;
7261 }
7262
7263 bool binary(binary_t& /*unused*/)
7264 {
7265 return true;
7266 }
7267
7268 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7269 {
7270 return true;
7271 }
7272
7273 bool key(string_t& /*unused*/)
7274 {
7275 return true;
7276 }
7277
7279 {
7280 return true;
7281 }
7282
7283 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7284 {
7285 return true;
7286 }
7287
7289 {
7290 return true;
7291 }
7292
7293 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
7294 {
7295 return false;
7296 }
7297};
7298
7299} // namespace detail
7301
7302// #include <nlohmann/detail/input/lexer.hpp>
7303// __ _____ _____ _____
7304// __| | __| | | | JSON for Modern C++
7305// | | |__ | | | | | | version 3.11.2
7306// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7307//
7308// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7309// SPDX-License-Identifier: MIT
7310
7311
7312
7313#include <array> // array
7314#include <clocale> // localeconv
7315#include <cstddef> // size_t
7316#include <cstdio> // snprintf
7317#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7318#include <initializer_list> // initializer_list
7319#include <string> // char_traits, string
7320#include <utility> // move
7321#include <vector> // vector
7322
7323// #include <nlohmann/detail/input/input_adapters.hpp>
7324
7325// #include <nlohmann/detail/input/position_t.hpp>
7326
7327// #include <nlohmann/detail/macro_scope.hpp>
7328
7329
7331namespace detail
7332{
7333
7335// lexer //
7337
7338template<typename BasicJsonType>
7340{
7341 public:
7343 enum class token_type
7344 {
7345 uninitialized,
7346 literal_true,
7347 literal_false,
7348 literal_null,
7349 value_string,
7350 value_unsigned,
7351 value_integer,
7352 value_float,
7353 begin_array,
7354 begin_object,
7355 end_array,
7356 end_object,
7357 name_separator,
7358 value_separator,
7359 parse_error,
7360 end_of_input,
7361 literal_or_value
7362 };
7363
7367 static const char* token_type_name(const token_type t) noexcept
7368 {
7369 switch (t)
7370 {
7371 case token_type::uninitialized:
7372 return "<uninitialized>";
7373 case token_type::literal_true:
7374 return "true literal";
7375 case token_type::literal_false:
7376 return "false literal";
7377 case token_type::literal_null:
7378 return "null literal";
7379 case token_type::value_string:
7380 return "string literal";
7381 case token_type::value_unsigned:
7382 case token_type::value_integer:
7383 case token_type::value_float:
7384 return "number literal";
7385 case token_type::begin_array:
7386 return "'['";
7387 case token_type::begin_object:
7388 return "'{'";
7389 case token_type::end_array:
7390 return "']'";
7391 case token_type::end_object:
7392 return "'}'";
7393 case token_type::name_separator:
7394 return "':'";
7395 case token_type::value_separator:
7396 return "','";
7397 case token_type::parse_error:
7398 return "<parse error>";
7399 case token_type::end_of_input:
7400 return "end of input";
7401 case token_type::literal_or_value:
7402 return "'[', '{', or a literal";
7403 // LCOV_EXCL_START
7404 default: // catch non-enum values
7405 return "unknown token";
7406 // LCOV_EXCL_STOP
7407 }
7408 }
7409};
7415template<typename BasicJsonType, typename InputAdapterType>
7416class lexer : public lexer_base<BasicJsonType>
7417{
7418 using number_integer_t = typename BasicJsonType::number_integer_t;
7419 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7420 using number_float_t = typename BasicJsonType::number_float_t;
7421 using string_t = typename BasicJsonType::string_t;
7422 using char_type = typename InputAdapterType::char_type;
7423 using char_int_type = typename std::char_traits<char_type>::int_type;
7424
7425 public:
7427
7428 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7429 : ia(std::move(adapter))
7430 , ignore_comments(ignore_comments_)
7431 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7432 {}
7433
7434 // delete because of pointer members
7435 lexer(const lexer&) = delete;
7436 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7437 lexer& operator=(lexer&) = delete;
7438 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7439 ~lexer() = default;
7440
7441 private:
7443 // locales
7445
7448 static char get_decimal_point() noexcept
7449 {
7450 const auto* loc = localeconv();
7451 JSON_ASSERT(loc != nullptr);
7452 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7453 }
7454
7456 // scan functions
7458
7474 int get_codepoint()
7475 {
7476 // this function only makes sense after reading `\u`
7477 JSON_ASSERT(current == 'u');
7478 int codepoint = 0;
7479
7480 const auto factors = { 12u, 8u, 4u, 0u };
7481 for (const auto factor : factors)
7482 {
7483 get();
7484
7485 if (current >= '0' && current <= '9')
7486 {
7487 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7488 }
7489 else if (current >= 'A' && current <= 'F')
7490 {
7491 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7492 }
7493 else if (current >= 'a' && current <= 'f')
7494 {
7495 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7496 }
7497 else
7498 {
7499 return -1;
7500 }
7501 }
7502
7503 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7504 return codepoint;
7505 }
7506
7522 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7523 {
7524 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7525 add(current);
7526
7527 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7528 {
7529 get();
7530 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
7531 {
7532 add(current);
7533 }
7534 else
7535 {
7536 error_message = "invalid string: ill-formed UTF-8 byte";
7537 return false;
7538 }
7539 }
7540
7541 return true;
7542 }
7543
7559 token_type scan_string()
7560 {
7561 // reset token_buffer (ignore opening quote)
7562 reset();
7563
7564 // we entered the function by reading an open quote
7565 JSON_ASSERT(current == '\"');
7566
7567 while (true)
7568 {
7569 // get next character
7570 switch (get())
7571 {
7572 // end of file while parsing string
7573 case std::char_traits<char_type>::eof():
7574 {
7575 error_message = "invalid string: missing closing quote";
7576 return token_type::parse_error;
7577 }
7578
7579 // closing quote
7580 case '\"':
7581 {
7582 return token_type::value_string;
7583 }
7584
7585 // escapes
7586 case '\\':
7587 {
7588 switch (get())
7589 {
7590 // quotation mark
7591 case '\"':
7592 add('\"');
7593 break;
7594 // reverse solidus
7595 case '\\':
7596 add('\\');
7597 break;
7598 // solidus
7599 case '/':
7600 add('/');
7601 break;
7602 // backspace
7603 case 'b':
7604 add('\b');
7605 break;
7606 // form feed
7607 case 'f':
7608 add('\f');
7609 break;
7610 // line feed
7611 case 'n':
7612 add('\n');
7613 break;
7614 // carriage return
7615 case 'r':
7616 add('\r');
7617 break;
7618 // tab
7619 case 't':
7620 add('\t');
7621 break;
7622
7623 // unicode escapes
7624 case 'u':
7625 {
7626 const int codepoint1 = get_codepoint();
7627 int codepoint = codepoint1; // start with codepoint1
7628
7629 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7630 {
7631 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7632 return token_type::parse_error;
7633 }
7634
7635 // check if code point is a high surrogate
7636 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7637 {
7638 // expect next \uxxxx entry
7639 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7640 {
7641 const int codepoint2 = get_codepoint();
7642
7643 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7644 {
7645 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7646 return token_type::parse_error;
7647 }
7648
7649 // check if codepoint2 is a low surrogate
7650 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7651 {
7652 // overwrite codepoint
7653 codepoint = static_cast<int>(
7654 // high surrogate occupies the most significant 22 bits
7655 (static_cast<unsigned int>(codepoint1) << 10u)
7656 // low surrogate occupies the least significant 15 bits
7657 + static_cast<unsigned int>(codepoint2)
7658 // there is still the 0xD800, 0xDC00 and 0x10000 noise
7659 // in the result, so we have to subtract with:
7660 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7661 - 0x35FDC00u);
7662 }
7663 else
7664 {
7665 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7666 return token_type::parse_error;
7667 }
7668 }
7669 else
7670 {
7671 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7672 return token_type::parse_error;
7673 }
7674 }
7675 else
7676 {
7677 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7678 {
7679 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7680 return token_type::parse_error;
7681 }
7682 }
7683
7684 // result of the above calculation yields a proper codepoint
7685 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7686
7687 // translate codepoint into bytes
7688 if (codepoint < 0x80)
7689 {
7690 // 1-byte characters: 0xxxxxxx (ASCII)
7691 add(static_cast<char_int_type>(codepoint));
7692 }
7693 else if (codepoint <= 0x7FF)
7694 {
7695 // 2-byte characters: 110xxxxx 10xxxxxx
7696 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7697 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7698 }
7699 else if (codepoint <= 0xFFFF)
7700 {
7701 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7702 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7703 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7704 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7705 }
7706 else
7707 {
7708 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7709 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7710 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7711 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7712 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7713 }
7714
7715 break;
7716 }
7717
7718 // other characters after escape
7719 default:
7720 error_message = "invalid string: forbidden character after backslash";
7721 return token_type::parse_error;
7722 }
7723
7724 break;
7725 }
7726
7727 // invalid control characters
7728 case 0x00:
7729 {
7730 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7731 return token_type::parse_error;
7732 }
7733
7734 case 0x01:
7735 {
7736 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7737 return token_type::parse_error;
7738 }
7739
7740 case 0x02:
7741 {
7742 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7743 return token_type::parse_error;
7744 }
7745
7746 case 0x03:
7747 {
7748 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7749 return token_type::parse_error;
7750 }
7751
7752 case 0x04:
7753 {
7754 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7755 return token_type::parse_error;
7756 }
7757
7758 case 0x05:
7759 {
7760 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7761 return token_type::parse_error;
7762 }
7763
7764 case 0x06:
7765 {
7766 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7767 return token_type::parse_error;
7768 }
7769
7770 case 0x07:
7771 {
7772 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7773 return token_type::parse_error;
7774 }
7775
7776 case 0x08:
7777 {
7778 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7779 return token_type::parse_error;
7780 }
7781
7782 case 0x09:
7783 {
7784 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7785 return token_type::parse_error;
7786 }
7787
7788 case 0x0A:
7789 {
7790 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7791 return token_type::parse_error;
7792 }
7793
7794 case 0x0B:
7795 {
7796 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7797 return token_type::parse_error;
7798 }
7799
7800 case 0x0C:
7801 {
7802 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7803 return token_type::parse_error;
7804 }
7805
7806 case 0x0D:
7807 {
7808 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7809 return token_type::parse_error;
7810 }
7811
7812 case 0x0E:
7813 {
7814 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7815 return token_type::parse_error;
7816 }
7817
7818 case 0x0F:
7819 {
7820 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7821 return token_type::parse_error;
7822 }
7823
7824 case 0x10:
7825 {
7826 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7827 return token_type::parse_error;
7828 }
7829
7830 case 0x11:
7831 {
7832 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7833 return token_type::parse_error;
7834 }
7835
7836 case 0x12:
7837 {
7838 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7839 return token_type::parse_error;
7840 }
7841
7842 case 0x13:
7843 {
7844 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7845 return token_type::parse_error;
7846 }
7847
7848 case 0x14:
7849 {
7850 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7851 return token_type::parse_error;
7852 }
7853
7854 case 0x15:
7855 {
7856 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7857 return token_type::parse_error;
7858 }
7859
7860 case 0x16:
7861 {
7862 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7863 return token_type::parse_error;
7864 }
7865
7866 case 0x17:
7867 {
7868 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7869 return token_type::parse_error;
7870 }
7871
7872 case 0x18:
7873 {
7874 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7875 return token_type::parse_error;
7876 }
7877
7878 case 0x19:
7879 {
7880 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7881 return token_type::parse_error;
7882 }
7883
7884 case 0x1A:
7885 {
7886 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7887 return token_type::parse_error;
7888 }
7889
7890 case 0x1B:
7891 {
7892 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7893 return token_type::parse_error;
7894 }
7895
7896 case 0x1C:
7897 {
7898 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7899 return token_type::parse_error;
7900 }
7901
7902 case 0x1D:
7903 {
7904 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7905 return token_type::parse_error;
7906 }
7907
7908 case 0x1E:
7909 {
7910 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7911 return token_type::parse_error;
7912 }
7913
7914 case 0x1F:
7915 {
7916 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7917 return token_type::parse_error;
7918 }
7919
7920 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7921 case 0x20:
7922 case 0x21:
7923 case 0x23:
7924 case 0x24:
7925 case 0x25:
7926 case 0x26:
7927 case 0x27:
7928 case 0x28:
7929 case 0x29:
7930 case 0x2A:
7931 case 0x2B:
7932 case 0x2C:
7933 case 0x2D:
7934 case 0x2E:
7935 case 0x2F:
7936 case 0x30:
7937 case 0x31:
7938 case 0x32:
7939 case 0x33:
7940 case 0x34:
7941 case 0x35:
7942 case 0x36:
7943 case 0x37:
7944 case 0x38:
7945 case 0x39:
7946 case 0x3A:
7947 case 0x3B:
7948 case 0x3C:
7949 case 0x3D:
7950 case 0x3E:
7951 case 0x3F:
7952 case 0x40:
7953 case 0x41:
7954 case 0x42:
7955 case 0x43:
7956 case 0x44:
7957 case 0x45:
7958 case 0x46:
7959 case 0x47:
7960 case 0x48:
7961 case 0x49:
7962 case 0x4A:
7963 case 0x4B:
7964 case 0x4C:
7965 case 0x4D:
7966 case 0x4E:
7967 case 0x4F:
7968 case 0x50:
7969 case 0x51:
7970 case 0x52:
7971 case 0x53:
7972 case 0x54:
7973 case 0x55:
7974 case 0x56:
7975 case 0x57:
7976 case 0x58:
7977 case 0x59:
7978 case 0x5A:
7979 case 0x5B:
7980 case 0x5D:
7981 case 0x5E:
7982 case 0x5F:
7983 case 0x60:
7984 case 0x61:
7985 case 0x62:
7986 case 0x63:
7987 case 0x64:
7988 case 0x65:
7989 case 0x66:
7990 case 0x67:
7991 case 0x68:
7992 case 0x69:
7993 case 0x6A:
7994 case 0x6B:
7995 case 0x6C:
7996 case 0x6D:
7997 case 0x6E:
7998 case 0x6F:
7999 case 0x70:
8000 case 0x71:
8001 case 0x72:
8002 case 0x73:
8003 case 0x74:
8004 case 0x75:
8005 case 0x76:
8006 case 0x77:
8007 case 0x78:
8008 case 0x79:
8009 case 0x7A:
8010 case 0x7B:
8011 case 0x7C:
8012 case 0x7D:
8013 case 0x7E:
8014 case 0x7F:
8015 {
8016 add(current);
8017 break;
8018 }
8019
8020 // U+0080..U+07FF: bytes C2..DF 80..BF
8021 case 0xC2:
8022 case 0xC3:
8023 case 0xC4:
8024 case 0xC5:
8025 case 0xC6:
8026 case 0xC7:
8027 case 0xC8:
8028 case 0xC9:
8029 case 0xCA:
8030 case 0xCB:
8031 case 0xCC:
8032 case 0xCD:
8033 case 0xCE:
8034 case 0xCF:
8035 case 0xD0:
8036 case 0xD1:
8037 case 0xD2:
8038 case 0xD3:
8039 case 0xD4:
8040 case 0xD5:
8041 case 0xD6:
8042 case 0xD7:
8043 case 0xD8:
8044 case 0xD9:
8045 case 0xDA:
8046 case 0xDB:
8047 case 0xDC:
8048 case 0xDD:
8049 case 0xDE:
8050 case 0xDF:
8051 {
8052 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
8053 {
8054 return token_type::parse_error;
8055 }
8056 break;
8057 }
8058
8059 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
8060 case 0xE0:
8061 {
8062 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
8063 {
8064 return token_type::parse_error;
8065 }
8066 break;
8067 }
8068
8069 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
8070 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
8071 case 0xE1:
8072 case 0xE2:
8073 case 0xE3:
8074 case 0xE4:
8075 case 0xE5:
8076 case 0xE6:
8077 case 0xE7:
8078 case 0xE8:
8079 case 0xE9:
8080 case 0xEA:
8081 case 0xEB:
8082 case 0xEC:
8083 case 0xEE:
8084 case 0xEF:
8085 {
8086 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
8087 {
8088 return token_type::parse_error;
8089 }
8090 break;
8091 }
8092
8093 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
8094 case 0xED:
8095 {
8096 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
8097 {
8098 return token_type::parse_error;
8099 }
8100 break;
8101 }
8102
8103 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
8104 case 0xF0:
8105 {
8106 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8107 {
8108 return token_type::parse_error;
8109 }
8110 break;
8111 }
8112
8113 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
8114 case 0xF1:
8115 case 0xF2:
8116 case 0xF3:
8117 {
8118 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8119 {
8120 return token_type::parse_error;
8121 }
8122 break;
8123 }
8124
8125 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
8126 case 0xF4:
8127 {
8128 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
8129 {
8130 return token_type::parse_error;
8131 }
8132 break;
8133 }
8134
8135 // remaining bytes (80..C1 and F5..FF) are ill-formed
8136 default:
8137 {
8138 error_message = "invalid string: ill-formed UTF-8 byte";
8139 return token_type::parse_error;
8140 }
8141 }
8142 }
8143 }
8144
8149 bool scan_comment()
8150 {
8151 switch (get())
8152 {
8153 // single-line comments skip input until a newline or EOF is read
8154 case '/':
8155 {
8156 while (true)
8157 {
8158 switch (get())
8159 {
8160 case '\n':
8161 case '\r':
8162 case std::char_traits<char_type>::eof():
8163 case '\0':
8164 return true;
8165
8166 default:
8167 break;
8168 }
8169 }
8170 }
8171
8172 // multi-line comments skip input until */ is read
8173 case '*':
8174 {
8175 while (true)
8176 {
8177 switch (get())
8178 {
8179 case std::char_traits<char_type>::eof():
8180 case '\0':
8181 {
8182 error_message = "invalid comment; missing closing '*/'";
8183 return false;
8184 }
8185
8186 case '*':
8187 {
8188 switch (get())
8189 {
8190 case '/':
8191 return true;
8192
8193 default:
8194 {
8195 unget();
8196 continue;
8197 }
8198 }
8199 }
8200
8201 default:
8202 continue;
8203 }
8204 }
8205 }
8206
8207 // unexpected character after reading '/'
8208 default:
8209 {
8210 error_message = "invalid comment; expecting '/' or '*' after '/'";
8211 return false;
8212 }
8213 }
8214 }
8215
8217 static void strtof(float& f, const char* str, char** endptr) noexcept
8218 {
8219 f = std::strtof(str, endptr);
8220 }
8221
8223 static void strtof(double& f, const char* str, char** endptr) noexcept
8224 {
8225 f = std::strtod(str, endptr);
8226 }
8227
8229 static void strtof(long double& f, const char* str, char** endptr) noexcept
8230 {
8231 f = std::strtold(str, endptr);
8232 }
8233
8274 token_type scan_number() // lgtm [cpp/use-of-goto]
8275 {
8276 // reset token_buffer to store the number's bytes
8277 reset();
8278
8279 // the type of the parsed number; initially set to unsigned; will be
8280 // changed if minus sign, decimal point or exponent is read
8281 token_type number_type = token_type::value_unsigned;
8282
8283 // state (init): we just found out we need to scan a number
8284 switch (current)
8285 {
8286 case '-':
8287 {
8288 add(current);
8289 goto scan_number_minus;
8290 }
8291
8292 case '0':
8293 {
8294 add(current);
8295 goto scan_number_zero;
8296 }
8297
8298 case '1':
8299 case '2':
8300 case '3':
8301 case '4':
8302 case '5':
8303 case '6':
8304 case '7':
8305 case '8':
8306 case '9':
8307 {
8308 add(current);
8309 goto scan_number_any1;
8310 }
8311
8312 // all other characters are rejected outside scan_number()
8313 default: // LCOV_EXCL_LINE
8314 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8315 }
8316
8317scan_number_minus:
8318 // state: we just parsed a leading minus sign
8319 number_type = token_type::value_integer;
8320 switch (get())
8321 {
8322 case '0':
8323 {
8324 add(current);
8325 goto scan_number_zero;
8326 }
8327
8328 case '1':
8329 case '2':
8330 case '3':
8331 case '4':
8332 case '5':
8333 case '6':
8334 case '7':
8335 case '8':
8336 case '9':
8337 {
8338 add(current);
8339 goto scan_number_any1;
8340 }
8341
8342 default:
8343 {
8344 error_message = "invalid number; expected digit after '-'";
8345 return token_type::parse_error;
8346 }
8347 }
8348
8349scan_number_zero:
8350 // state: we just parse a zero (maybe with a leading minus sign)
8351 switch (get())
8352 {
8353 case '.':
8354 {
8355 add(decimal_point_char);
8356 goto scan_number_decimal1;
8357 }
8358
8359 case 'e':
8360 case 'E':
8361 {
8362 add(current);
8363 goto scan_number_exponent;
8364 }
8365
8366 default:
8367 goto scan_number_done;
8368 }
8369
8370scan_number_any1:
8371 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8372 switch (get())
8373 {
8374 case '0':
8375 case '1':
8376 case '2':
8377 case '3':
8378 case '4':
8379 case '5':
8380 case '6':
8381 case '7':
8382 case '8':
8383 case '9':
8384 {
8385 add(current);
8386 goto scan_number_any1;
8387 }
8388
8389 case '.':
8390 {
8391 add(decimal_point_char);
8392 goto scan_number_decimal1;
8393 }
8394
8395 case 'e':
8396 case 'E':
8397 {
8398 add(current);
8399 goto scan_number_exponent;
8400 }
8401
8402 default:
8403 goto scan_number_done;
8404 }
8405
8406scan_number_decimal1:
8407 // state: we just parsed a decimal point
8408 number_type = token_type::value_float;
8409 switch (get())
8410 {
8411 case '0':
8412 case '1':
8413 case '2':
8414 case '3':
8415 case '4':
8416 case '5':
8417 case '6':
8418 case '7':
8419 case '8':
8420 case '9':
8421 {
8422 add(current);
8423 goto scan_number_decimal2;
8424 }
8425
8426 default:
8427 {
8428 error_message = "invalid number; expected digit after '.'";
8429 return token_type::parse_error;
8430 }
8431 }
8432
8433scan_number_decimal2:
8434 // we just parsed at least one number after a decimal point
8435 switch (get())
8436 {
8437 case '0':
8438 case '1':
8439 case '2':
8440 case '3':
8441 case '4':
8442 case '5':
8443 case '6':
8444 case '7':
8445 case '8':
8446 case '9':
8447 {
8448 add(current);
8449 goto scan_number_decimal2;
8450 }
8451
8452 case 'e':
8453 case 'E':
8454 {
8455 add(current);
8456 goto scan_number_exponent;
8457 }
8458
8459 default:
8460 goto scan_number_done;
8461 }
8462
8463scan_number_exponent:
8464 // we just parsed an exponent
8465 number_type = token_type::value_float;
8466 switch (get())
8467 {
8468 case '+':
8469 case '-':
8470 {
8471 add(current);
8472 goto scan_number_sign;
8473 }
8474
8475 case '0':
8476 case '1':
8477 case '2':
8478 case '3':
8479 case '4':
8480 case '5':
8481 case '6':
8482 case '7':
8483 case '8':
8484 case '9':
8485 {
8486 add(current);
8487 goto scan_number_any2;
8488 }
8489
8490 default:
8491 {
8492 error_message =
8493 "invalid number; expected '+', '-', or digit after exponent";
8494 return token_type::parse_error;
8495 }
8496 }
8497
8498scan_number_sign:
8499 // we just parsed an exponent sign
8500 switch (get())
8501 {
8502 case '0':
8503 case '1':
8504 case '2':
8505 case '3':
8506 case '4':
8507 case '5':
8508 case '6':
8509 case '7':
8510 case '8':
8511 case '9':
8512 {
8513 add(current);
8514 goto scan_number_any2;
8515 }
8516
8517 default:
8518 {
8519 error_message = "invalid number; expected digit after exponent sign";
8520 return token_type::parse_error;
8521 }
8522 }
8523
8524scan_number_any2:
8525 // we just parsed a number after the exponent or exponent sign
8526 switch (get())
8527 {
8528 case '0':
8529 case '1':
8530 case '2':
8531 case '3':
8532 case '4':
8533 case '5':
8534 case '6':
8535 case '7':
8536 case '8':
8537 case '9':
8538 {
8539 add(current);
8540 goto scan_number_any2;
8541 }
8542
8543 default:
8544 goto scan_number_done;
8545 }
8546
8547scan_number_done:
8548 // unget the character after the number (we only read it to know that
8549 // we are done scanning a number)
8550 unget();
8551
8552 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8553 errno = 0;
8554
8555 // try to parse integers first and fall back to floats
8556 if (number_type == token_type::value_unsigned)
8557 {
8558 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8559
8560 // we checked the number format before
8561 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8562
8563 if (errno == 0)
8564 {
8565 value_unsigned = static_cast<number_unsigned_t>(x);
8566 if (value_unsigned == x)
8567 {
8568 return token_type::value_unsigned;
8569 }
8570 }
8571 }
8572 else if (number_type == token_type::value_integer)
8573 {
8574 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8575
8576 // we checked the number format before
8577 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8578
8579 if (errno == 0)
8580 {
8581 value_integer = static_cast<number_integer_t>(x);
8582 if (value_integer == x)
8583 {
8584 return token_type::value_integer;
8585 }
8586 }
8587 }
8588
8589 // this code is reached if we parse a floating-point number or if an
8590 // integer conversion above failed
8591 strtof(value_float, token_buffer.data(), &endptr);
8592
8593 // we checked the number format before
8594 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8595
8596 return token_type::value_float;
8597 }
8598
8605 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8606 token_type return_type)
8607 {
8608 JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
8609 for (std::size_t i = 1; i < length; ++i)
8610 {
8611 if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8612 {
8613 error_message = "invalid literal";
8614 return token_type::parse_error;
8615 }
8616 }
8617 return return_type;
8618 }
8619
8621 // input management
8623
8625 void reset() noexcept
8626 {
8627 token_buffer.clear();
8628 token_string.clear();
8629 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
8630 }
8631
8632 /*
8633 @brief get next character from the input
8634
8635 This function provides the interface to the used input adapter. It does
8636 not throw in case the input reached EOF, but returns a
8637 `std::char_traits<char>::eof()` in that case. Stores the scanned characters
8638 for use in error messages.
8639
8640 @return character read from the input
8641 */
8642 char_int_type get()
8643 {
8644 ++position.chars_read_total;
8645 ++position.chars_read_current_line;
8646
8647 if (next_unget)
8648 {
8649 // just reset the next_unget variable and work with current
8650 next_unget = false;
8651 }
8652 else
8653 {
8654 current = ia.get_character();
8655 }
8656
8657 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
8658 {
8659 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
8660 }
8661
8662 if (current == '\n')
8663 {
8664 ++position.lines_read;
8665 position.chars_read_current_line = 0;
8666 }
8667
8668 return current;
8669 }
8670
8679 void unget()
8680 {
8681 next_unget = true;
8682
8683 --position.chars_read_total;
8684
8685 // in case we "unget" a newline, we have to also decrement the lines_read
8686 if (position.chars_read_current_line == 0)
8687 {
8688 if (position.lines_read > 0)
8689 {
8690 --position.lines_read;
8691 }
8692 }
8693 else
8694 {
8695 --position.chars_read_current_line;
8696 }
8697
8698 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
8699 {
8700 JSON_ASSERT(!token_string.empty());
8701 token_string.pop_back();
8702 }
8703 }
8704
8706 void add(char_int_type c)
8707 {
8708 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8709 }
8710
8711 public:
8713 // value getters
8715
8717 constexpr number_integer_t get_number_integer() const noexcept
8718 {
8719 return value_integer;
8720 }
8721
8723 constexpr number_unsigned_t get_number_unsigned() const noexcept
8724 {
8725 return value_unsigned;
8726 }
8727
8729 constexpr number_float_t get_number_float() const noexcept
8730 {
8731 return value_float;
8732 }
8733
8735 string_t& get_string()
8736 {
8737 return token_buffer;
8738 }
8739
8741 // diagnostics
8743
8745 constexpr position_t get_position() const noexcept
8746 {
8747 return position;
8748 }
8749
8753 std::string get_token_string() const
8754 {
8755 // escape control characters
8756 std::string result;
8757 for (const auto c : token_string)
8758 {
8759 if (static_cast<unsigned char>(c) <= '\x1F')
8760 {
8761 // escape control characters
8762 std::array<char, 9> cs{{}};
8763 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8764 result += cs.data();
8765 }
8766 else
8767 {
8768 // add character as is
8769 result.push_back(static_cast<std::string::value_type>(c));
8770 }
8771 }
8772
8773 return result;
8774 }
8775
8778 constexpr const char* get_error_message() const noexcept
8779 {
8780 return error_message;
8781 }
8782
8784 // actual scanner
8786
8792 {
8793 if (get() == 0xEF)
8794 {
8795 // check if we completely parse the BOM
8796 return get() == 0xBB && get() == 0xBF;
8797 }
8798
8799 // the first character is not the beginning of the BOM; unget it to
8800 // process is later
8801 unget();
8802 return true;
8803 }
8804
8806 {
8807 do
8808 {
8809 get();
8810 }
8811 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8812 }
8813
8815 {
8816 // initially, skip the BOM
8817 if (position.chars_read_total == 0 && !skip_bom())
8818 {
8819 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8820 return token_type::parse_error;
8821 }
8822
8823 // read next character and ignore whitespace
8824 skip_whitespace();
8825
8826 // ignore comments
8827 while (ignore_comments && current == '/')
8828 {
8829 if (!scan_comment())
8830 {
8831 return token_type::parse_error;
8832 }
8833
8834 // skip following whitespace
8835 skip_whitespace();
8836 }
8837
8838 switch (current)
8839 {
8840 // structural characters
8841 case '[':
8842 return token_type::begin_array;
8843 case ']':
8844 return token_type::end_array;
8845 case '{':
8846 return token_type::begin_object;
8847 case '}':
8848 return token_type::end_object;
8849 case ':':
8850 return token_type::name_separator;
8851 case ',':
8852 return token_type::value_separator;
8853
8854 // literals
8855 case 't':
8856 {
8857 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')}};
8858 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8859 }
8860 case 'f':
8861 {
8862 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')}};
8863 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8864 }
8865 case 'n':
8866 {
8867 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')}};
8868 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8869 }
8870
8871 // string
8872 case '\"':
8873 return scan_string();
8874
8875 // number
8876 case '-':
8877 case '0':
8878 case '1':
8879 case '2':
8880 case '3':
8881 case '4':
8882 case '5':
8883 case '6':
8884 case '7':
8885 case '8':
8886 case '9':
8887 return scan_number();
8888
8889 // end of input (the null byte is needed when parsing from
8890 // string literals)
8891 case '\0':
8892 case std::char_traits<char_type>::eof():
8893 return token_type::end_of_input;
8894
8895 // error
8896 default:
8897 error_message = "invalid literal";
8898 return token_type::parse_error;
8899 }
8900 }
8901
8902 private:
8904 InputAdapterType ia;
8905
8907 const bool ignore_comments = false;
8908
8910 char_int_type current = std::char_traits<char_type>::eof();
8911
8913 bool next_unget = false;
8914
8916 position_t position {};
8917
8919 std::vector<char_type> token_string {};
8920
8922 string_t token_buffer {};
8923
8925 const char* error_message = "";
8926
8927 // number values
8928 number_integer_t value_integer = 0;
8929 number_unsigned_t value_unsigned = 0;
8930 number_float_t value_float = 0;
8931
8933 const char_int_type decimal_point_char = '.';
8934};
8935
8936} // namespace detail
8938
8939// #include <nlohmann/detail/macro_scope.hpp>
8940
8941// #include <nlohmann/detail/meta/is_sax.hpp>
8942// __ _____ _____ _____
8943// __| | __| | | | JSON for Modern C++
8944// | | |__ | | | | | | version 3.11.2
8945// |_____|_____|_____|_|___| https://github.com/nlohmann/json
8946//
8947// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
8948// SPDX-License-Identifier: MIT
8949
8950
8951
8952#include <cstdint> // size_t
8953#include <utility> // declval
8954#include <string> // string
8955
8956// #include <nlohmann/detail/abi_macros.hpp>
8957
8958// #include <nlohmann/detail/meta/detected.hpp>
8959
8960// #include <nlohmann/detail/meta/type_traits.hpp>
8961
8962
8964namespace detail
8965{
8966
8967template<typename T>
8968using null_function_t = decltype(std::declval<T&>().null());
8969
8970template<typename T>
8971using boolean_function_t =
8972 decltype(std::declval<T&>().boolean(std::declval<bool>()));
8973
8974template<typename T, typename Integer>
8975using number_integer_function_t =
8976 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
8977
8978template<typename T, typename Unsigned>
8979using number_unsigned_function_t =
8980 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
8981
8982template<typename T, typename Float, typename String>
8983using number_float_function_t = decltype(std::declval<T&>().number_float(
8984 std::declval<Float>(), std::declval<const String&>()));
8985
8986template<typename T, typename String>
8987using string_function_t =
8988 decltype(std::declval<T&>().string(std::declval<String&>()));
8989
8990template<typename T, typename Binary>
8991using binary_function_t =
8992 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
8993
8994template<typename T>
8995using start_object_function_t =
8996 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
8997
8998template<typename T, typename String>
8999using key_function_t =
9000 decltype(std::declval<T&>().key(std::declval<String&>()));
9001
9002template<typename T>
9003using end_object_function_t = decltype(std::declval<T&>().end_object());
9004
9005template<typename T>
9006using start_array_function_t =
9007 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9008
9009template<typename T>
9010using end_array_function_t = decltype(std::declval<T&>().end_array());
9011
9012template<typename T, typename Exception>
9013using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9014 std::declval<std::size_t>(), std::declval<const std::string&>(),
9015 std::declval<const Exception&>()));
9016
9017template<typename SAX, typename BasicJsonType>
9018struct is_sax
9019{
9020 private:
9021 static_assert(is_basic_json<BasicJsonType>::value,
9022 "BasicJsonType must be of type basic_json<...>");
9023
9024 using number_integer_t = typename BasicJsonType::number_integer_t;
9025 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9026 using number_float_t = typename BasicJsonType::number_float_t;
9027 using string_t = typename BasicJsonType::string_t;
9028 using binary_t = typename BasicJsonType::binary_t;
9029 using exception_t = typename BasicJsonType::exception;
9030
9031 public:
9032 static constexpr bool value =
9033 is_detected_exact<bool, null_function_t, SAX>::value &&
9034 is_detected_exact<bool, boolean_function_t, SAX>::value &&
9035 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
9036 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
9037 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
9038 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
9039 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
9040 is_detected_exact<bool, start_object_function_t, SAX>::value &&
9041 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
9042 is_detected_exact<bool, end_object_function_t, SAX>::value &&
9043 is_detected_exact<bool, start_array_function_t, SAX>::value &&
9044 is_detected_exact<bool, end_array_function_t, SAX>::value &&
9045 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
9046};
9047
9048template<typename SAX, typename BasicJsonType>
9049struct is_sax_static_asserts
9050{
9051 private:
9052 static_assert(is_basic_json<BasicJsonType>::value,
9053 "BasicJsonType must be of type basic_json<...>");
9054
9055 using number_integer_t = typename BasicJsonType::number_integer_t;
9056 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9057 using number_float_t = typename BasicJsonType::number_float_t;
9058 using string_t = typename BasicJsonType::string_t;
9059 using binary_t = typename BasicJsonType::binary_t;
9060 using exception_t = typename BasicJsonType::exception;
9061
9062 public:
9063 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
9064 "Missing/invalid function: bool null()");
9065 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9066 "Missing/invalid function: bool boolean(bool)");
9067 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9068 "Missing/invalid function: bool boolean(bool)");
9069 static_assert(
9070 is_detected_exact<bool, number_integer_function_t, SAX,
9071 number_integer_t>::value,
9072 "Missing/invalid function: bool number_integer(number_integer_t)");
9073 static_assert(
9074 is_detected_exact<bool, number_unsigned_function_t, SAX,
9075 number_unsigned_t>::value,
9076 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9077 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9078 number_float_t, string_t>::value,
9079 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9080 static_assert(
9081 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
9082 "Missing/invalid function: bool string(string_t&)");
9083 static_assert(
9084 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
9085 "Missing/invalid function: bool binary(binary_t&)");
9086 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
9087 "Missing/invalid function: bool start_object(std::size_t)");
9088 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
9089 "Missing/invalid function: bool key(string_t&)");
9090 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
9091 "Missing/invalid function: bool end_object()");
9092 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
9093 "Missing/invalid function: bool start_array(std::size_t)");
9094 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
9095 "Missing/invalid function: bool end_array()");
9096 static_assert(
9097 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
9098 "Missing/invalid function: bool parse_error(std::size_t, const "
9099 "std::string&, const exception&)");
9100};
9101
9102} // namespace detail
9104
9105// #include <nlohmann/detail/meta/type_traits.hpp>
9106
9107// #include <nlohmann/detail/string_concat.hpp>
9108
9109// #include <nlohmann/detail/value_t.hpp>
9110
9111
9113namespace detail
9114{
9115
9118{
9119 error,
9120 ignore,
9121 store
9122};
9123
9131static inline bool little_endianness(int num = 1) noexcept
9132{
9133 return *reinterpret_cast<char*>(&num) == 1;
9134}
9135
9136
9138// binary reader //
9140
9144template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
9146{
9147 using number_integer_t = typename BasicJsonType::number_integer_t;
9148 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9149 using number_float_t = typename BasicJsonType::number_float_t;
9150 using string_t = typename BasicJsonType::string_t;
9151 using binary_t = typename BasicJsonType::binary_t;
9152 using json_sax_t = SAX;
9153 using char_type = typename InputAdapterType::char_type;
9154 using char_int_type = typename std::char_traits<char_type>::int_type;
9155
9156 public:
9162 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9163 {
9164 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
9165 }
9166
9167 // make class move-only
9169 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9171 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9172 ~binary_reader() = default;
9173
9183 bool sax_parse(const input_format_t format,
9184 json_sax_t* sax_,
9185 const bool strict = true,
9186 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9187 {
9188 sax = sax_;
9189 bool result = false;
9190
9191 switch (format)
9192 {
9193 case input_format_t::bson:
9194 result = parse_bson_internal();
9195 break;
9196
9197 case input_format_t::cbor:
9198 result = parse_cbor_internal(true, tag_handler);
9199 break;
9200
9201 case input_format_t::msgpack:
9202 result = parse_msgpack_internal();
9203 break;
9204
9205 case input_format_t::ubjson:
9206 case input_format_t::bjdata:
9207 result = parse_ubjson_internal();
9208 break;
9209
9210 case input_format_t::json: // LCOV_EXCL_LINE
9211 default: // LCOV_EXCL_LINE
9212 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9213 }
9214
9215 // strict mode: next byte must be EOF
9216 if (result && strict)
9217 {
9218 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9219 {
9220 get_ignore_noop();
9221 }
9222 else
9223 {
9224 get();
9225 }
9226
9227 if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
9228 {
9229 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9230 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9231 }
9232 }
9233
9234 return result;
9235 }
9236
9237 private:
9239 // BSON //
9241
9246 bool parse_bson_internal()
9247 {
9248 std::int32_t document_size{};
9249 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9250
9251 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
9252 {
9253 return false;
9254 }
9255
9256 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9257 {
9258 return false;
9259 }
9260
9261 return sax->end_object();
9262 }
9263
9271 bool get_bson_cstr(string_t& result)
9272 {
9273 auto out = std::back_inserter(result);
9274 while (true)
9275 {
9276 get();
9277 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
9278 {
9279 return false;
9280 }
9281 if (current == 0x00)
9282 {
9283 return true;
9284 }
9285 *out++ = static_cast<typename string_t::value_type>(current);
9286 }
9287 }
9288
9300 template<typename NumberType>
9301 bool get_bson_string(const NumberType len, string_t& result)
9302 {
9303 if (JSON_HEDLEY_UNLIKELY(len < 1))
9304 {
9305 auto last_token = get_token_string();
9306 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9307 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
9308 }
9309
9310 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
9311 }
9312
9322 template<typename NumberType>
9323 bool get_bson_binary(const NumberType len, binary_t& result)
9324 {
9325 if (JSON_HEDLEY_UNLIKELY(len < 0))
9326 {
9327 auto last_token = get_token_string();
9328 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9329 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
9330 }
9331
9332 // All BSON binary values have a subtype
9333 std::uint8_t subtype{};
9334 get_number<std::uint8_t>(input_format_t::bson, subtype);
9335 result.set_subtype(subtype);
9336
9337 return get_binary(input_format_t::bson, len, result);
9338 }
9339
9350 bool parse_bson_element_internal(const char_int_type element_type,
9351 const std::size_t element_type_parse_position)
9352 {
9353 switch (element_type)
9354 {
9355 case 0x01: // double
9356 {
9357 double number{};
9358 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9359 }
9360
9361 case 0x02: // string
9362 {
9363 std::int32_t len{};
9364 string_t value;
9365 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
9366 }
9367
9368 case 0x03: // object
9369 {
9370 return parse_bson_internal();
9371 }
9372
9373 case 0x04: // array
9374 {
9375 return parse_bson_array();
9376 }
9377
9378 case 0x05: // binary
9379 {
9380 std::int32_t len{};
9381 binary_t value;
9382 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9383 }
9384
9385 case 0x08: // boolean
9386 {
9387 return sax->boolean(get() != 0);
9388 }
9389
9390 case 0x0A: // null
9391 {
9392 return sax->null();
9393 }
9394
9395 case 0x10: // int32
9396 {
9397 std::int32_t value{};
9398 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9399 }
9400
9401 case 0x12: // int64
9402 {
9403 std::int64_t value{};
9404 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9405 }
9406
9407 default: // anything else not supported (yet)
9408 {
9409 std::array<char, 3> cr{{}};
9410 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9411 const std::string cr_str{cr.data()};
9412 return sax->parse_error(element_type_parse_position, cr_str,
9413 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
9414 }
9415 }
9416 }
9417
9430 bool parse_bson_element_list(const bool is_array)
9431 {
9432 string_t key;
9433
9434 while (auto element_type = get())
9435 {
9436 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
9437 {
9438 return false;
9439 }
9440
9441 const std::size_t element_type_parse_position = chars_read;
9442 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
9443 {
9444 return false;
9445 }
9446
9447 if (!is_array && !sax->key(key))
9448 {
9449 return false;
9450 }
9451
9452 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
9453 {
9454 return false;
9455 }
9456
9457 // get_bson_cstr only appends
9458 key.clear();
9459 }
9460
9461 return true;
9462 }
9463
9468 bool parse_bson_array()
9469 {
9470 std::int32_t document_size{};
9471 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9472
9473 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
9474 {
9475 return false;
9476 }
9477
9478 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
9479 {
9480 return false;
9481 }
9482
9483 return sax->end_array();
9484 }
9485
9487 // CBOR //
9489
9498 bool parse_cbor_internal(const bool get_char,
9499 const cbor_tag_handler_t tag_handler)
9500 {
9501 switch (get_char ? get() : current)
9502 {
9503 // EOF
9504 case std::char_traits<char_type>::eof():
9505 return unexpect_eof(input_format_t::cbor, "value");
9506
9507 // Integer 0x00..0x17 (0..23)
9508 case 0x00:
9509 case 0x01:
9510 case 0x02:
9511 case 0x03:
9512 case 0x04:
9513 case 0x05:
9514 case 0x06:
9515 case 0x07:
9516 case 0x08:
9517 case 0x09:
9518 case 0x0A:
9519 case 0x0B:
9520 case 0x0C:
9521 case 0x0D:
9522 case 0x0E:
9523 case 0x0F:
9524 case 0x10:
9525 case 0x11:
9526 case 0x12:
9527 case 0x13:
9528 case 0x14:
9529 case 0x15:
9530 case 0x16:
9531 case 0x17:
9532 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9533
9534 case 0x18: // Unsigned integer (one-byte uint8_t follows)
9535 {
9536 std::uint8_t number{};
9537 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9538 }
9539
9540 case 0x19: // Unsigned integer (two-byte uint16_t follows)
9541 {
9542 std::uint16_t number{};
9543 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9544 }
9545
9546 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9547 {
9548 std::uint32_t number{};
9549 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9550 }
9551
9552 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9553 {
9554 std::uint64_t number{};
9555 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9556 }
9557
9558 // Negative integer -1-0x00..-1-0x17 (-1..-24)
9559 case 0x20:
9560 case 0x21:
9561 case 0x22:
9562 case 0x23:
9563 case 0x24:
9564 case 0x25:
9565 case 0x26:
9566 case 0x27:
9567 case 0x28:
9568 case 0x29:
9569 case 0x2A:
9570 case 0x2B:
9571 case 0x2C:
9572 case 0x2D:
9573 case 0x2E:
9574 case 0x2F:
9575 case 0x30:
9576 case 0x31:
9577 case 0x32:
9578 case 0x33:
9579 case 0x34:
9580 case 0x35:
9581 case 0x36:
9582 case 0x37:
9583 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9584
9585 case 0x38: // Negative integer (one-byte uint8_t follows)
9586 {
9587 std::uint8_t number{};
9588 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9589 }
9590
9591 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9592 {
9593 std::uint16_t number{};
9594 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9595 }
9596
9597 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9598 {
9599 std::uint32_t number{};
9600 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9601 }
9602
9603 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9604 {
9605 std::uint64_t number{};
9606 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
9607 - static_cast<number_integer_t>(number));
9608 }
9609
9610 // Binary data (0x00..0x17 bytes follow)
9611 case 0x40:
9612 case 0x41:
9613 case 0x42:
9614 case 0x43:
9615 case 0x44:
9616 case 0x45:
9617 case 0x46:
9618 case 0x47:
9619 case 0x48:
9620 case 0x49:
9621 case 0x4A:
9622 case 0x4B:
9623 case 0x4C:
9624 case 0x4D:
9625 case 0x4E:
9626 case 0x4F:
9627 case 0x50:
9628 case 0x51:
9629 case 0x52:
9630 case 0x53:
9631 case 0x54:
9632 case 0x55:
9633 case 0x56:
9634 case 0x57:
9635 case 0x58: // Binary data (one-byte uint8_t for n follows)
9636 case 0x59: // Binary data (two-byte uint16_t for n follow)
9637 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9638 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9639 case 0x5F: // Binary data (indefinite length)
9640 {
9641 binary_t b;
9642 return get_cbor_binary(b) && sax->binary(b);
9643 }
9644
9645 // UTF-8 string (0x00..0x17 bytes follow)
9646 case 0x60:
9647 case 0x61:
9648 case 0x62:
9649 case 0x63:
9650 case 0x64:
9651 case 0x65:
9652 case 0x66:
9653 case 0x67:
9654 case 0x68:
9655 case 0x69:
9656 case 0x6A:
9657 case 0x6B:
9658 case 0x6C:
9659 case 0x6D:
9660 case 0x6E:
9661 case 0x6F:
9662 case 0x70:
9663 case 0x71:
9664 case 0x72:
9665 case 0x73:
9666 case 0x74:
9667 case 0x75:
9668 case 0x76:
9669 case 0x77:
9670 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9671 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9672 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9673 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9674 case 0x7F: // UTF-8 string (indefinite length)
9675 {
9676 string_t s;
9677 return get_cbor_string(s) && sax->string(s);
9678 }
9679
9680 // array (0x00..0x17 data items follow)
9681 case 0x80:
9682 case 0x81:
9683 case 0x82:
9684 case 0x83:
9685 case 0x84:
9686 case 0x85:
9687 case 0x86:
9688 case 0x87:
9689 case 0x88:
9690 case 0x89:
9691 case 0x8A:
9692 case 0x8B:
9693 case 0x8C:
9694 case 0x8D:
9695 case 0x8E:
9696 case 0x8F:
9697 case 0x90:
9698 case 0x91:
9699 case 0x92:
9700 case 0x93:
9701 case 0x94:
9702 case 0x95:
9703 case 0x96:
9704 case 0x97:
9705 return get_cbor_array(
9706 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9707
9708 case 0x98: // array (one-byte uint8_t for n follows)
9709 {
9710 std::uint8_t len{};
9711 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9712 }
9713
9714 case 0x99: // array (two-byte uint16_t for n follow)
9715 {
9716 std::uint16_t len{};
9717 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9718 }
9719
9720 case 0x9A: // array (four-byte uint32_t for n follow)
9721 {
9722 std::uint32_t len{};
9723 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9724 }
9725
9726 case 0x9B: // array (eight-byte uint64_t for n follow)
9727 {
9728 std::uint64_t len{};
9729 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9730 }
9731
9732 case 0x9F: // array (indefinite length)
9733 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
9734
9735 // map (0x00..0x17 pairs of data items follow)
9736 case 0xA0:
9737 case 0xA1:
9738 case 0xA2:
9739 case 0xA3:
9740 case 0xA4:
9741 case 0xA5:
9742 case 0xA6:
9743 case 0xA7:
9744 case 0xA8:
9745 case 0xA9:
9746 case 0xAA:
9747 case 0xAB:
9748 case 0xAC:
9749 case 0xAD:
9750 case 0xAE:
9751 case 0xAF:
9752 case 0xB0:
9753 case 0xB1:
9754 case 0xB2:
9755 case 0xB3:
9756 case 0xB4:
9757 case 0xB5:
9758 case 0xB6:
9759 case 0xB7:
9760 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9761
9762 case 0xB8: // map (one-byte uint8_t for n follows)
9763 {
9764 std::uint8_t len{};
9765 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9766 }
9767
9768 case 0xB9: // map (two-byte uint16_t for n follow)
9769 {
9770 std::uint16_t len{};
9771 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9772 }
9773
9774 case 0xBA: // map (four-byte uint32_t for n follow)
9775 {
9776 std::uint32_t len{};
9777 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9778 }
9779
9780 case 0xBB: // map (eight-byte uint64_t for n follow)
9781 {
9782 std::uint64_t len{};
9783 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9784 }
9785
9786 case 0xBF: // map (indefinite length)
9787 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
9788
9789 case 0xC6: // tagged item
9790 case 0xC7:
9791 case 0xC8:
9792 case 0xC9:
9793 case 0xCA:
9794 case 0xCB:
9795 case 0xCC:
9796 case 0xCD:
9797 case 0xCE:
9798 case 0xCF:
9799 case 0xD0:
9800 case 0xD1:
9801 case 0xD2:
9802 case 0xD3:
9803 case 0xD4:
9804 case 0xD8: // tagged item (1 bytes follow)
9805 case 0xD9: // tagged item (2 bytes follow)
9806 case 0xDA: // tagged item (4 bytes follow)
9807 case 0xDB: // tagged item (8 bytes follow)
9808 {
9809 switch (tag_handler)
9810 {
9812 {
9813 auto last_token = get_token_string();
9814 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9815 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9816 }
9817
9819 {
9820 // ignore binary subtype
9821 switch (current)
9822 {
9823 case 0xD8:
9824 {
9825 std::uint8_t subtype_to_ignore{};
9826 get_number(input_format_t::cbor, subtype_to_ignore);
9827 break;
9828 }
9829 case 0xD9:
9830 {
9831 std::uint16_t subtype_to_ignore{};
9832 get_number(input_format_t::cbor, subtype_to_ignore);
9833 break;
9834 }
9835 case 0xDA:
9836 {
9837 std::uint32_t subtype_to_ignore{};
9838 get_number(input_format_t::cbor, subtype_to_ignore);
9839 break;
9840 }
9841 case 0xDB:
9842 {
9843 std::uint64_t subtype_to_ignore{};
9844 get_number(input_format_t::cbor, subtype_to_ignore);
9845 break;
9846 }
9847 default:
9848 break;
9849 }
9850 return parse_cbor_internal(true, tag_handler);
9851 }
9852
9854 {
9855 binary_t b;
9856 // use binary subtype and store in binary container
9857 switch (current)
9858 {
9859 case 0xD8:
9860 {
9861 std::uint8_t subtype{};
9862 get_number(input_format_t::cbor, subtype);
9863 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9864 break;
9865 }
9866 case 0xD9:
9867 {
9868 std::uint16_t subtype{};
9869 get_number(input_format_t::cbor, subtype);
9870 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9871 break;
9872 }
9873 case 0xDA:
9874 {
9875 std::uint32_t subtype{};
9876 get_number(input_format_t::cbor, subtype);
9877 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9878 break;
9879 }
9880 case 0xDB:
9881 {
9882 std::uint64_t subtype{};
9883 get_number(input_format_t::cbor, subtype);
9884 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9885 break;
9886 }
9887 default:
9888 return parse_cbor_internal(true, tag_handler);
9889 }
9890 get();
9891 return get_cbor_binary(b) && sax->binary(b);
9892 }
9893
9894 default: // LCOV_EXCL_LINE
9895 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9896 return false; // LCOV_EXCL_LINE
9897 }
9898 }
9899
9900 case 0xF4: // false
9901 return sax->boolean(false);
9902
9903 case 0xF5: // true
9904 return sax->boolean(true);
9905
9906 case 0xF6: // null
9907 return sax->null();
9908
9909 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
9910 {
9911 const auto byte1_raw = get();
9912 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9913 {
9914 return false;
9915 }
9916 const auto byte2_raw = get();
9917 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9918 {
9919 return false;
9920 }
9921
9922 const auto byte1 = static_cast<unsigned char>(byte1_raw);
9923 const auto byte2 = static_cast<unsigned char>(byte2_raw);
9924
9925 // code from RFC 7049, Appendix D, Figure 3:
9926 // As half-precision floating-point numbers were only added
9927 // to IEEE 754 in 2008, today's programming platforms often
9928 // still only have limited support for them. It is very
9929 // easy to include at least decoding support for them even
9930 // without such support. An example of a small decoder for
9931 // half-precision floating-point numbers in the C language
9932 // is shown in Fig. 3.
9933 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
9934 const double val = [&half]
9935 {
9936 const int exp = (half >> 10u) & 0x1Fu;
9937 const unsigned int mant = half & 0x3FFu;
9938 JSON_ASSERT(0 <= exp&& exp <= 32);
9939 JSON_ASSERT(mant <= 1024);
9940 switch (exp)
9941 {
9942 case 0:
9943 return std::ldexp(mant, -24);
9944 case 31:
9945 return (mant == 0)
9946 ? std::numeric_limits<double>::infinity()
9947 : std::numeric_limits<double>::quiet_NaN();
9948 default:
9949 return std::ldexp(mant + 1024, exp - 25);
9950 }
9951 }();
9952 return sax->number_float((half & 0x8000u) != 0
9953 ? static_cast<number_float_t>(-val)
9954 : static_cast<number_float_t>(val), "");
9955 }
9956
9957 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
9958 {
9959 float number{};
9960 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9961 }
9962
9963 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
9964 {
9965 double number{};
9966 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9967 }
9968
9969 default: // anything else (0xFF is handled inside the other types)
9970 {
9971 auto last_token = get_token_string();
9972 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9973 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9974 }
9975 }
9976 }
9977
9989 bool get_cbor_string(string_t& result)
9990 {
9991 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
9992 {
9993 return false;
9994 }
9995
9996 switch (current)
9997 {
9998 // UTF-8 string (0x00..0x17 bytes follow)
9999 case 0x60:
10000 case 0x61:
10001 case 0x62:
10002 case 0x63:
10003 case 0x64:
10004 case 0x65:
10005 case 0x66:
10006 case 0x67:
10007 case 0x68:
10008 case 0x69:
10009 case 0x6A:
10010 case 0x6B:
10011 case 0x6C:
10012 case 0x6D:
10013 case 0x6E:
10014 case 0x6F:
10015 case 0x70:
10016 case 0x71:
10017 case 0x72:
10018 case 0x73:
10019 case 0x74:
10020 case 0x75:
10021 case 0x76:
10022 case 0x77:
10023 {
10024 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10025 }
10026
10027 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10028 {
10029 std::uint8_t len{};
10030 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10031 }
10032
10033 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10034 {
10035 std::uint16_t len{};
10036 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10037 }
10038
10039 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10040 {
10041 std::uint32_t len{};
10042 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10043 }
10044
10045 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10046 {
10047 std::uint64_t len{};
10048 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10049 }
10050
10051 case 0x7F: // UTF-8 string (indefinite length)
10052 {
10053 while (get() != 0xFF)
10054 {
10055 string_t chunk;
10056 if (!get_cbor_string(chunk))
10057 {
10058 return false;
10059 }
10060 result.append(chunk);
10061 }
10062 return true;
10063 }
10064
10065 default:
10066 {
10067 auto last_token = get_token_string();
10068 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10069 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10070 }
10071 }
10072 }
10073
10085 bool get_cbor_binary(binary_t& result)
10086 {
10087 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10088 {
10089 return false;
10090 }
10091
10092 switch (current)
10093 {
10094 // Binary data (0x00..0x17 bytes follow)
10095 case 0x40:
10096 case 0x41:
10097 case 0x42:
10098 case 0x43:
10099 case 0x44:
10100 case 0x45:
10101 case 0x46:
10102 case 0x47:
10103 case 0x48:
10104 case 0x49:
10105 case 0x4A:
10106 case 0x4B:
10107 case 0x4C:
10108 case 0x4D:
10109 case 0x4E:
10110 case 0x4F:
10111 case 0x50:
10112 case 0x51:
10113 case 0x52:
10114 case 0x53:
10115 case 0x54:
10116 case 0x55:
10117 case 0x56:
10118 case 0x57:
10119 {
10120 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10121 }
10122
10123 case 0x58: // Binary data (one-byte uint8_t for n follows)
10124 {
10125 std::uint8_t len{};
10126 return get_number(input_format_t::cbor, len) &&
10127 get_binary(input_format_t::cbor, len, result);
10128 }
10129
10130 case 0x59: // Binary data (two-byte uint16_t for n follow)
10131 {
10132 std::uint16_t len{};
10133 return get_number(input_format_t::cbor, len) &&
10134 get_binary(input_format_t::cbor, len, result);
10135 }
10136
10137 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10138 {
10139 std::uint32_t len{};
10140 return get_number(input_format_t::cbor, len) &&
10141 get_binary(input_format_t::cbor, len, result);
10142 }
10143
10144 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10145 {
10146 std::uint64_t len{};
10147 return get_number(input_format_t::cbor, len) &&
10148 get_binary(input_format_t::cbor, len, result);
10149 }
10150
10151 case 0x5F: // Binary data (indefinite length)
10152 {
10153 while (get() != 0xFF)
10154 {
10155 binary_t chunk;
10156 if (!get_cbor_binary(chunk))
10157 {
10158 return false;
10159 }
10160 result.insert(result.end(), chunk.begin(), chunk.end());
10161 }
10162 return true;
10163 }
10164
10165 default:
10166 {
10167 auto last_token = get_token_string();
10168 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10169 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));
10170 }
10171 }
10172 }
10173
10180 bool get_cbor_array(const std::size_t len,
10181 const cbor_tag_handler_t tag_handler)
10182 {
10183 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10184 {
10185 return false;
10186 }
10187
10188 if (len != static_cast<std::size_t>(-1))
10189 {
10190 for (std::size_t i = 0; i < len; ++i)
10191 {
10192 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10193 {
10194 return false;
10195 }
10196 }
10197 }
10198 else
10199 {
10200 while (get() != 0xFF)
10201 {
10202 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10203 {
10204 return false;
10205 }
10206 }
10207 }
10208
10209 return sax->end_array();
10210 }
10211
10218 bool get_cbor_object(const std::size_t len,
10219 const cbor_tag_handler_t tag_handler)
10220 {
10221 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10222 {
10223 return false;
10224 }
10225
10226 if (len != 0)
10227 {
10228 string_t key;
10229 if (len != static_cast<std::size_t>(-1))
10230 {
10231 for (std::size_t i = 0; i < len; ++i)
10232 {
10233 get();
10234 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10235 {
10236 return false;
10237 }
10238
10239 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10240 {
10241 return false;
10242 }
10243 key.clear();
10244 }
10245 }
10246 else
10247 {
10248 while (get() != 0xFF)
10249 {
10250 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10251 {
10252 return false;
10253 }
10254
10255 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10256 {
10257 return false;
10258 }
10259 key.clear();
10260 }
10261 }
10262 }
10263
10264 return sax->end_object();
10265 }
10266
10268 // MsgPack //
10270
10274 bool parse_msgpack_internal()
10275 {
10276 switch (get())
10277 {
10278 // EOF
10279 case std::char_traits<char_type>::eof():
10280 return unexpect_eof(input_format_t::msgpack, "value");
10281
10282 // positive fixint
10283 case 0x00:
10284 case 0x01:
10285 case 0x02:
10286 case 0x03:
10287 case 0x04:
10288 case 0x05:
10289 case 0x06:
10290 case 0x07:
10291 case 0x08:
10292 case 0x09:
10293 case 0x0A:
10294 case 0x0B:
10295 case 0x0C:
10296 case 0x0D:
10297 case 0x0E:
10298 case 0x0F:
10299 case 0x10:
10300 case 0x11:
10301 case 0x12:
10302 case 0x13:
10303 case 0x14:
10304 case 0x15:
10305 case 0x16:
10306 case 0x17:
10307 case 0x18:
10308 case 0x19:
10309 case 0x1A:
10310 case 0x1B:
10311 case 0x1C:
10312 case 0x1D:
10313 case 0x1E:
10314 case 0x1F:
10315 case 0x20:
10316 case 0x21:
10317 case 0x22:
10318 case 0x23:
10319 case 0x24:
10320 case 0x25:
10321 case 0x26:
10322 case 0x27:
10323 case 0x28:
10324 case 0x29:
10325 case 0x2A:
10326 case 0x2B:
10327 case 0x2C:
10328 case 0x2D:
10329 case 0x2E:
10330 case 0x2F:
10331 case 0x30:
10332 case 0x31:
10333 case 0x32:
10334 case 0x33:
10335 case 0x34:
10336 case 0x35:
10337 case 0x36:
10338 case 0x37:
10339 case 0x38:
10340 case 0x39:
10341 case 0x3A:
10342 case 0x3B:
10343 case 0x3C:
10344 case 0x3D:
10345 case 0x3E:
10346 case 0x3F:
10347 case 0x40:
10348 case 0x41:
10349 case 0x42:
10350 case 0x43:
10351 case 0x44:
10352 case 0x45:
10353 case 0x46:
10354 case 0x47:
10355 case 0x48:
10356 case 0x49:
10357 case 0x4A:
10358 case 0x4B:
10359 case 0x4C:
10360 case 0x4D:
10361 case 0x4E:
10362 case 0x4F:
10363 case 0x50:
10364 case 0x51:
10365 case 0x52:
10366 case 0x53:
10367 case 0x54:
10368 case 0x55:
10369 case 0x56:
10370 case 0x57:
10371 case 0x58:
10372 case 0x59:
10373 case 0x5A:
10374 case 0x5B:
10375 case 0x5C:
10376 case 0x5D:
10377 case 0x5E:
10378 case 0x5F:
10379 case 0x60:
10380 case 0x61:
10381 case 0x62:
10382 case 0x63:
10383 case 0x64:
10384 case 0x65:
10385 case 0x66:
10386 case 0x67:
10387 case 0x68:
10388 case 0x69:
10389 case 0x6A:
10390 case 0x6B:
10391 case 0x6C:
10392 case 0x6D:
10393 case 0x6E:
10394 case 0x6F:
10395 case 0x70:
10396 case 0x71:
10397 case 0x72:
10398 case 0x73:
10399 case 0x74:
10400 case 0x75:
10401 case 0x76:
10402 case 0x77:
10403 case 0x78:
10404 case 0x79:
10405 case 0x7A:
10406 case 0x7B:
10407 case 0x7C:
10408 case 0x7D:
10409 case 0x7E:
10410 case 0x7F:
10411 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10412
10413 // fixmap
10414 case 0x80:
10415 case 0x81:
10416 case 0x82:
10417 case 0x83:
10418 case 0x84:
10419 case 0x85:
10420 case 0x86:
10421 case 0x87:
10422 case 0x88:
10423 case 0x89:
10424 case 0x8A:
10425 case 0x8B:
10426 case 0x8C:
10427 case 0x8D:
10428 case 0x8E:
10429 case 0x8F:
10430 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10431
10432 // fixarray
10433 case 0x90:
10434 case 0x91:
10435 case 0x92:
10436 case 0x93:
10437 case 0x94:
10438 case 0x95:
10439 case 0x96:
10440 case 0x97:
10441 case 0x98:
10442 case 0x99:
10443 case 0x9A:
10444 case 0x9B:
10445 case 0x9C:
10446 case 0x9D:
10447 case 0x9E:
10448 case 0x9F:
10449 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10450
10451 // fixstr
10452 case 0xA0:
10453 case 0xA1:
10454 case 0xA2:
10455 case 0xA3:
10456 case 0xA4:
10457 case 0xA5:
10458 case 0xA6:
10459 case 0xA7:
10460 case 0xA8:
10461 case 0xA9:
10462 case 0xAA:
10463 case 0xAB:
10464 case 0xAC:
10465 case 0xAD:
10466 case 0xAE:
10467 case 0xAF:
10468 case 0xB0:
10469 case 0xB1:
10470 case 0xB2:
10471 case 0xB3:
10472 case 0xB4:
10473 case 0xB5:
10474 case 0xB6:
10475 case 0xB7:
10476 case 0xB8:
10477 case 0xB9:
10478 case 0xBA:
10479 case 0xBB:
10480 case 0xBC:
10481 case 0xBD:
10482 case 0xBE:
10483 case 0xBF:
10484 case 0xD9: // str 8
10485 case 0xDA: // str 16
10486 case 0xDB: // str 32
10487 {
10488 string_t s;
10489 return get_msgpack_string(s) && sax->string(s);
10490 }
10491
10492 case 0xC0: // nil
10493 return sax->null();
10494
10495 case 0xC2: // false
10496 return sax->boolean(false);
10497
10498 case 0xC3: // true
10499 return sax->boolean(true);
10500
10501 case 0xC4: // bin 8
10502 case 0xC5: // bin 16
10503 case 0xC6: // bin 32
10504 case 0xC7: // ext 8
10505 case 0xC8: // ext 16
10506 case 0xC9: // ext 32
10507 case 0xD4: // fixext 1
10508 case 0xD5: // fixext 2
10509 case 0xD6: // fixext 4
10510 case 0xD7: // fixext 8
10511 case 0xD8: // fixext 16
10512 {
10513 binary_t b;
10514 return get_msgpack_binary(b) && sax->binary(b);
10515 }
10516
10517 case 0xCA: // float 32
10518 {
10519 float number{};
10520 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10521 }
10522
10523 case 0xCB: // float 64
10524 {
10525 double number{};
10526 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10527 }
10528
10529 case 0xCC: // uint 8
10530 {
10531 std::uint8_t number{};
10532 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10533 }
10534
10535 case 0xCD: // uint 16
10536 {
10537 std::uint16_t number{};
10538 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10539 }
10540
10541 case 0xCE: // uint 32
10542 {
10543 std::uint32_t number{};
10544 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10545 }
10546
10547 case 0xCF: // uint 64
10548 {
10549 std::uint64_t number{};
10550 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10551 }
10552
10553 case 0xD0: // int 8
10554 {
10555 std::int8_t number{};
10556 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10557 }
10558
10559 case 0xD1: // int 16
10560 {
10561 std::int16_t number{};
10562 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10563 }
10564
10565 case 0xD2: // int 32
10566 {
10567 std::int32_t number{};
10568 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10569 }
10570
10571 case 0xD3: // int 64
10572 {
10573 std::int64_t number{};
10574 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10575 }
10576
10577 case 0xDC: // array 16
10578 {
10579 std::uint16_t len{};
10580 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
10581 }
10582
10583 case 0xDD: // array 32
10584 {
10585 std::uint32_t len{};
10586 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10587 }
10588
10589 case 0xDE: // map 16
10590 {
10591 std::uint16_t len{};
10592 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
10593 }
10594
10595 case 0xDF: // map 32
10596 {
10597 std::uint32_t len{};
10598 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10599 }
10600
10601 // negative fixint
10602 case 0xE0:
10603 case 0xE1:
10604 case 0xE2:
10605 case 0xE3:
10606 case 0xE4:
10607 case 0xE5:
10608 case 0xE6:
10609 case 0xE7:
10610 case 0xE8:
10611 case 0xE9:
10612 case 0xEA:
10613 case 0xEB:
10614 case 0xEC:
10615 case 0xED:
10616 case 0xEE:
10617 case 0xEF:
10618 case 0xF0:
10619 case 0xF1:
10620 case 0xF2:
10621 case 0xF3:
10622 case 0xF4:
10623 case 0xF5:
10624 case 0xF6:
10625 case 0xF7:
10626 case 0xF8:
10627 case 0xF9:
10628 case 0xFA:
10629 case 0xFB:
10630 case 0xFC:
10631 case 0xFD:
10632 case 0xFE:
10633 case 0xFF:
10634 return sax->number_integer(static_cast<std::int8_t>(current));
10635
10636 default: // anything else
10637 {
10638 auto last_token = get_token_string();
10639 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10640 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
10641 }
10642 }
10643 }
10644
10655 bool get_msgpack_string(string_t& result)
10656 {
10657 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
10658 {
10659 return false;
10660 }
10661
10662 switch (current)
10663 {
10664 // fixstr
10665 case 0xA0:
10666 case 0xA1:
10667 case 0xA2:
10668 case 0xA3:
10669 case 0xA4:
10670 case 0xA5:
10671 case 0xA6:
10672 case 0xA7:
10673 case 0xA8:
10674 case 0xA9:
10675 case 0xAA:
10676 case 0xAB:
10677 case 0xAC:
10678 case 0xAD:
10679 case 0xAE:
10680 case 0xAF:
10681 case 0xB0:
10682 case 0xB1:
10683 case 0xB2:
10684 case 0xB3:
10685 case 0xB4:
10686 case 0xB5:
10687 case 0xB6:
10688 case 0xB7:
10689 case 0xB8:
10690 case 0xB9:
10691 case 0xBA:
10692 case 0xBB:
10693 case 0xBC:
10694 case 0xBD:
10695 case 0xBE:
10696 case 0xBF:
10697 {
10698 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
10699 }
10700
10701 case 0xD9: // str 8
10702 {
10703 std::uint8_t len{};
10704 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10705 }
10706
10707 case 0xDA: // str 16
10708 {
10709 std::uint16_t len{};
10710 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10711 }
10712
10713 case 0xDB: // str 32
10714 {
10715 std::uint32_t len{};
10716 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10717 }
10718
10719 default:
10720 {
10721 auto last_token = get_token_string();
10722 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10723 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
10724 }
10725 }
10726 }
10727
10738 bool get_msgpack_binary(binary_t& result)
10739 {
10740 // helper function to set the subtype
10741 auto assign_and_return_true = [&result](std::int8_t subtype)
10742 {
10743 result.set_subtype(static_cast<std::uint8_t>(subtype));
10744 return true;
10745 };
10746
10747 switch (current)
10748 {
10749 case 0xC4: // bin 8
10750 {
10751 std::uint8_t len{};
10752 return get_number(input_format_t::msgpack, len) &&
10753 get_binary(input_format_t::msgpack, len, result);
10754 }
10755
10756 case 0xC5: // bin 16
10757 {
10758 std::uint16_t len{};
10759 return get_number(input_format_t::msgpack, len) &&
10760 get_binary(input_format_t::msgpack, len, result);
10761 }
10762
10763 case 0xC6: // bin 32
10764 {
10765 std::uint32_t len{};
10766 return get_number(input_format_t::msgpack, len) &&
10767 get_binary(input_format_t::msgpack, len, result);
10768 }
10769
10770 case 0xC7: // ext 8
10771 {
10772 std::uint8_t len{};
10773 std::int8_t subtype{};
10774 return get_number(input_format_t::msgpack, len) &&
10775 get_number(input_format_t::msgpack, subtype) &&
10776 get_binary(input_format_t::msgpack, len, result) &&
10777 assign_and_return_true(subtype);
10778 }
10779
10780 case 0xC8: // ext 16
10781 {
10782 std::uint16_t len{};
10783 std::int8_t subtype{};
10784 return get_number(input_format_t::msgpack, len) &&
10785 get_number(input_format_t::msgpack, subtype) &&
10786 get_binary(input_format_t::msgpack, len, result) &&
10787 assign_and_return_true(subtype);
10788 }
10789
10790 case 0xC9: // ext 32
10791 {
10792 std::uint32_t len{};
10793 std::int8_t subtype{};
10794 return get_number(input_format_t::msgpack, len) &&
10795 get_number(input_format_t::msgpack, subtype) &&
10796 get_binary(input_format_t::msgpack, len, result) &&
10797 assign_and_return_true(subtype);
10798 }
10799
10800 case 0xD4: // fixext 1
10801 {
10802 std::int8_t subtype{};
10803 return get_number(input_format_t::msgpack, subtype) &&
10804 get_binary(input_format_t::msgpack, 1, result) &&
10805 assign_and_return_true(subtype);
10806 }
10807
10808 case 0xD5: // fixext 2
10809 {
10810 std::int8_t subtype{};
10811 return get_number(input_format_t::msgpack, subtype) &&
10812 get_binary(input_format_t::msgpack, 2, result) &&
10813 assign_and_return_true(subtype);
10814 }
10815
10816 case 0xD6: // fixext 4
10817 {
10818 std::int8_t subtype{};
10819 return get_number(input_format_t::msgpack, subtype) &&
10820 get_binary(input_format_t::msgpack, 4, result) &&
10821 assign_and_return_true(subtype);
10822 }
10823
10824 case 0xD7: // fixext 8
10825 {
10826 std::int8_t subtype{};
10827 return get_number(input_format_t::msgpack, subtype) &&
10828 get_binary(input_format_t::msgpack, 8, result) &&
10829 assign_and_return_true(subtype);
10830 }
10831
10832 case 0xD8: // fixext 16
10833 {
10834 std::int8_t subtype{};
10835 return get_number(input_format_t::msgpack, subtype) &&
10836 get_binary(input_format_t::msgpack, 16, result) &&
10837 assign_and_return_true(subtype);
10838 }
10839
10840 default: // LCOV_EXCL_LINE
10841 return false; // LCOV_EXCL_LINE
10842 }
10843 }
10844
10849 bool get_msgpack_array(const std::size_t len)
10850 {
10851 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10852 {
10853 return false;
10854 }
10855
10856 for (std::size_t i = 0; i < len; ++i)
10857 {
10858 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10859 {
10860 return false;
10861 }
10862 }
10863
10864 return sax->end_array();
10865 }
10866
10871 bool get_msgpack_object(const std::size_t len)
10872 {
10873 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10874 {
10875 return false;
10876 }
10877
10878 string_t key;
10879 for (std::size_t i = 0; i < len; ++i)
10880 {
10881 get();
10882 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
10883 {
10884 return false;
10885 }
10886
10887 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10888 {
10889 return false;
10890 }
10891 key.clear();
10892 }
10893
10894 return sax->end_object();
10895 }
10896
10898 // UBJSON //
10900
10908 bool parse_ubjson_internal(const bool get_char = true)
10909 {
10910 return get_ubjson_value(get_char ? get_ignore_noop() : current);
10911 }
10912
10927 bool get_ubjson_string(string_t& result, const bool get_char = true)
10928 {
10929 if (get_char)
10930 {
10931 get(); // TODO(niels): may we ignore N here?
10932 }
10933
10934 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
10935 {
10936 return false;
10937 }
10938
10939 switch (current)
10940 {
10941 case 'U':
10942 {
10943 std::uint8_t len{};
10944 return get_number(input_format, len) && get_string(input_format, len, result);
10945 }
10946
10947 case 'i':
10948 {
10949 std::int8_t len{};
10950 return get_number(input_format, len) && get_string(input_format, len, result);
10951 }
10952
10953 case 'I':
10954 {
10955 std::int16_t len{};
10956 return get_number(input_format, len) && get_string(input_format, len, result);
10957 }
10958
10959 case 'l':
10960 {
10961 std::int32_t len{};
10962 return get_number(input_format, len) && get_string(input_format, len, result);
10963 }
10964
10965 case 'L':
10966 {
10967 std::int64_t len{};
10968 return get_number(input_format, len) && get_string(input_format, len, result);
10969 }
10970
10971 case 'u':
10972 {
10973 if (input_format != input_format_t::bjdata)
10974 {
10975 break;
10976 }
10977 std::uint16_t len{};
10978 return get_number(input_format, len) && get_string(input_format, len, result);
10979 }
10980
10981 case 'm':
10982 {
10983 if (input_format != input_format_t::bjdata)
10984 {
10985 break;
10986 }
10987 std::uint32_t len{};
10988 return get_number(input_format, len) && get_string(input_format, len, result);
10989 }
10990
10991 case 'M':
10992 {
10993 if (input_format != input_format_t::bjdata)
10994 {
10995 break;
10996 }
10997 std::uint64_t len{};
10998 return get_number(input_format, len) && get_string(input_format, len, result);
10999 }
11000
11001 default:
11002 break;
11003 }
11004 auto last_token = get_token_string();
11005 std::string message;
11006
11007 if (input_format != input_format_t::bjdata)
11008 {
11009 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11010 }
11011 else
11012 {
11013 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11014 }
11015 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11016 }
11017
11022 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11023 {
11024 std::pair<std::size_t, char_int_type> size_and_type;
11025 size_t dimlen = 0;
11026 bool no_ndarray = true;
11027
11028 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11029 {
11030 return false;
11031 }
11032
11033 if (size_and_type.first != npos)
11034 {
11035 if (size_and_type.second != 0)
11036 {
11037 if (size_and_type.second != 'N')
11038 {
11039 for (std::size_t i = 0; i < size_and_type.first; ++i)
11040 {
11041 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11042 {
11043 return false;
11044 }
11045 dim.push_back(dimlen);
11046 }
11047 }
11048 }
11049 else
11050 {
11051 for (std::size_t i = 0; i < size_and_type.first; ++i)
11052 {
11053 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11054 {
11055 return false;
11056 }
11057 dim.push_back(dimlen);
11058 }
11059 }
11060 }
11061 else
11062 {
11063 while (current != ']')
11064 {
11065 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11066 {
11067 return false;
11068 }
11069 dim.push_back(dimlen);
11070 get_ignore_noop();
11071 }
11072 }
11073 return true;
11074 }
11075
11087 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11088 {
11089 if (prefix == 0)
11090 {
11091 prefix = get_ignore_noop();
11092 }
11093
11094 switch (prefix)
11095 {
11096 case 'U':
11097 {
11098 std::uint8_t number{};
11099 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11100 {
11101 return false;
11102 }
11103 result = static_cast<std::size_t>(number);
11104 return true;
11105 }
11106
11107 case 'i':
11108 {
11109 std::int8_t number{};
11110 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11111 {
11112 return false;
11113 }
11114 if (number < 0)
11115 {
11116 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11117 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11118 }
11119 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11120 return true;
11121 }
11122
11123 case 'I':
11124 {
11125 std::int16_t number{};
11126 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11127 {
11128 return false;
11129 }
11130 if (number < 0)
11131 {
11132 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11133 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11134 }
11135 result = static_cast<std::size_t>(number);
11136 return true;
11137 }
11138
11139 case 'l':
11140 {
11141 std::int32_t number{};
11142 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11143 {
11144 return false;
11145 }
11146 if (number < 0)
11147 {
11148 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11149 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11150 }
11151 result = static_cast<std::size_t>(number);
11152 return true;
11153 }
11154
11155 case 'L':
11156 {
11157 std::int64_t number{};
11158 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11159 {
11160 return false;
11161 }
11162 if (number < 0)
11163 {
11164 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11165 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11166 }
11167 if (!value_in_range_of<std::size_t>(number))
11168 {
11169 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11170 exception_message(input_format, "integer value overflow", "size"), nullptr));
11171 }
11172 result = static_cast<std::size_t>(number);
11173 return true;
11174 }
11175
11176 case 'u':
11177 {
11178 if (input_format != input_format_t::bjdata)
11179 {
11180 break;
11181 }
11182 std::uint16_t number{};
11183 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11184 {
11185 return false;
11186 }
11187 result = static_cast<std::size_t>(number);
11188 return true;
11189 }
11190
11191 case 'm':
11192 {
11193 if (input_format != input_format_t::bjdata)
11194 {
11195 break;
11196 }
11197 std::uint32_t number{};
11198 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11199 {
11200 return false;
11201 }
11202 result = conditional_static_cast<std::size_t>(number);
11203 return true;
11204 }
11205
11206 case 'M':
11207 {
11208 if (input_format != input_format_t::bjdata)
11209 {
11210 break;
11211 }
11212 std::uint64_t number{};
11213 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11214 {
11215 return false;
11216 }
11217 if (!value_in_range_of<std::size_t>(number))
11218 {
11219 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11220 exception_message(input_format, "integer value overflow", "size"), nullptr));
11221 }
11222 result = detail::conditional_static_cast<std::size_t>(number);
11223 return true;
11224 }
11225
11226 case '[':
11227 {
11228 if (input_format != input_format_t::bjdata)
11229 {
11230 break;
11231 }
11232 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11233 {
11234 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));
11235 }
11236 std::vector<size_t> dim;
11237 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11238 {
11239 return false;
11240 }
11241 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11242 {
11243 result = dim.at(dim.size() - 1);
11244 return true;
11245 }
11246 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11247 {
11248 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11249 {
11250 if ( i == 0 )
11251 {
11252 result = 0;
11253 return true;
11254 }
11255 }
11256
11257 string_t key = "_ArraySize_";
11258 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11259 {
11260 return false;
11261 }
11262 result = 1;
11263 for (auto i : dim)
11264 {
11265 result *= i;
11266 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()
11267 {
11268 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));
11269 }
11270 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11271 {
11272 return false;
11273 }
11274 }
11275 is_ndarray = true;
11276 return sax->end_array();
11277 }
11278 result = 0;
11279 return true;
11280 }
11281
11282 default:
11283 break;
11284 }
11285 auto last_token = get_token_string();
11286 std::string message;
11287
11288 if (input_format != input_format_t::bjdata)
11289 {
11290 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11291 }
11292 else
11293 {
11294 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11295 }
11296 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
11297 }
11298
11310 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
11311 {
11312 result.first = npos; // size
11313 result.second = 0; // type
11314 bool is_ndarray = false;
11315
11316 get_ignore_noop();
11317
11318 if (current == '$')
11319 {
11320 result.second = get(); // must not ignore 'N', because 'N' maybe the type
11321 if (input_format == input_format_t::bjdata
11322 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
11323 {
11324 auto last_token = get_token_string();
11325 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11326 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
11327 }
11328
11329 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
11330 {
11331 return false;
11332 }
11333
11334 get_ignore_noop();
11335 if (JSON_HEDLEY_UNLIKELY(current != '#'))
11336 {
11337 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11338 {
11339 return false;
11340 }
11341 auto last_token = get_token_string();
11342 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11343 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
11344 }
11345
11346 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11347 if (input_format == input_format_t::bjdata && is_ndarray)
11348 {
11349 if (inside_ndarray)
11350 {
11351 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11352 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
11353 }
11354 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
11355 }
11356 return is_error;
11357 }
11358
11359 if (current == '#')
11360 {
11361 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11362 if (input_format == input_format_t::bjdata && is_ndarray)
11363 {
11364 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11365 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
11366 }
11367 return is_error;
11368 }
11369
11370 return true;
11371 }
11372
11377 bool get_ubjson_value(const char_int_type prefix)
11378 {
11379 switch (prefix)
11380 {
11381 case std::char_traits<char_type>::eof(): // EOF
11382 return unexpect_eof(input_format, "value");
11383
11384 case 'T': // true
11385 return sax->boolean(true);
11386 case 'F': // false
11387 return sax->boolean(false);
11388
11389 case 'Z': // null
11390 return sax->null();
11391
11392 case 'U':
11393 {
11394 std::uint8_t number{};
11395 return get_number(input_format, number) && sax->number_unsigned(number);
11396 }
11397
11398 case 'i':
11399 {
11400 std::int8_t number{};
11401 return get_number(input_format, number) && sax->number_integer(number);
11402 }
11403
11404 case 'I':
11405 {
11406 std::int16_t number{};
11407 return get_number(input_format, number) && sax->number_integer(number);
11408 }
11409
11410 case 'l':
11411 {
11412 std::int32_t number{};
11413 return get_number(input_format, number) && sax->number_integer(number);
11414 }
11415
11416 case 'L':
11417 {
11418 std::int64_t number{};
11419 return get_number(input_format, number) && sax->number_integer(number);
11420 }
11421
11422 case 'u':
11423 {
11424 if (input_format != input_format_t::bjdata)
11425 {
11426 break;
11427 }
11428 std::uint16_t number{};
11429 return get_number(input_format, number) && sax->number_unsigned(number);
11430 }
11431
11432 case 'm':
11433 {
11434 if (input_format != input_format_t::bjdata)
11435 {
11436 break;
11437 }
11438 std::uint32_t number{};
11439 return get_number(input_format, number) && sax->number_unsigned(number);
11440 }
11441
11442 case 'M':
11443 {
11444 if (input_format != input_format_t::bjdata)
11445 {
11446 break;
11447 }
11448 std::uint64_t number{};
11449 return get_number(input_format, number) && sax->number_unsigned(number);
11450 }
11451
11452 case 'h':
11453 {
11454 if (input_format != input_format_t::bjdata)
11455 {
11456 break;
11457 }
11458 const auto byte1_raw = get();
11459 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11460 {
11461 return false;
11462 }
11463 const auto byte2_raw = get();
11464 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11465 {
11466 return false;
11467 }
11468
11469 const auto byte1 = static_cast<unsigned char>(byte1_raw);
11470 const auto byte2 = static_cast<unsigned char>(byte2_raw);
11471
11472 // code from RFC 7049, Appendix D, Figure 3:
11473 // As half-precision floating-point numbers were only added
11474 // to IEEE 754 in 2008, today's programming platforms often
11475 // still only have limited support for them. It is very
11476 // easy to include at least decoding support for them even
11477 // without such support. An example of a small decoder for
11478 // half-precision floating-point numbers in the C language
11479 // is shown in Fig. 3.
11480 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11481 const double val = [&half]
11482 {
11483 const int exp = (half >> 10u) & 0x1Fu;
11484 const unsigned int mant = half & 0x3FFu;
11485 JSON_ASSERT(0 <= exp&& exp <= 32);
11486 JSON_ASSERT(mant <= 1024);
11487 switch (exp)
11488 {
11489 case 0:
11490 return std::ldexp(mant, -24);
11491 case 31:
11492 return (mant == 0)
11493 ? std::numeric_limits<double>::infinity()
11494 : std::numeric_limits<double>::quiet_NaN();
11495 default:
11496 return std::ldexp(mant + 1024, exp - 25);
11497 }
11498 }();
11499 return sax->number_float((half & 0x8000u) != 0
11500 ? static_cast<number_float_t>(-val)
11501 : static_cast<number_float_t>(val), "");
11502 }
11503
11504 case 'd':
11505 {
11506 float number{};
11507 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11508 }
11509
11510 case 'D':
11511 {
11512 double number{};
11513 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11514 }
11515
11516 case 'H':
11517 {
11518 return get_ubjson_high_precision_number();
11519 }
11520
11521 case 'C': // char
11522 {
11523 get();
11524 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
11525 {
11526 return false;
11527 }
11528 if (JSON_HEDLEY_UNLIKELY(current > 127))
11529 {
11530 auto last_token = get_token_string();
11531 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11532 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
11533 }
11534 string_t s(1, static_cast<typename string_t::value_type>(current));
11535 return sax->string(s);
11536 }
11537
11538 case 'S': // string
11539 {
11540 string_t s;
11541 return get_ubjson_string(s) && sax->string(s);
11542 }
11543
11544 case '[': // array
11545 return get_ubjson_array();
11546
11547 case '{': // object
11548 return get_ubjson_object();
11549
11550 default: // anything else
11551 break;
11552 }
11553 auto last_token = get_token_string();
11554 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));
11555 }
11556
11560 bool get_ubjson_array()
11561 {
11562 std::pair<std::size_t, char_int_type> size_and_type;
11563 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11564 {
11565 return false;
11566 }
11567
11568 // 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):
11569 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
11570
11571 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11572 {
11573 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
11574 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)
11575 {
11576 return p.first < t;
11577 });
11578 string_t key = "_ArrayType_";
11579 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
11580 {
11581 auto last_token = get_token_string();
11582 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11583 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
11584 }
11585
11586 string_t type = it->second; // sax->string() takes a reference
11587 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
11588 {
11589 return false;
11590 }
11591
11592 if (size_and_type.second == 'C')
11593 {
11594 size_and_type.second = 'U';
11595 }
11596
11597 key = "_ArrayData_";
11598 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
11599 {
11600 return false;
11601 }
11602
11603 for (std::size_t i = 0; i < size_and_type.first; ++i)
11604 {
11605 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11606 {
11607 return false;
11608 }
11609 }
11610
11611 return (sax->end_array() && sax->end_object());
11612 }
11613
11614 if (size_and_type.first != npos)
11615 {
11616 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
11617 {
11618 return false;
11619 }
11620
11621 if (size_and_type.second != 0)
11622 {
11623 if (size_and_type.second != 'N')
11624 {
11625 for (std::size_t i = 0; i < size_and_type.first; ++i)
11626 {
11627 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11628 {
11629 return false;
11630 }
11631 }
11632 }
11633 }
11634 else
11635 {
11636 for (std::size_t i = 0; i < size_and_type.first; ++i)
11637 {
11638 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11639 {
11640 return false;
11641 }
11642 }
11643 }
11644 }
11645 else
11646 {
11647 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
11648 {
11649 return false;
11650 }
11651
11652 while (current != ']')
11653 {
11654 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
11655 {
11656 return false;
11657 }
11658 get_ignore_noop();
11659 }
11660 }
11661
11662 return sax->end_array();
11663 }
11664
11668 bool get_ubjson_object()
11669 {
11670 std::pair<std::size_t, char_int_type> size_and_type;
11671 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11672 {
11673 return false;
11674 }
11675
11676 // do not accept ND-array size in objects in BJData
11677 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11678 {
11679 auto last_token = get_token_string();
11680 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11681 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
11682 }
11683
11684 string_t key;
11685 if (size_and_type.first != npos)
11686 {
11687 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
11688 {
11689 return false;
11690 }
11691
11692 if (size_and_type.second != 0)
11693 {
11694 for (std::size_t i = 0; i < size_and_type.first; ++i)
11695 {
11696 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11697 {
11698 return false;
11699 }
11700 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11701 {
11702 return false;
11703 }
11704 key.clear();
11705 }
11706 }
11707 else
11708 {
11709 for (std::size_t i = 0; i < size_and_type.first; ++i)
11710 {
11711 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11712 {
11713 return false;
11714 }
11715 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11716 {
11717 return false;
11718 }
11719 key.clear();
11720 }
11721 }
11722 }
11723 else
11724 {
11725 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
11726 {
11727 return false;
11728 }
11729
11730 while (current != '}')
11731 {
11732 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
11733 {
11734 return false;
11735 }
11736 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11737 {
11738 return false;
11739 }
11740 get_ignore_noop();
11741 key.clear();
11742 }
11743 }
11744
11745 return sax->end_object();
11746 }
11747
11748 // Note, no reader for UBJSON binary types is implemented because they do
11749 // not exist
11750
11751 bool get_ubjson_high_precision_number()
11752 {
11753 // get size of following number string
11754 std::size_t size{};
11755 bool no_ndarray = true;
11756 auto res = get_ubjson_size_value(size, no_ndarray);
11757 if (JSON_HEDLEY_UNLIKELY(!res))
11758 {
11759 return res;
11760 }
11761
11762 // get number string
11763 std::vector<char> number_vector;
11764 for (std::size_t i = 0; i < size; ++i)
11765 {
11766 get();
11767 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11768 {
11769 return false;
11770 }
11771 number_vector.push_back(static_cast<char>(current));
11772 }
11773
11774 // parse number string
11775 using ia_type = decltype(detail::input_adapter(number_vector));
11776 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11777 const auto result_number = number_lexer.scan();
11778 const auto number_string = number_lexer.get_token_string();
11779 const auto result_remainder = number_lexer.scan();
11780
11781 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
11782
11783 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
11784 {
11785 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11786 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11787 }
11788
11789 switch (result_number)
11790 {
11791 case token_type::value_integer:
11792 return sax->number_integer(number_lexer.get_number_integer());
11793 case token_type::value_unsigned:
11794 return sax->number_unsigned(number_lexer.get_number_unsigned());
11795 case token_type::value_float:
11796 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11797 case token_type::uninitialized:
11798 case token_type::literal_true:
11799 case token_type::literal_false:
11800 case token_type::literal_null:
11801 case token_type::value_string:
11802 case token_type::begin_array:
11803 case token_type::begin_object:
11804 case token_type::end_array:
11805 case token_type::end_object:
11806 case token_type::name_separator:
11807 case token_type::value_separator:
11808 case token_type::parse_error:
11809 case token_type::end_of_input:
11810 case token_type::literal_or_value:
11811 default:
11812 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11813 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11814 }
11815 }
11816
11818 // Utility functions //
11820
11830 char_int_type get()
11831 {
11832 ++chars_read;
11833 return current = ia.get_character();
11834 }
11835
11839 char_int_type get_ignore_noop()
11840 {
11841 do
11842 {
11843 get();
11844 }
11845 while (current == 'N');
11846
11847 return current;
11848 }
11849
11850 /*
11851 @brief read a number from the input
11852
11853 @tparam NumberType the type of the number
11854 @param[in] format the current format (for diagnostics)
11855 @param[out] result number of type @a NumberType
11856
11857 @return whether conversion completed
11858
11859 @note This function needs to respect the system's endianness, because
11860 bytes in CBOR, MessagePack, and UBJSON are stored in network order
11861 (big endian) and therefore need reordering on little endian systems.
11862 On the other hand, BSON and BJData use little endian and should reorder
11863 on big endian systems.
11864 */
11865 template<typename NumberType, bool InputIsLittleEndian = false>
11866 bool get_number(const input_format_t format, NumberType& result)
11867 {
11868 // step 1: read input into array with system's byte order
11869 std::array<std::uint8_t, sizeof(NumberType)> vec{};
11870 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
11871 {
11872 get();
11873 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
11874 {
11875 return false;
11876 }
11877
11878 // reverse byte order prior to conversion if necessary
11879 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
11880 {
11881 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
11882 }
11883 else
11884 {
11885 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
11886 }
11887 }
11888
11889 // step 2: convert array into number of type T and return
11890 std::memcpy(&result, vec.data(), sizeof(NumberType));
11891 return true;
11892 }
11893
11908 template<typename NumberType>
11909 bool get_string(const input_format_t format,
11910 const NumberType len,
11911 string_t& result)
11912 {
11913 bool success = true;
11914 for (NumberType i = 0; i < len; i++)
11915 {
11916 get();
11917 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
11918 {
11919 success = false;
11920 break;
11921 }
11922 result.push_back(static_cast<typename string_t::value_type>(current));
11923 }
11924 return success;
11925 }
11926
11941 template<typename NumberType>
11942 bool get_binary(const input_format_t format,
11943 const NumberType len,
11944 binary_t& result)
11945 {
11946 bool success = true;
11947 for (NumberType i = 0; i < len; i++)
11948 {
11949 get();
11950 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
11951 {
11952 success = false;
11953 break;
11954 }
11955 result.push_back(static_cast<std::uint8_t>(current));
11956 }
11957 return success;
11958 }
11959
11966 bool unexpect_eof(const input_format_t format, const char* context) const
11967 {
11968 if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
11969 {
11970 return sax->parse_error(chars_read, "<end of file>",
11971 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
11972 }
11973 return true;
11974 }
11975
11979 std::string get_token_string() const
11980 {
11981 std::array<char, 3> cr{{}};
11982 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
11983 return std::string{cr.data()};
11984 }
11985
11992 std::string exception_message(const input_format_t format,
11993 const std::string& detail,
11994 const std::string& context) const
11995 {
11996 std::string error_msg = "syntax error while parsing ";
11997
11998 switch (format)
11999 {
12000 case input_format_t::cbor:
12001 error_msg += "CBOR";
12002 break;
12003
12004 case input_format_t::msgpack:
12005 error_msg += "MessagePack";
12006 break;
12007
12008 case input_format_t::ubjson:
12009 error_msg += "UBJSON";
12010 break;
12011
12012 case input_format_t::bson:
12013 error_msg += "BSON";
12014 break;
12015
12016 case input_format_t::bjdata:
12017 error_msg += "BJData";
12018 break;
12019
12020 case input_format_t::json: // LCOV_EXCL_LINE
12021 default: // LCOV_EXCL_LINE
12022 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12023 }
12024
12025 return concat(error_msg, ' ', context, ": ", detail);
12026 }
12027
12028 private:
12029 static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
12030
12032 InputAdapterType ia;
12033
12035 char_int_type current = std::char_traits<char_type>::eof();
12036
12038 std::size_t chars_read = 0;
12039
12041 const bool is_little_endian = little_endianness();
12042
12044 const input_format_t input_format = input_format_t::json;
12045
12047 json_sax_t* sax = nullptr;
12048
12049 // excluded markers in bjdata optimized type
12050#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12051 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12052
12053#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12054 make_array<bjd_type>( \
12055 bjd_type{'C', "char"}, \
12056 bjd_type{'D', "double"}, \
12057 bjd_type{'I', "int16"}, \
12058 bjd_type{'L', "int64"}, \
12059 bjd_type{'M', "uint64"}, \
12060 bjd_type{'U', "uint8"}, \
12061 bjd_type{'d', "single"}, \
12062 bjd_type{'i', "int8"}, \
12063 bjd_type{'l', "int32"}, \
12064 bjd_type{'m', "uint32"}, \
12065 bjd_type{'u', "uint16"})
12066
12068 // lookup tables
12069 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12070 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12072
12073 using bjd_type = std::pair<char_int_type, string_t>;
12074 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12075 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12077
12078#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12079#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12080};
12081
12082#ifndef JSON_HAS_CPP_17
12083 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12084 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12085#endif
12086
12087} // namespace detail
12089
12090// #include <nlohmann/detail/input/input_adapters.hpp>
12091
12092// #include <nlohmann/detail/input/lexer.hpp>
12093
12094// #include <nlohmann/detail/input/parser.hpp>
12095// __ _____ _____ _____
12096// __| | __| | | | JSON for Modern C++
12097// | | |__ | | | | | | version 3.11.2
12098// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12099//
12100// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12101// SPDX-License-Identifier: MIT
12102
12103
12104
12105#include <cmath> // isfinite
12106#include <cstdint> // uint8_t
12107#include <functional> // function
12108#include <string> // string
12109#include <utility> // move
12110#include <vector> // vector
12111
12112// #include <nlohmann/detail/exceptions.hpp>
12113
12114// #include <nlohmann/detail/input/input_adapters.hpp>
12115
12116// #include <nlohmann/detail/input/json_sax.hpp>
12117
12118// #include <nlohmann/detail/input/lexer.hpp>
12119
12120// #include <nlohmann/detail/macro_scope.hpp>
12121
12122// #include <nlohmann/detail/meta/is_sax.hpp>
12123
12124// #include <nlohmann/detail/string_concat.hpp>
12125
12126// #include <nlohmann/detail/value_t.hpp>
12127
12128
12130namespace detail
12131{
12133// parser //
12135
12136enum class parse_event_t : std::uint8_t
12137{
12139 object_start,
12141 object_end,
12143 array_start,
12145 array_end,
12147 key,
12149 value
12150};
12151
12152template<typename BasicJsonType>
12153using parser_callback_t =
12154 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12155
12161template<typename BasicJsonType, typename InputAdapterType>
12162class parser
12163{
12164 using number_integer_t = typename BasicJsonType::number_integer_t;
12165 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12166 using number_float_t = typename BasicJsonType::number_float_t;
12167 using string_t = typename BasicJsonType::string_t;
12168 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
12169 using token_type = typename lexer_t::token_type;
12170
12171 public:
12173 explicit parser(InputAdapterType&& adapter,
12174 const parser_callback_t<BasicJsonType> cb = nullptr,
12175 const bool allow_exceptions_ = true,
12176 const bool skip_comments = false)
12177 : callback(cb)
12178 , m_lexer(std::move(adapter), skip_comments)
12179 , allow_exceptions(allow_exceptions_)
12180 {
12181 // read first token
12182 get_token();
12183 }
12184
12195 void parse(const bool strict, BasicJsonType& result)
12196 {
12197 if (callback)
12198 {
12199 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
12200 sax_parse_internal(&sdp);
12201
12202 // in strict mode, input must be completely read
12203 if (strict && (get_token() != token_type::end_of_input))
12204 {
12205 sdp.parse_error(m_lexer.get_position(),
12206 m_lexer.get_token_string(),
12207 parse_error::create(101, m_lexer.get_position(),
12208 exception_message(token_type::end_of_input, "value"), nullptr));
12209 }
12210
12211 // in case of an error, return discarded value
12212 if (sdp.is_errored())
12213 {
12214 result = value_t::discarded;
12215 return;
12216 }
12217
12218 // set top-level value to null if it was discarded by the callback
12219 // function
12220 if (result.is_discarded())
12221 {
12222 result = nullptr;
12223 }
12224 }
12225 else
12226 {
12227 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
12228 sax_parse_internal(&sdp);
12229
12230 // in strict mode, input must be completely read
12231 if (strict && (get_token() != token_type::end_of_input))
12232 {
12233 sdp.parse_error(m_lexer.get_position(),
12234 m_lexer.get_token_string(),
12235 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12236 }
12237
12238 // in case of an error, return discarded value
12239 if (sdp.is_errored())
12240 {
12241 result = value_t::discarded;
12242 return;
12243 }
12244 }
12245
12246 result.assert_invariant();
12247 }
12248
12255 bool accept(const bool strict = true)
12256 {
12257 json_sax_acceptor<BasicJsonType> sax_acceptor;
12258 return sax_parse(&sax_acceptor, strict);
12259 }
12260
12261 template<typename SAX>
12263 bool sax_parse(SAX* sax, const bool strict = true)
12264 {
12265 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
12266 const bool result = sax_parse_internal(sax);
12267
12268 // strict mode: next byte must be EOF
12269 if (result && strict && (get_token() != token_type::end_of_input))
12270 {
12271 return sax->parse_error(m_lexer.get_position(),
12272 m_lexer.get_token_string(),
12273 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12274 }
12275
12276 return result;
12277 }
12278
12279 private:
12280 template<typename SAX>
12282 bool sax_parse_internal(SAX* sax)
12283 {
12284 // stack to remember the hierarchy of structured values we are parsing
12285 // true = array; false = object
12286 std::vector<bool> states;
12287 // value to avoid a goto (see comment where set to true)
12288 bool skip_to_state_evaluation = false;
12289
12290 while (true)
12291 {
12292 if (!skip_to_state_evaluation)
12293 {
12294 // invariant: get_token() was called before each iteration
12295 switch (last_token)
12296 {
12297 case token_type::begin_object:
12298 {
12299 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
12300 {
12301 return false;
12302 }
12303
12304 // closing } -> we are done
12305 if (get_token() == token_type::end_object)
12306 {
12307 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12308 {
12309 return false;
12310 }
12311 break;
12312 }
12313
12314 // parse key
12315 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
12316 {
12317 return sax->parse_error(m_lexer.get_position(),
12318 m_lexer.get_token_string(),
12319 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12320 }
12321 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12322 {
12323 return false;
12324 }
12325
12326 // parse separator (:)
12327 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12328 {
12329 return sax->parse_error(m_lexer.get_position(),
12330 m_lexer.get_token_string(),
12331 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12332 }
12333
12334 // remember we are now inside an object
12335 states.push_back(false);
12336
12337 // parse values
12338 get_token();
12339 continue;
12340 }
12341
12342 case token_type::begin_array:
12343 {
12344 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
12345 {
12346 return false;
12347 }
12348
12349 // closing ] -> we are done
12350 if (get_token() == token_type::end_array)
12351 {
12352 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12353 {
12354 return false;
12355 }
12356 break;
12357 }
12358
12359 // remember we are now inside an array
12360 states.push_back(true);
12361
12362 // parse values (no need to call get_token)
12363 continue;
12364 }
12365
12366 case token_type::value_float:
12367 {
12368 const auto res = m_lexer.get_number_float();
12369
12370 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
12371 {
12372 return sax->parse_error(m_lexer.get_position(),
12373 m_lexer.get_token_string(),
12374 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
12375 }
12376
12377 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
12378 {
12379 return false;
12380 }
12381
12382 break;
12383 }
12384
12385 case token_type::literal_false:
12386 {
12387 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
12388 {
12389 return false;
12390 }
12391 break;
12392 }
12393
12394 case token_type::literal_null:
12395 {
12396 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
12397 {
12398 return false;
12399 }
12400 break;
12401 }
12402
12403 case token_type::literal_true:
12404 {
12405 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
12406 {
12407 return false;
12408 }
12409 break;
12410 }
12411
12412 case token_type::value_integer:
12413 {
12414 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
12415 {
12416 return false;
12417 }
12418 break;
12419 }
12420
12421 case token_type::value_string:
12422 {
12423 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
12424 {
12425 return false;
12426 }
12427 break;
12428 }
12429
12430 case token_type::value_unsigned:
12431 {
12432 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
12433 {
12434 return false;
12435 }
12436 break;
12437 }
12438
12439 case token_type::parse_error:
12440 {
12441 // using "uninitialized" to avoid "expected" message
12442 return sax->parse_error(m_lexer.get_position(),
12443 m_lexer.get_token_string(),
12444 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
12445 }
12446
12447 case token_type::uninitialized:
12448 case token_type::end_array:
12449 case token_type::end_object:
12450 case token_type::name_separator:
12451 case token_type::value_separator:
12452 case token_type::end_of_input:
12453 case token_type::literal_or_value:
12454 default: // the last token was unexpected
12455 {
12456 return sax->parse_error(m_lexer.get_position(),
12457 m_lexer.get_token_string(),
12458 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12459 }
12460 }
12461 }
12462 else
12463 {
12464 skip_to_state_evaluation = false;
12465 }
12466
12467 // we reached this line after we successfully parsed a value
12468 if (states.empty())
12469 {
12470 // empty stack: we reached the end of the hierarchy: done
12471 return true;
12472 }
12473
12474 if (states.back()) // array
12475 {
12476 // comma -> next value
12477 if (get_token() == token_type::value_separator)
12478 {
12479 // parse a new value
12480 get_token();
12481 continue;
12482 }
12483
12484 // closing ]
12485 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
12486 {
12487 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12488 {
12489 return false;
12490 }
12491
12492 // We are done with this array. Before we can parse a
12493 // new value, we need to evaluate the new state first.
12494 // By setting skip_to_state_evaluation to false, we
12495 // are effectively jumping to the beginning of this if.
12496 JSON_ASSERT(!states.empty());
12497 states.pop_back();
12498 skip_to_state_evaluation = true;
12499 continue;
12500 }
12501
12502 return sax->parse_error(m_lexer.get_position(),
12503 m_lexer.get_token_string(),
12504 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
12505 }
12506
12507 // states.back() is false -> object
12508
12509 // comma -> next value
12510 if (get_token() == token_type::value_separator)
12511 {
12512 // parse key
12513 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
12514 {
12515 return sax->parse_error(m_lexer.get_position(),
12516 m_lexer.get_token_string(),
12517 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12518 }
12519
12520 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12521 {
12522 return false;
12523 }
12524
12525 // parse separator (:)
12526 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12527 {
12528 return sax->parse_error(m_lexer.get_position(),
12529 m_lexer.get_token_string(),
12530 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12531 }
12532
12533 // parse values
12534 get_token();
12535 continue;
12536 }
12537
12538 // closing }
12539 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
12540 {
12541 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12542 {
12543 return false;
12544 }
12545
12546 // We are done with this object. Before we can parse a
12547 // new value, we need to evaluate the new state first.
12548 // By setting skip_to_state_evaluation to false, we
12549 // are effectively jumping to the beginning of this if.
12550 JSON_ASSERT(!states.empty());
12551 states.pop_back();
12552 skip_to_state_evaluation = true;
12553 continue;
12554 }
12555
12556 return sax->parse_error(m_lexer.get_position(),
12557 m_lexer.get_token_string(),
12558 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
12559 }
12560 }
12561
12563 token_type get_token()
12564 {
12565 return last_token = m_lexer.scan();
12566 }
12567
12568 std::string exception_message(const token_type expected, const std::string& context)
12569 {
12570 std::string error_msg = "syntax error ";
12571
12572 if (!context.empty())
12573 {
12574 error_msg += concat("while parsing ", context, ' ');
12575 }
12576
12577 error_msg += "- ";
12578
12579 if (last_token == token_type::parse_error)
12580 {
12581 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12582 m_lexer.get_token_string(), '\'');
12583 }
12584 else
12585 {
12586 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12587 }
12588
12589 if (expected != token_type::uninitialized)
12590 {
12591 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12592 }
12593
12594 return error_msg;
12595 }
12596
12597 private:
12599 const parser_callback_t<BasicJsonType> callback = nullptr;
12601 token_type last_token = token_type::uninitialized;
12603 lexer_t m_lexer;
12605 const bool allow_exceptions = true;
12606};
12607
12608} // namespace detail
12610
12611// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12612// __ _____ _____ _____
12613// __| | __| | | | JSON for Modern C++
12614// | | |__ | | | | | | version 3.11.2
12615// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12616//
12617// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12618// SPDX-License-Identifier: MIT
12619
12620
12621
12622// #include <nlohmann/detail/abi_macros.hpp>
12623
12624// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12625// __ _____ _____ _____
12626// __| | __| | | | JSON for Modern C++
12627// | | |__ | | | | | | version 3.11.2
12628// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12629//
12630// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12631// SPDX-License-Identifier: MIT
12632
12633
12634
12635#include <cstddef> // ptrdiff_t
12636#include <limits> // numeric_limits
12637
12638// #include <nlohmann/detail/macro_scope.hpp>
12639
12640
12642namespace detail
12643{
12644
12645/*
12646@brief an iterator for primitive JSON types
12647
12648This class models an iterator for primitive JSON types (boolean, number,
12649string). It's only purpose is to allow the iterator/const_iterator classes
12650to "iterate" over primitive values. Internally, the iterator is modeled by
12651a `difference_type` variable. Value begin_value (`0`) models the begin,
12652end_value (`1`) models past the end.
12653*/
12654class primitive_iterator_t
12655{
12656 private:
12657 using difference_type = std::ptrdiff_t;
12658 static constexpr difference_type begin_value = 0;
12659 static constexpr difference_type end_value = begin_value + 1;
12660
12663 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12664
12665 public:
12666 constexpr difference_type get_value() const noexcept
12667 {
12668 return m_it;
12669 }
12670
12672 void set_begin() noexcept
12673 {
12674 m_it = begin_value;
12675 }
12676
12678 void set_end() noexcept
12679 {
12680 m_it = end_value;
12681 }
12682
12684 constexpr bool is_begin() const noexcept
12685 {
12686 return m_it == begin_value;
12687 }
12688
12690 constexpr bool is_end() const noexcept
12691 {
12692 return m_it == end_value;
12693 }
12694
12695 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12696 {
12697 return lhs.m_it == rhs.m_it;
12698 }
12699
12700 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12701 {
12702 return lhs.m_it < rhs.m_it;
12703 }
12704
12705 primitive_iterator_t operator+(difference_type n) noexcept
12706 {
12707 auto result = *this;
12708 result += n;
12709 return result;
12710 }
12711
12712 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12713 {
12714 return lhs.m_it - rhs.m_it;
12715 }
12716
12717 primitive_iterator_t& operator++() noexcept
12718 {
12719 ++m_it;
12720 return *this;
12721 }
12722
12723 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
12724 {
12725 auto result = *this;
12726 ++m_it;
12727 return result;
12728 }
12729
12730 primitive_iterator_t& operator--() noexcept
12731 {
12732 --m_it;
12733 return *this;
12734 }
12735
12736 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
12737 {
12738 auto result = *this;
12739 --m_it;
12740 return result;
12741 }
12742
12743 primitive_iterator_t& operator+=(difference_type n) noexcept
12744 {
12745 m_it += n;
12746 return *this;
12747 }
12748
12749 primitive_iterator_t& operator-=(difference_type n) noexcept
12750 {
12751 m_it -= n;
12752 return *this;
12753 }
12754};
12755
12756} // namespace detail
12758
12759
12761namespace detail
12762{
12763
12770template<typename BasicJsonType> struct internal_iterator
12771{
12773 typename BasicJsonType::object_t::iterator object_iterator {};
12775 typename BasicJsonType::array_t::iterator array_iterator {};
12777 primitive_iterator_t primitive_iterator {};
12778};
12779
12780} // namespace detail
12782
12783// #include <nlohmann/detail/iterators/iter_impl.hpp>
12784// __ _____ _____ _____
12785// __| | __| | | | JSON for Modern C++
12786// | | |__ | | | | | | version 3.11.2
12787// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12788//
12789// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12790// SPDX-License-Identifier: MIT
12791
12792
12793
12794#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
12795#include <type_traits> // conditional, is_const, remove_const
12796
12797// #include <nlohmann/detail/exceptions.hpp>
12798
12799// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12800
12801// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12802
12803// #include <nlohmann/detail/macro_scope.hpp>
12804
12805// #include <nlohmann/detail/meta/cpp_future.hpp>
12806
12807// #include <nlohmann/detail/meta/type_traits.hpp>
12808
12809// #include <nlohmann/detail/value_t.hpp>
12810
12811
12813namespace detail
12814{
12815
12816// forward declare, to be able to friend it later on
12817template<typename IteratorType> class iteration_proxy;
12818template<typename IteratorType> class iteration_proxy_value;
12819
12836template<typename BasicJsonType>
12837class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
12838{
12840 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
12842 friend other_iter_impl;
12843 friend BasicJsonType;
12846
12847 using object_t = typename BasicJsonType::object_t;
12848 using array_t = typename BasicJsonType::array_t;
12849 // make sure BasicJsonType is basic_json or const basic_json
12851 "iter_impl only accepts (const) basic_json");
12852 // superficial check for the LegacyBidirectionalIterator named requirement
12853 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
12854 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
12855 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
12856
12857 public:
12863 using iterator_category = std::bidirectional_iterator_tag;
12864
12866 using value_type = typename BasicJsonType::value_type;
12868 using difference_type = typename BasicJsonType::difference_type;
12870 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
12871 typename BasicJsonType::const_pointer,
12872 typename BasicJsonType::pointer>::type;
12875 typename std::conditional<std::is_const<BasicJsonType>::value,
12876 typename BasicJsonType::const_reference,
12877 typename BasicJsonType::reference>::type;
12878
12879 iter_impl() = default;
12880 ~iter_impl() = default;
12881 iter_impl(iter_impl&&) noexcept = default;
12882 iter_impl& operator=(iter_impl&&) noexcept = default;
12883
12890 explicit iter_impl(pointer object) noexcept : m_object(object)
12891 {
12892 JSON_ASSERT(m_object != nullptr);
12893
12894 switch (m_object->m_data.m_type)
12895 {
12896 case value_t::object:
12897 {
12898 m_it.object_iterator = typename object_t::iterator();
12899 break;
12900 }
12901
12902 case value_t::array:
12903 {
12904 m_it.array_iterator = typename array_t::iterator();
12905 break;
12906 }
12907
12908 case value_t::null:
12909 case value_t::string:
12910 case value_t::boolean:
12914 case value_t::binary:
12915 case value_t::discarded:
12916 default:
12917 {
12918 m_it.primitive_iterator = primitive_iterator_t();
12919 break;
12920 }
12921 }
12922 }
12923
12941 : m_object(other.m_object), m_it(other.m_it)
12942 {}
12943
12951 {
12952 if (&other != this)
12953 {
12954 m_object = other.m_object;
12955 m_it = other.m_it;
12956 }
12957 return *this;
12958 }
12959
12965 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
12966 : m_object(other.m_object), m_it(other.m_it)
12967 {}
12968
12975 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
12976 {
12977 m_object = other.m_object;
12978 m_it = other.m_it;
12979 return *this;
12980 }
12981
12987 void set_begin() noexcept
12988 {
12989 JSON_ASSERT(m_object != nullptr);
12990
12991 switch (m_object->m_data.m_type)
12992 {
12993 case value_t::object:
12994 {
12995 m_it.object_iterator = m_object->m_data.m_value.object->begin();
12996 break;
12997 }
12998
12999 case value_t::array:
13000 {
13001 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13002 break;
13003 }
13004
13005 case value_t::null:
13006 {
13007 // set to end so begin()==end() is true: null is empty
13008 m_it.primitive_iterator.set_end();
13009 break;
13010 }
13011
13012 case value_t::string:
13013 case value_t::boolean:
13017 case value_t::binary:
13018 case value_t::discarded:
13019 default:
13020 {
13021 m_it.primitive_iterator.set_begin();
13022 break;
13023 }
13024 }
13025 }
13026
13031 void set_end() noexcept
13032 {
13033 JSON_ASSERT(m_object != nullptr);
13034
13035 switch (m_object->m_data.m_type)
13036 {
13037 case value_t::object:
13038 {
13039 m_it.object_iterator = m_object->m_data.m_value.object->end();
13040 break;
13041 }
13042
13043 case value_t::array:
13044 {
13045 m_it.array_iterator = m_object->m_data.m_value.array->end();
13046 break;
13047 }
13048
13049 case value_t::null:
13050 case value_t::string:
13051 case value_t::boolean:
13055 case value_t::binary:
13056 case value_t::discarded:
13057 default:
13058 {
13059 m_it.primitive_iterator.set_end();
13060 break;
13061 }
13062 }
13063 }
13064
13065 public:
13071 {
13072 JSON_ASSERT(m_object != nullptr);
13073
13074 switch (m_object->m_data.m_type)
13075 {
13076 case value_t::object:
13077 {
13078 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13079 return m_it.object_iterator->second;
13080 }
13081
13082 case value_t::array:
13083 {
13084 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13085 return *m_it.array_iterator;
13086 }
13087
13088 case value_t::null:
13089 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13090
13091 case value_t::string:
13092 case value_t::boolean:
13096 case value_t::binary:
13097 case value_t::discarded:
13098 default:
13099 {
13101 {
13102 return *m_object;
13103 }
13104
13105 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13106 }
13107 }
13108 }
13109
13115 {
13116 JSON_ASSERT(m_object != nullptr);
13117
13118 switch (m_object->m_data.m_type)
13119 {
13120 case value_t::object:
13121 {
13122 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13123 return &(m_it.object_iterator->second);
13124 }
13125
13126 case value_t::array:
13127 {
13128 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13129 return &*m_it.array_iterator;
13130 }
13131
13132 case value_t::null:
13133 case value_t::string:
13134 case value_t::boolean:
13138 case value_t::binary:
13139 case value_t::discarded:
13140 default:
13141 {
13143 {
13144 return m_object;
13145 }
13146
13147 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13148 }
13149 }
13150 }
13151
13156 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13157 {
13158 auto result = *this;
13159 ++(*this);
13160 return result;
13161 }
13162
13168 {
13169 JSON_ASSERT(m_object != nullptr);
13170
13171 switch (m_object->m_data.m_type)
13172 {
13173 case value_t::object:
13174 {
13175 std::advance(m_it.object_iterator, 1);
13176 break;
13177 }
13178
13179 case value_t::array:
13180 {
13181 std::advance(m_it.array_iterator, 1);
13182 break;
13183 }
13184
13185 case value_t::null:
13186 case value_t::string:
13187 case value_t::boolean:
13191 case value_t::binary:
13192 case value_t::discarded:
13193 default:
13194 {
13196 break;
13197 }
13198 }
13199
13200 return *this;
13201 }
13202
13207 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13208 {
13209 auto result = *this;
13210 --(*this);
13211 return result;
13212 }
13213
13219 {
13220 JSON_ASSERT(m_object != nullptr);
13221
13222 switch (m_object->m_data.m_type)
13223 {
13224 case value_t::object:
13225 {
13226 std::advance(m_it.object_iterator, -1);
13227 break;
13228 }
13229
13230 case value_t::array:
13231 {
13232 std::advance(m_it.array_iterator, -1);
13233 break;
13234 }
13235
13236 case value_t::null:
13237 case value_t::string:
13238 case value_t::boolean:
13242 case value_t::binary:
13243 case value_t::discarded:
13244 default:
13245 {
13247 break;
13248 }
13249 }
13250
13251 return *this;
13252 }
13253
13258 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 >
13259 bool operator==(const IterImpl& other) const
13260 {
13261 // if objects are not the same, the comparison is undefined
13262 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13263 {
13264 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13265 }
13266
13267 JSON_ASSERT(m_object != nullptr);
13268
13269 switch (m_object->m_data.m_type)
13270 {
13271 case value_t::object:
13272 return (m_it.object_iterator == other.m_it.object_iterator);
13273
13274 case value_t::array:
13275 return (m_it.array_iterator == other.m_it.array_iterator);
13276
13277 case value_t::null:
13278 case value_t::string:
13279 case value_t::boolean:
13283 case value_t::binary:
13284 case value_t::discarded:
13285 default:
13286 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
13287 }
13288 }
13289
13294 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 >
13295 bool operator!=(const IterImpl& other) const
13296 {
13297 return !operator==(other);
13298 }
13299
13304 bool operator<(const iter_impl& other) const
13305 {
13306 // if objects are not the same, the comparison is undefined
13307 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13308 {
13309 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13310 }
13311
13312 JSON_ASSERT(m_object != nullptr);
13313
13314 switch (m_object->m_data.m_type)
13315 {
13316 case value_t::object:
13317 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
13318
13319 case value_t::array:
13320 return (m_it.array_iterator < other.m_it.array_iterator);
13321
13322 case value_t::null:
13323 case value_t::string:
13324 case value_t::boolean:
13328 case value_t::binary:
13329 case value_t::discarded:
13330 default:
13332 }
13333 }
13334
13339 bool operator<=(const iter_impl& other) const
13340 {
13341 return !other.operator < (*this);
13342 }
13343
13348 bool operator>(const iter_impl& other) const
13349 {
13350 return !operator<=(other);
13351 }
13352
13357 bool operator>=(const iter_impl& other) const
13358 {
13359 return !operator<(other);
13360 }
13361
13367 {
13368 JSON_ASSERT(m_object != nullptr);
13369
13370 switch (m_object->m_data.m_type)
13371 {
13372 case value_t::object:
13373 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13374
13375 case value_t::array:
13376 {
13377 std::advance(m_it.array_iterator, i);
13378 break;
13379 }
13380
13381 case value_t::null:
13382 case value_t::string:
13383 case value_t::boolean:
13387 case value_t::binary:
13388 case value_t::discarded:
13389 default:
13390 {
13392 break;
13393 }
13394 }
13395
13396 return *this;
13397 }
13398
13404 {
13405 return operator+=(-i);
13406 }
13407
13413 {
13414 auto result = *this;
13415 result += i;
13416 return result;
13417 }
13418
13424 {
13425 auto result = it;
13426 result += i;
13427 return result;
13428 }
13429
13435 {
13436 auto result = *this;
13437 result -= i;
13438 return result;
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 return m_it.array_iterator - other.m_it.array_iterator;
13456
13457 case value_t::null:
13458 case value_t::string:
13459 case value_t::boolean:
13463 case value_t::binary:
13464 case value_t::discarded:
13465 default:
13467 }
13468 }
13469
13475 {
13476 JSON_ASSERT(m_object != nullptr);
13477
13478 switch (m_object->m_data.m_type)
13479 {
13480 case value_t::object:
13481 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
13482
13483 case value_t::array:
13484 return *std::next(m_it.array_iterator, n);
13485
13486 case value_t::null:
13487 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13488
13489 case value_t::string:
13490 case value_t::boolean:
13494 case value_t::binary:
13495 case value_t::discarded:
13496 default:
13497 {
13498 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
13499 {
13500 return *m_object;
13501 }
13502
13503 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13504 }
13505 }
13506 }
13507
13512 const typename object_t::key_type& key() const
13513 {
13514 JSON_ASSERT(m_object != nullptr);
13515
13516 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
13517 {
13518 return m_it.object_iterator->first;
13519 }
13520
13521 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
13522 }
13523
13529 {
13530 return operator*();
13531 }
13532
13535 pointer m_object = nullptr;
13538};
13539
13540} // namespace detail
13542
13543// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
13544
13545// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
13546// __ _____ _____ _____
13547// __| | __| | | | JSON for Modern C++
13548// | | |__ | | | | | | version 3.11.2
13549// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13550//
13551// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
13552// SPDX-License-Identifier: MIT
13553
13554
13555
13556#include <cstddef> // ptrdiff_t
13557#include <iterator> // reverse_iterator
13558#include <utility> // declval
13559
13560// #include <nlohmann/detail/abi_macros.hpp>
13561
13562
13564namespace detail
13565{
13566
13568// reverse_iterator //
13570
13589template<typename Base>
13590class json_reverse_iterator : public std::reverse_iterator<Base>
13591{
13592 public:
13593 using difference_type = std::ptrdiff_t;
13595 using base_iterator = std::reverse_iterator<Base>;
13597 using reference = typename Base::reference;
13598
13600 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13601 : base_iterator(it) {}
13602
13604 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13605
13607 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
13608 {
13609 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13610 }
13611
13614 {
13615 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13616 }
13617
13619 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
13620 {
13621 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13622 }
13623
13626 {
13627 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13628 }
13629
13632 {
13633 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13634 }
13635
13638 {
13639 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13640 }
13641
13644 {
13645 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13646 }
13647
13650 {
13651 return base_iterator(*this) - base_iterator(other);
13652 }
13653
13656 {
13657 return *(this->operator+(n));
13658 }
13659
13661 auto key() const -> decltype(std::declval<Base>().key())
13662 {
13663 auto it = --this->base();
13664 return it.key();
13665 }
13666
13669 {
13670 auto it = --this->base();
13671 return it.operator * ();
13672 }
13673};
13674
13675} // namespace detail
13677
13678// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13679
13680// #include <nlohmann/detail/json_custom_base_class.hpp>
13681
13682
13683#include <type_traits> // conditional, is_same
13684
13685// #include <nlohmann/detail/abi_macros.hpp>
13686
13687
13689namespace detail
13690{
13691
13703
13704template<class T>
13705using json_base_class = typename std::conditional <
13706 std::is_same<T, void>::value,
13708 T
13709 >::type;
13710
13711} // namespace detail
13713
13714// #include <nlohmann/detail/json_pointer.hpp>
13715// __ _____ _____ _____
13716// __| | __| | | | JSON for Modern C++
13717// | | |__ | | | | | | version 3.11.2
13718// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13719//
13720// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
13721// SPDX-License-Identifier: MIT
13722
13723
13724
13725#include <algorithm> // all_of
13726#include <cctype> // isdigit
13727#include <cerrno> // errno, ERANGE
13728#include <cstdlib> // strtoull
13729#ifndef JSON_NO_IO
13730 #include <iosfwd> // ostream
13731#endif // JSON_NO_IO
13732#include <limits> // max
13733#include <numeric> // accumulate
13734#include <string> // string
13735#include <utility> // move
13736#include <vector> // vector
13737
13738// #include <nlohmann/detail/exceptions.hpp>
13739
13740// #include <nlohmann/detail/macro_scope.hpp>
13741
13742// #include <nlohmann/detail/string_concat.hpp>
13743
13744// #include <nlohmann/detail/string_escape.hpp>
13745
13746// #include <nlohmann/detail/value_t.hpp>
13747
13748
13750
13753template<typename RefStringType>
13755{
13756 // allow basic_json to access private members
13758 friend class basic_json;
13759
13760 template<typename>
13761 friend class json_pointer;
13762
13763 template<typename T>
13764 struct string_t_helper
13765 {
13766 using type = T;
13767 };
13768
13770 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
13771 {
13772 using type = StringType;
13773 };
13774
13775 public:
13776 // for backwards compatibility accept BasicJsonType
13777 using string_t = typename string_t_helper<RefStringType>::type;
13778
13781 explicit json_pointer(const string_t& s = "")
13782 : reference_tokens(split(s))
13783 {}
13784
13788 {
13789 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
13790 string_t{},
13791 [](const string_t& a, const string_t& b)
13792 {
13793 return detail::concat(a, '/', detail::escape(b));
13794 });
13795 }
13796
13800 operator string_t() const
13801 {
13802 return to_string();
13803 }
13804
13805#ifndef JSON_NO_IO
13808 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
13809 {
13810 o << ptr.to_string();
13811 return o;
13812 }
13813#endif
13814
13818 {
13819 reference_tokens.insert(reference_tokens.end(),
13820 ptr.reference_tokens.begin(),
13821 ptr.reference_tokens.end());
13822 return *this;
13823 }
13824
13828 {
13829 push_back(std::move(token));
13830 return *this;
13831 }
13832
13835 json_pointer& operator/=(std::size_t array_idx)
13836 {
13837 return *this /= std::to_string(array_idx);
13838 }
13839
13843 const json_pointer& rhs)
13844 {
13845 return json_pointer(lhs) /= rhs;
13846 }
13847
13850 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
13851 {
13852 return json_pointer(lhs) /= std::move(token);
13853 }
13854
13857 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
13858 {
13859 return json_pointer(lhs) /= array_idx;
13860 }
13861
13865 {
13866 if (empty())
13867 {
13868 return *this;
13869 }
13870
13871 json_pointer res = *this;
13872 res.pop_back();
13873 return res;
13874 }
13875
13879 {
13881 {
13882 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13883 }
13884
13885 reference_tokens.pop_back();
13886 }
13887
13890 const string_t& back() const
13891 {
13893 {
13894 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13895 }
13896
13897 return reference_tokens.back();
13898 }
13899
13902 void push_back(const string_t& token)
13903 {
13904 reference_tokens.push_back(token);
13905 }
13906
13909 void push_back(string_t&& token)
13910 {
13911 reference_tokens.push_back(std::move(token));
13912 }
13913
13916 bool empty() const noexcept
13917 {
13918 return reference_tokens.empty();
13919 }
13920
13921 private:
13932 template<typename BasicJsonType>
13933 static typename BasicJsonType::size_type array_index(const string_t& s)
13934 {
13935 using size_type = typename BasicJsonType::size_type;
13936
13937 // error condition (cf. RFC 6901, Sect. 4)
13938 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
13939 {
13940 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
13941 }
13942
13943 // error condition (cf. RFC 6901, Sect. 4)
13944 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
13945 {
13946 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
13947 }
13948
13949 const char* p = s.c_str();
13950 char* p_end = nullptr;
13951 errno = 0; // strtoull doesn't reset errno
13952 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
13953 if (p == p_end // invalid input or empty string
13954 || errno == ERANGE // out of range
13955 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
13956 {
13957 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
13958 }
13959
13960 // only triggered on special platforms (like 32bit), see also
13961 // https://github.com/nlohmann/json/pull/2203
13962 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
13963 {
13964 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
13965 }
13966
13967 return static_cast<size_type>(res);
13968 }
13969
13971 json_pointer top() const
13972 {
13974 {
13975 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13976 }
13977
13978 json_pointer result = *this;
13979 result.reference_tokens = {reference_tokens[0]};
13980 return result;
13981 }
13982
13983 private:
13992 template<typename BasicJsonType>
13993 BasicJsonType& get_and_create(BasicJsonType& j) const
13994 {
13995 auto* result = &j;
13996
13997 // in case no reference tokens exist, return a reference to the JSON value
13998 // j which will be overwritten by a primitive value
13999 for (const auto& reference_token : reference_tokens)
14000 {
14001 switch (result->type())
14002 {
14004 {
14005 if (reference_token == "0")
14006 {
14007 // start a new array if reference token is 0
14008 result = &result->operator[](0);
14009 }
14010 else
14011 {
14012 // start a new object otherwise
14013 result = &result->operator[](reference_token);
14014 }
14015 break;
14016 }
14017
14019 {
14020 // create an entry in the object
14021 result = &result->operator[](reference_token);
14022 break;
14023 }
14024
14026 {
14027 // create an entry in the array
14028 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14029 break;
14030 }
14031
14032 /*
14033 The following code is only reached if there exists a reference
14034 token _and_ the current value is primitive. In this case, we have
14035 an error situation, because primitive values may only occur as
14036 single value; that is, with an empty list of reference tokens.
14037 */
14045 default:
14046 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14047 }
14048 }
14049
14050 return *result;
14051 }
14052
14072 template<typename BasicJsonType>
14073 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14074 {
14075 for (const auto& reference_token : reference_tokens)
14076 {
14077 // convert null values to arrays or objects before continuing
14078 if (ptr->is_null())
14079 {
14080 // check if reference token is a number
14081 const bool nums =
14082 std::all_of(reference_token.begin(), reference_token.end(),
14083 [](const unsigned char x)
14084 {
14085 return std::isdigit(x);
14086 });
14087
14088 // change value to array for numbers or "-" or to object otherwise
14089 *ptr = (nums || reference_token == "-")
14091 : detail::value_t::object;
14092 }
14093
14094 switch (ptr->type())
14095 {
14097 {
14098 // use unchecked object access
14099 ptr = &ptr->operator[](reference_token);
14100 break;
14101 }
14102
14104 {
14105 if (reference_token == "-")
14106 {
14107 // explicitly treat "-" as index beyond the end
14108 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14109 }
14110 else
14111 {
14112 // convert array index to number; unchecked access
14113 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14114 }
14115 break;
14116 }
14117
14126 default:
14127 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14128 }
14129 }
14130
14131 return *ptr;
14132 }
14133
14140 template<typename BasicJsonType>
14141 BasicJsonType& get_checked(BasicJsonType* ptr) const
14142 {
14143 for (const auto& reference_token : reference_tokens)
14144 {
14145 switch (ptr->type())
14146 {
14148 {
14149 // note: at performs range check
14150 ptr = &ptr->at(reference_token);
14151 break;
14152 }
14153
14155 {
14156 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14157 {
14158 // "-" always fails the range check
14160 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14161 ") is out of range"), ptr));
14162 }
14163
14164 // note: at performs range check
14165 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14166 break;
14167 }
14168
14177 default:
14178 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14179 }
14180 }
14181
14182 return *ptr;
14183 }
14184
14198 template<typename BasicJsonType>
14199 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
14200 {
14201 for (const auto& reference_token : reference_tokens)
14202 {
14203 switch (ptr->type())
14204 {
14206 {
14207 // use unchecked object access
14208 ptr = &ptr->operator[](reference_token);
14209 break;
14210 }
14211
14213 {
14214 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14215 {
14216 // "-" cannot be used for const access
14217 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));
14218 }
14219
14220 // use unchecked array access
14221 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14222 break;
14223 }
14224
14233 default:
14234 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14235 }
14236 }
14237
14238 return *ptr;
14239 }
14240
14247 template<typename BasicJsonType>
14248 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
14249 {
14250 for (const auto& reference_token : reference_tokens)
14251 {
14252 switch (ptr->type())
14253 {
14255 {
14256 // note: at performs range check
14257 ptr = &ptr->at(reference_token);
14258 break;
14259 }
14260
14262 {
14263 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14264 {
14265 // "-" always fails the range check
14267 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14268 ") is out of range"), ptr));
14269 }
14270
14271 // note: at performs range check
14272 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14273 break;
14274 }
14275
14284 default:
14285 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14286 }
14287 }
14288
14289 return *ptr;
14290 }
14291
14296 template<typename BasicJsonType>
14297 bool contains(const BasicJsonType* ptr) const
14298 {
14299 for (const auto& reference_token : reference_tokens)
14300 {
14301 switch (ptr->type())
14302 {
14304 {
14305 if (!ptr->contains(reference_token))
14306 {
14307 // we did not find the key in the object
14308 return false;
14309 }
14310
14311 ptr = &ptr->operator[](reference_token);
14312 break;
14313 }
14314
14316 {
14317 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14318 {
14319 // "-" always fails the range check
14320 return false;
14321 }
14322 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
14323 {
14324 // invalid char
14325 return false;
14326 }
14327 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
14328 {
14329 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
14330 {
14331 // first char should be between '1' and '9'
14332 return false;
14333 }
14334 for (std::size_t i = 1; i < reference_token.size(); i++)
14335 {
14336 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
14337 {
14338 // other char should be between '0' and '9'
14339 return false;
14340 }
14341 }
14342 }
14343
14344 const auto idx = array_index<BasicJsonType>(reference_token);
14345 if (idx >= ptr->size())
14346 {
14347 // index out of range
14348 return false;
14349 }
14350
14351 ptr = &ptr->operator[](idx);
14352 break;
14353 }
14354
14363 default:
14364 {
14365 // we do not expect primitive values if there is still a
14366 // reference token to process
14367 return false;
14368 }
14369 }
14370 }
14371
14372 // no reference token left means we found a primitive value
14373 return true;
14374 }
14375
14385 static std::vector<string_t> split(const string_t& reference_string)
14386 {
14387 std::vector<string_t> result;
14388
14389 // special case: empty reference string -> no reference tokens
14390 if (reference_string.empty())
14391 {
14392 return result;
14393 }
14394
14395 // check if nonempty reference string begins with slash
14396 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
14397 {
14398 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
14399 }
14400
14401 // extract the reference tokens:
14402 // - slash: position of the last read slash (or end of string)
14403 // - start: position after the previous slash
14404 for (
14405 // search for the first slash after the first character
14406 std::size_t slash = reference_string.find_first_of('/', 1),
14407 // set the beginning of the first reference token
14408 start = 1;
14409 // we can stop if start == 0 (if slash == string_t::npos)
14410 start != 0;
14411 // set the beginning of the next reference token
14412 // (will eventually be 0 if slash == string_t::npos)
14413 start = (slash == string_t::npos) ? 0 : slash + 1,
14414 // find next slash
14415 slash = reference_string.find_first_of('/', start))
14416 {
14417 // use the text between the beginning of the reference token
14418 // (start) and the last slash (slash).
14419 auto reference_token = reference_string.substr(start, slash - start);
14420
14421 // check reference tokens are properly escaped
14422 for (std::size_t pos = reference_token.find_first_of('~');
14423 pos != string_t::npos;
14424 pos = reference_token.find_first_of('~', pos + 1))
14425 {
14426 JSON_ASSERT(reference_token[pos] == '~');
14427
14428 // ~ must be followed by 0 or 1
14429 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
14430 (reference_token[pos + 1] != '0' &&
14431 reference_token[pos + 1] != '1')))
14432 {
14433 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
14434 }
14435 }
14436
14437 // finally, store the reference token
14438 detail::unescape(reference_token);
14439 result.push_back(reference_token);
14440 }
14441
14442 return result;
14443 }
14444
14445 private:
14453 template<typename BasicJsonType>
14454 static void flatten(const string_t& reference_string,
14455 const BasicJsonType& value,
14456 BasicJsonType& result)
14457 {
14458 switch (value.type())
14459 {
14461 {
14462 if (value.m_data.m_value.array->empty())
14463 {
14464 // flatten empty array as null
14465 result[reference_string] = nullptr;
14466 }
14467 else
14468 {
14469 // iterate array and use index as reference string
14470 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
14471 {
14472 flatten(detail::concat(reference_string, '/', std::to_string(i)),
14473 value.m_data.m_value.array->operator[](i), result);
14474 }
14475 }
14476 break;
14477 }
14478
14480 {
14481 if (value.m_data.m_value.object->empty())
14482 {
14483 // flatten empty object as null
14484 result[reference_string] = nullptr;
14485 }
14486 else
14487 {
14488 // iterate object and use keys as reference string
14489 for (const auto& element : *value.m_data.m_value.object)
14490 {
14491 flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
14492 }
14493 }
14494 break;
14495 }
14496
14505 default:
14506 {
14507 // add primitive value with its reference string
14508 result[reference_string] = value;
14509 break;
14510 }
14511 }
14512 }
14513
14524 template<typename BasicJsonType>
14525 static BasicJsonType
14526 unflatten(const BasicJsonType& value)
14527 {
14528 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
14529 {
14530 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
14531 }
14532
14533 BasicJsonType result;
14534
14535 // iterate the JSON object values
14536 for (const auto& element : *value.m_data.m_value.object)
14537 {
14538 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
14539 {
14540 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
14541 }
14542
14543 // assign value to reference pointed to by JSON pointer; Note that if
14544 // the JSON pointer is "" (i.e., points to the whole value), function
14545 // get_and_create returns a reference to result itself. An assignment
14546 // will then create a primitive value.
14547 json_pointer(element.first).get_and_create(result) = element.second;
14548 }
14549
14550 return result;
14551 }
14552
14553 // can't use conversion operator because of ambiguity
14554 json_pointer<string_t> convert() const&
14555 {
14557 result.reference_tokens = reference_tokens;
14558 return result;
14559 }
14560
14561 json_pointer<string_t> convert()&&
14562 {
14564 result.reference_tokens = std::move(reference_tokens);
14565 return result;
14566 }
14567
14568 public:
14569#if JSON_HAS_THREE_WAY_COMPARISON
14572 template<typename RefStringTypeRhs>
14573 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
14574 {
14575 return reference_tokens == rhs.reference_tokens;
14576 }
14577
14580 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
14581 bool operator==(const string_t& rhs) const
14582 {
14583 return *this == json_pointer(rhs);
14584 }
14585
14587 template<typename RefStringTypeRhs>
14588 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
14589 {
14590 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
14591 }
14592#else
14595 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14596 // NOLINTNEXTLINE(readability-redundant-declaration)
14597 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14598 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14599
14602 template<typename RefStringTypeLhs, typename StringType>
14603 // NOLINTNEXTLINE(readability-redundant-declaration)
14604 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14605 const StringType& rhs);
14606
14609 template<typename RefStringTypeRhs, typename StringType>
14610 // NOLINTNEXTLINE(readability-redundant-declaration)
14611 friend bool operator==(const StringType& lhs,
14613
14616 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14617 // NOLINTNEXTLINE(readability-redundant-declaration)
14618 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14619 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14620
14623 template<typename RefStringTypeLhs, typename StringType>
14624 // NOLINTNEXTLINE(readability-redundant-declaration)
14625 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14626 const StringType& rhs);
14627
14630 template<typename RefStringTypeRhs, typename StringType>
14631 // NOLINTNEXTLINE(readability-redundant-declaration)
14632 friend bool operator!=(const StringType& lhs,
14634
14636 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14637 // NOLINTNEXTLINE(readability-redundant-declaration)
14638 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14639 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14640#endif
14641
14642 private:
14644 std::vector<string_t> reference_tokens;
14645};
14646
14647#if !JSON_HAS_THREE_WAY_COMPARISON
14648// functions cannot be defined inside class due to ODR violations
14649template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14651 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14652{
14653 return lhs.reference_tokens == rhs.reference_tokens;
14654}
14655
14656template<typename RefStringTypeLhs,
14657 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14659inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14660 const StringType& rhs)
14661{
14662 return lhs == json_pointer<RefStringTypeLhs>(rhs);
14663}
14664
14665template<typename RefStringTypeRhs,
14666 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14668inline bool operator==(const StringType& lhs,
14669 const json_pointer<RefStringTypeRhs>& rhs)
14670{
14671 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
14672}
14673
14674template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14676 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14677{
14678 return !(lhs == rhs);
14679}
14680
14681template<typename RefStringTypeLhs,
14682 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14684inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14685 const StringType& rhs)
14686{
14687 return !(lhs == rhs);
14688}
14689
14690template<typename RefStringTypeRhs,
14691 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14693inline bool operator!=(const StringType& lhs,
14694 const json_pointer<RefStringTypeRhs>& rhs)
14695{
14696 return !(lhs == rhs);
14697}
14698
14699template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14701 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14702{
14703 return lhs.reference_tokens < rhs.reference_tokens;
14704}
14705#endif
14706
14708
14709// #include <nlohmann/detail/json_ref.hpp>
14710// __ _____ _____ _____
14711// __| | __| | | | JSON for Modern C++
14712// | | |__ | | | | | | version 3.11.2
14713// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14714//
14715// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
14716// SPDX-License-Identifier: MIT
14717
14718
14719
14720#include <initializer_list>
14721#include <utility>
14722
14723// #include <nlohmann/detail/abi_macros.hpp>
14724
14725// #include <nlohmann/detail/meta/type_traits.hpp>
14726
14727
14729namespace detail
14730{
14731
14732template<typename BasicJsonType>
14734{
14735 public:
14736 using value_type = BasicJsonType;
14737
14739 : owned_value(std::move(value))
14740 {}
14741
14742 json_ref(const value_type& value)
14743 : value_ref(&value)
14744 {}
14745
14746 json_ref(std::initializer_list<json_ref> init)
14747 : owned_value(init)
14748 {}
14749
14750 template <
14751 class... Args,
14752 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
14753 json_ref(Args && ... args)
14754 : owned_value(std::forward<Args>(args)...)
14755 {}
14756
14757 // class should be movable only
14758 json_ref(json_ref&&) noexcept = default;
14759 json_ref(const json_ref&) = delete;
14760 json_ref& operator=(const json_ref&) = delete;
14761 json_ref& operator=(json_ref&&) = delete;
14762 ~json_ref() = default;
14763
14765 {
14766 if (value_ref == nullptr)
14767 {
14768 return std::move(owned_value);
14769 }
14770 return *value_ref;
14771 }
14772
14773 value_type const& operator*() const
14774 {
14775 return value_ref ? *value_ref : owned_value;
14776 }
14777
14778 value_type const* operator->() const
14779 {
14780 return &** this;
14781 }
14782
14783 private:
14784 mutable value_type owned_value = nullptr;
14785 value_type const* value_ref = nullptr;
14786};
14787
14788} // namespace detail
14790
14791// #include <nlohmann/detail/macro_scope.hpp>
14792
14793// #include <nlohmann/detail/string_concat.hpp>
14794
14795// #include <nlohmann/detail/string_escape.hpp>
14796
14797// #include <nlohmann/detail/meta/cpp_future.hpp>
14798
14799// #include <nlohmann/detail/meta/type_traits.hpp>
14800
14801// #include <nlohmann/detail/output/binary_writer.hpp>
14802// __ _____ _____ _____
14803// __| | __| | | | JSON for Modern C++
14804// | | |__ | | | | | | version 3.11.2
14805// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14806//
14807// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
14808// SPDX-License-Identifier: MIT
14809
14810
14811
14812#include <algorithm> // reverse
14813#include <array> // array
14814#include <map> // map
14815#include <cmath> // isnan, isinf
14816#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
14817#include <cstring> // memcpy
14818#include <limits> // numeric_limits
14819#include <string> // string
14820#include <utility> // move
14821#include <vector> // vector
14822
14823// #include <nlohmann/detail/input/binary_reader.hpp>
14824
14825// #include <nlohmann/detail/macro_scope.hpp>
14826
14827// #include <nlohmann/detail/output/output_adapters.hpp>
14828// __ _____ _____ _____
14829// __| | __| | | | JSON for Modern C++
14830// | | |__ | | | | | | version 3.11.2
14831// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14832//
14833// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
14834// SPDX-License-Identifier: MIT
14835
14836
14837
14838#include <algorithm> // copy
14839#include <cstddef> // size_t
14840#include <iterator> // back_inserter
14841#include <memory> // shared_ptr, make_shared
14842#include <string> // basic_string
14843#include <vector> // vector
14844
14845#ifndef JSON_NO_IO
14846 #include <ios> // streamsize
14847 #include <ostream> // basic_ostream
14848#endif // JSON_NO_IO
14849
14850// #include <nlohmann/detail/macro_scope.hpp>
14851
14852
14854namespace detail
14855{
14856
14858template<typename CharType> struct output_adapter_protocol
14859{
14860 virtual void write_character(CharType c) = 0;
14861 virtual void write_characters(const CharType* s, std::size_t length) = 0;
14862 virtual ~output_adapter_protocol() = default;
14863
14864 output_adapter_protocol() = default;
14865 output_adapter_protocol(const output_adapter_protocol&) = default;
14866 output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
14867 output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
14868 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
14869};
14870
14872template<typename CharType>
14873using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
14874
14876template<typename CharType, typename AllocatorType = std::allocator<CharType>>
14877class output_vector_adapter : public output_adapter_protocol<CharType>
14878{
14879 public:
14880 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
14881 : v(vec)
14882 {}
14883
14884 void write_character(CharType c) override
14885 {
14886 v.push_back(c);
14887 }
14888
14890 void write_characters(const CharType* s, std::size_t length) override
14891 {
14892 v.insert(v.end(), s, s + length);
14893 }
14894
14895 private:
14896 std::vector<CharType, AllocatorType>& v;
14897};
14898
14899#ifndef JSON_NO_IO
14901template<typename CharType>
14902class output_stream_adapter : public output_adapter_protocol<CharType>
14903{
14904 public:
14905 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
14906 : stream(s)
14907 {}
14908
14909 void write_character(CharType c) override
14910 {
14911 stream.put(c);
14912 }
14913
14915 void write_characters(const CharType* s, std::size_t length) override
14916 {
14917 stream.write(s, static_cast<std::streamsize>(length));
14918 }
14919
14920 private:
14921 std::basic_ostream<CharType>& stream;
14922};
14923#endif // JSON_NO_IO
14924
14926template<typename CharType, typename StringType = std::basic_string<CharType>>
14927class output_string_adapter : public output_adapter_protocol<CharType>
14928{
14929 public:
14930 explicit output_string_adapter(StringType& s) noexcept
14931 : str(s)
14932 {}
14933
14934 void write_character(CharType c) override
14935 {
14936 str.push_back(c);
14937 }
14938
14940 void write_characters(const CharType* s, std::size_t length) override
14941 {
14942 str.append(s, length);
14943 }
14944
14945 private:
14946 StringType& str;
14947};
14948
14949template<typename CharType, typename StringType = std::basic_string<CharType>>
14950class output_adapter
14951{
14952 public:
14953 template<typename AllocatorType = std::allocator<CharType>>
14954 output_adapter(std::vector<CharType, AllocatorType>& vec)
14955 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
14956
14957#ifndef JSON_NO_IO
14958 output_adapter(std::basic_ostream<CharType>& s)
14959 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
14960#endif // JSON_NO_IO
14961
14962 output_adapter(StringType& s)
14963 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
14964
14965 operator output_adapter_t<CharType>()
14966 {
14967 return oa;
14968 }
14969
14970 private:
14971 output_adapter_t<CharType> oa = nullptr;
14972};
14973
14974} // namespace detail
14976
14977// #include <nlohmann/detail/string_concat.hpp>
14978
14979
14981namespace detail
14982{
14983
14985// binary writer //
14987
14991template<typename BasicJsonType, typename CharType>
14992class binary_writer
14993{
14994 using string_t = typename BasicJsonType::string_t;
14995 using binary_t = typename BasicJsonType::binary_t;
14996 using number_float_t = typename BasicJsonType::number_float_t;
14997
14998 public:
15004 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15005 {
15006 JSON_ASSERT(oa);
15007 }
15008
15013 void write_bson(const BasicJsonType& j)
15014 {
15015 switch (j.type())
15016 {
15017 case value_t::object:
15018 {
15019 write_bson_object(*j.m_data.m_value.object);
15020 break;
15021 }
15022
15023 case value_t::null:
15024 case value_t::array:
15025 case value_t::string:
15026 case value_t::boolean:
15027 case value_t::number_integer:
15028 case value_t::number_unsigned:
15029 case value_t::number_float:
15030 case value_t::binary:
15031 case value_t::discarded:
15032 default:
15033 {
15034 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15035 }
15036 }
15037 }
15038
15042 void write_cbor(const BasicJsonType& j)
15043 {
15044 switch (j.type())
15045 {
15046 case value_t::null:
15047 {
15048 oa->write_character(to_char_type(0xF6));
15049 break;
15050 }
15051
15052 case value_t::boolean:
15053 {
15054 oa->write_character(j.m_data.m_value.boolean
15055 ? to_char_type(0xF5)
15056 : to_char_type(0xF4));
15057 break;
15058 }
15059
15060 case value_t::number_integer:
15061 {
15062 if (j.m_data.m_value.number_integer >= 0)
15063 {
15064 // CBOR does not differentiate between positive signed
15065 // integers and unsigned integers. Therefore, we used the
15066 // code from the value_t::number_unsigned case here.
15067 if (j.m_data.m_value.number_integer <= 0x17)
15068 {
15069 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15070 }
15071 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15072 {
15073 oa->write_character(to_char_type(0x18));
15074 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15075 }
15076 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15077 {
15078 oa->write_character(to_char_type(0x19));
15079 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15080 }
15081 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15082 {
15083 oa->write_character(to_char_type(0x1A));
15084 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15085 }
15086 else
15087 {
15088 oa->write_character(to_char_type(0x1B));
15089 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15090 }
15091 }
15092 else
15093 {
15094 // The conversions below encode the sign in the first
15095 // byte, and the value is converted to a positive number.
15096 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15097 if (j.m_data.m_value.number_integer >= -24)
15098 {
15099 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15100 }
15101 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15102 {
15103 oa->write_character(to_char_type(0x38));
15104 write_number(static_cast<std::uint8_t>(positive_number));
15105 }
15106 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15107 {
15108 oa->write_character(to_char_type(0x39));
15109 write_number(static_cast<std::uint16_t>(positive_number));
15110 }
15111 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15112 {
15113 oa->write_character(to_char_type(0x3A));
15114 write_number(static_cast<std::uint32_t>(positive_number));
15115 }
15116 else
15117 {
15118 oa->write_character(to_char_type(0x3B));
15119 write_number(static_cast<std::uint64_t>(positive_number));
15120 }
15121 }
15122 break;
15123 }
15124
15125 case value_t::number_unsigned:
15126 {
15127 if (j.m_data.m_value.number_unsigned <= 0x17)
15128 {
15129 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15130 }
15131 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15132 {
15133 oa->write_character(to_char_type(0x18));
15134 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15135 }
15136 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15137 {
15138 oa->write_character(to_char_type(0x19));
15139 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15140 }
15141 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15142 {
15143 oa->write_character(to_char_type(0x1A));
15144 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15145 }
15146 else
15147 {
15148 oa->write_character(to_char_type(0x1B));
15149 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15150 }
15151 break;
15152 }
15153
15154 case value_t::number_float:
15155 {
15156 if (std::isnan(j.m_data.m_value.number_float))
15157 {
15158 // NaN is 0xf97e00 in CBOR
15159 oa->write_character(to_char_type(0xF9));
15160 oa->write_character(to_char_type(0x7E));
15161 oa->write_character(to_char_type(0x00));
15162 }
15163 else if (std::isinf(j.m_data.m_value.number_float))
15164 {
15165 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
15166 oa->write_character(to_char_type(0xf9));
15167 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15168 oa->write_character(to_char_type(0x00));
15169 }
15170 else
15171 {
15172 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15173 }
15174 break;
15175 }
15176
15177 case value_t::string:
15178 {
15179 // step 1: write control byte and the string length
15180 const auto N = j.m_data.m_value.string->size();
15181 if (N <= 0x17)
15182 {
15183 write_number(static_cast<std::uint8_t>(0x60 + N));
15184 }
15185 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15186 {
15187 oa->write_character(to_char_type(0x78));
15188 write_number(static_cast<std::uint8_t>(N));
15189 }
15190 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15191 {
15192 oa->write_character(to_char_type(0x79));
15193 write_number(static_cast<std::uint16_t>(N));
15194 }
15195 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15196 {
15197 oa->write_character(to_char_type(0x7A));
15198 write_number(static_cast<std::uint32_t>(N));
15199 }
15200 // LCOV_EXCL_START
15201 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15202 {
15203 oa->write_character(to_char_type(0x7B));
15204 write_number(static_cast<std::uint64_t>(N));
15205 }
15206 // LCOV_EXCL_STOP
15207
15208 // step 2: write the string
15209 oa->write_characters(
15210 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15211 j.m_data.m_value.string->size());
15212 break;
15213 }
15214
15215 case value_t::array:
15216 {
15217 // step 1: write control byte and the array size
15218 const auto N = j.m_data.m_value.array->size();
15219 if (N <= 0x17)
15220 {
15221 write_number(static_cast<std::uint8_t>(0x80 + N));
15222 }
15223 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15224 {
15225 oa->write_character(to_char_type(0x98));
15226 write_number(static_cast<std::uint8_t>(N));
15227 }
15228 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15229 {
15230 oa->write_character(to_char_type(0x99));
15231 write_number(static_cast<std::uint16_t>(N));
15232 }
15233 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15234 {
15235 oa->write_character(to_char_type(0x9A));
15236 write_number(static_cast<std::uint32_t>(N));
15237 }
15238 // LCOV_EXCL_START
15239 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15240 {
15241 oa->write_character(to_char_type(0x9B));
15242 write_number(static_cast<std::uint64_t>(N));
15243 }
15244 // LCOV_EXCL_STOP
15245
15246 // step 2: write each element
15247 for (const auto& el : *j.m_data.m_value.array)
15248 {
15249 write_cbor(el);
15250 }
15251 break;
15252 }
15253
15254 case value_t::binary:
15255 {
15256 if (j.m_data.m_value.binary->has_subtype())
15257 {
15258 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
15259 {
15260 write_number(static_cast<std::uint8_t>(0xd8));
15261 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
15262 }
15263 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
15264 {
15265 write_number(static_cast<std::uint8_t>(0xd9));
15266 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
15267 }
15268 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
15269 {
15270 write_number(static_cast<std::uint8_t>(0xda));
15271 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
15272 }
15273 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
15274 {
15275 write_number(static_cast<std::uint8_t>(0xdb));
15276 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
15277 }
15278 }
15279
15280 // step 1: write control byte and the binary array size
15281 const auto N = j.m_data.m_value.binary->size();
15282 if (N <= 0x17)
15283 {
15284 write_number(static_cast<std::uint8_t>(0x40 + N));
15285 }
15286 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15287 {
15288 oa->write_character(to_char_type(0x58));
15289 write_number(static_cast<std::uint8_t>(N));
15290 }
15291 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15292 {
15293 oa->write_character(to_char_type(0x59));
15294 write_number(static_cast<std::uint16_t>(N));
15295 }
15296 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15297 {
15298 oa->write_character(to_char_type(0x5A));
15299 write_number(static_cast<std::uint32_t>(N));
15300 }
15301 // LCOV_EXCL_START
15302 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15303 {
15304 oa->write_character(to_char_type(0x5B));
15305 write_number(static_cast<std::uint64_t>(N));
15306 }
15307 // LCOV_EXCL_STOP
15308
15309 // step 2: write each element
15310 oa->write_characters(
15311 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15312 N);
15313
15314 break;
15315 }
15316
15317 case value_t::object:
15318 {
15319 // step 1: write control byte and the object size
15320 const auto N = j.m_data.m_value.object->size();
15321 if (N <= 0x17)
15322 {
15323 write_number(static_cast<std::uint8_t>(0xA0 + N));
15324 }
15325 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15326 {
15327 oa->write_character(to_char_type(0xB8));
15328 write_number(static_cast<std::uint8_t>(N));
15329 }
15330 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15331 {
15332 oa->write_character(to_char_type(0xB9));
15333 write_number(static_cast<std::uint16_t>(N));
15334 }
15335 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15336 {
15337 oa->write_character(to_char_type(0xBA));
15338 write_number(static_cast<std::uint32_t>(N));
15339 }
15340 // LCOV_EXCL_START
15341 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15342 {
15343 oa->write_character(to_char_type(0xBB));
15344 write_number(static_cast<std::uint64_t>(N));
15345 }
15346 // LCOV_EXCL_STOP
15347
15348 // step 2: write each element
15349 for (const auto& el : *j.m_data.m_value.object)
15350 {
15351 write_cbor(el.first);
15352 write_cbor(el.second);
15353 }
15354 break;
15355 }
15356
15357 case value_t::discarded:
15358 default:
15359 break;
15360 }
15361 }
15362
15366 void write_msgpack(const BasicJsonType& j)
15367 {
15368 switch (j.type())
15369 {
15370 case value_t::null: // nil
15371 {
15372 oa->write_character(to_char_type(0xC0));
15373 break;
15374 }
15375
15376 case value_t::boolean: // true and false
15377 {
15378 oa->write_character(j.m_data.m_value.boolean
15379 ? to_char_type(0xC3)
15380 : to_char_type(0xC2));
15381 break;
15382 }
15383
15384 case value_t::number_integer:
15385 {
15386 if (j.m_data.m_value.number_integer >= 0)
15387 {
15388 // MessagePack does not differentiate between positive
15389 // signed integers and unsigned integers. Therefore, we used
15390 // the code from the value_t::number_unsigned case here.
15391 if (j.m_data.m_value.number_unsigned < 128)
15392 {
15393 // positive fixnum
15394 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15395 }
15396 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15397 {
15398 // uint 8
15399 oa->write_character(to_char_type(0xCC));
15400 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15401 }
15402 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15403 {
15404 // uint 16
15405 oa->write_character(to_char_type(0xCD));
15406 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15407 }
15408 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15409 {
15410 // uint 32
15411 oa->write_character(to_char_type(0xCE));
15412 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15413 }
15414 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15415 {
15416 // uint 64
15417 oa->write_character(to_char_type(0xCF));
15418 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15419 }
15420 }
15421 else
15422 {
15423 if (j.m_data.m_value.number_integer >= -32)
15424 {
15425 // negative fixnum
15426 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15427 }
15428 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
15429 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
15430 {
15431 // int 8
15432 oa->write_character(to_char_type(0xD0));
15433 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15434 }
15435 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
15436 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
15437 {
15438 // int 16
15439 oa->write_character(to_char_type(0xD1));
15440 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
15441 }
15442 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
15443 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
15444 {
15445 // int 32
15446 oa->write_character(to_char_type(0xD2));
15447 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
15448 }
15449 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
15450 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
15451 {
15452 // int 64
15453 oa->write_character(to_char_type(0xD3));
15454 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
15455 }
15456 }
15457 break;
15458 }
15459
15460 case value_t::number_unsigned:
15461 {
15462 if (j.m_data.m_value.number_unsigned < 128)
15463 {
15464 // positive fixnum
15465 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15466 }
15467 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15468 {
15469 // uint 8
15470 oa->write_character(to_char_type(0xCC));
15471 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15472 }
15473 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15474 {
15475 // uint 16
15476 oa->write_character(to_char_type(0xCD));
15477 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15478 }
15479 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15480 {
15481 // uint 32
15482 oa->write_character(to_char_type(0xCE));
15483 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15484 }
15485 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15486 {
15487 // uint 64
15488 oa->write_character(to_char_type(0xCF));
15489 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15490 }
15491 break;
15492 }
15493
15494 case value_t::number_float:
15495 {
15496 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
15497 break;
15498 }
15499
15500 case value_t::string:
15501 {
15502 // step 1: write control byte and the string length
15503 const auto N = j.m_data.m_value.string->size();
15504 if (N <= 31)
15505 {
15506 // fixstr
15507 write_number(static_cast<std::uint8_t>(0xA0 | N));
15508 }
15509 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15510 {
15511 // str 8
15512 oa->write_character(to_char_type(0xD9));
15513 write_number(static_cast<std::uint8_t>(N));
15514 }
15515 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15516 {
15517 // str 16
15518 oa->write_character(to_char_type(0xDA));
15519 write_number(static_cast<std::uint16_t>(N));
15520 }
15521 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15522 {
15523 // str 32
15524 oa->write_character(to_char_type(0xDB));
15525 write_number(static_cast<std::uint32_t>(N));
15526 }
15527
15528 // step 2: write the string
15529 oa->write_characters(
15530 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15531 j.m_data.m_value.string->size());
15532 break;
15533 }
15534
15535 case value_t::array:
15536 {
15537 // step 1: write control byte and the array size
15538 const auto N = j.m_data.m_value.array->size();
15539 if (N <= 15)
15540 {
15541 // fixarray
15542 write_number(static_cast<std::uint8_t>(0x90 | N));
15543 }
15544 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15545 {
15546 // array 16
15547 oa->write_character(to_char_type(0xDC));
15548 write_number(static_cast<std::uint16_t>(N));
15549 }
15550 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15551 {
15552 // array 32
15553 oa->write_character(to_char_type(0xDD));
15554 write_number(static_cast<std::uint32_t>(N));
15555 }
15556
15557 // step 2: write each element
15558 for (const auto& el : *j.m_data.m_value.array)
15559 {
15560 write_msgpack(el);
15561 }
15562 break;
15563 }
15564
15565 case value_t::binary:
15566 {
15567 // step 0: determine if the binary type has a set subtype to
15568 // determine whether or not to use the ext or fixext types
15569 const bool use_ext = j.m_data.m_value.binary->has_subtype();
15570
15571 // step 1: write control byte and the byte string length
15572 const auto N = j.m_data.m_value.binary->size();
15573 if (N <= (std::numeric_limits<std::uint8_t>::max)())
15574 {
15575 std::uint8_t output_type{};
15576 bool fixed = true;
15577 if (use_ext)
15578 {
15579 switch (N)
15580 {
15581 case 1:
15582 output_type = 0xD4; // fixext 1
15583 break;
15584 case 2:
15585 output_type = 0xD5; // fixext 2
15586 break;
15587 case 4:
15588 output_type = 0xD6; // fixext 4
15589 break;
15590 case 8:
15591 output_type = 0xD7; // fixext 8
15592 break;
15593 case 16:
15594 output_type = 0xD8; // fixext 16
15595 break;
15596 default:
15597 output_type = 0xC7; // ext 8
15598 fixed = false;
15599 break;
15600 }
15601
15602 }
15603 else
15604 {
15605 output_type = 0xC4; // bin 8
15606 fixed = false;
15607 }
15608
15609 oa->write_character(to_char_type(output_type));
15610 if (!fixed)
15611 {
15612 write_number(static_cast<std::uint8_t>(N));
15613 }
15614 }
15615 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15616 {
15617 const std::uint8_t output_type = use_ext
15618 ? 0xC8 // ext 16
15619 : 0xC5; // bin 16
15620
15621 oa->write_character(to_char_type(output_type));
15622 write_number(static_cast<std::uint16_t>(N));
15623 }
15624 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15625 {
15626 const std::uint8_t output_type = use_ext
15627 ? 0xC9 // ext 32
15628 : 0xC6; // bin 32
15629
15630 oa->write_character(to_char_type(output_type));
15631 write_number(static_cast<std::uint32_t>(N));
15632 }
15633
15634 // step 1.5: if this is an ext type, write the subtype
15635 if (use_ext)
15636 {
15637 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
15638 }
15639
15640 // step 2: write the byte string
15641 oa->write_characters(
15642 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15643 N);
15644
15645 break;
15646 }
15647
15648 case value_t::object:
15649 {
15650 // step 1: write control byte and the object size
15651 const auto N = j.m_data.m_value.object->size();
15652 if (N <= 15)
15653 {
15654 // fixmap
15655 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
15656 }
15657 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15658 {
15659 // map 16
15660 oa->write_character(to_char_type(0xDE));
15661 write_number(static_cast<std::uint16_t>(N));
15662 }
15663 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15664 {
15665 // map 32
15666 oa->write_character(to_char_type(0xDF));
15667 write_number(static_cast<std::uint32_t>(N));
15668 }
15669
15670 // step 2: write each element
15671 for (const auto& el : *j.m_data.m_value.object)
15672 {
15673 write_msgpack(el.first);
15674 write_msgpack(el.second);
15675 }
15676 break;
15677 }
15678
15679 case value_t::discarded:
15680 default:
15681 break;
15682 }
15683 }
15684
15692 void write_ubjson(const BasicJsonType& j, const bool use_count,
15693 const bool use_type, const bool add_prefix = true,
15694 const bool use_bjdata = false)
15695 {
15696 switch (j.type())
15697 {
15698 case value_t::null:
15699 {
15700 if (add_prefix)
15701 {
15702 oa->write_character(to_char_type('Z'));
15703 }
15704 break;
15705 }
15706
15707 case value_t::boolean:
15708 {
15709 if (add_prefix)
15710 {
15711 oa->write_character(j.m_data.m_value.boolean
15712 ? to_char_type('T')
15713 : to_char_type('F'));
15714 }
15715 break;
15716 }
15717
15718 case value_t::number_integer:
15719 {
15720 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
15721 break;
15722 }
15723
15724 case value_t::number_unsigned:
15725 {
15726 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
15727 break;
15728 }
15729
15730 case value_t::number_float:
15731 {
15732 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
15733 break;
15734 }
15735
15736 case value_t::string:
15737 {
15738 if (add_prefix)
15739 {
15740 oa->write_character(to_char_type('S'));
15741 }
15742 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
15743 oa->write_characters(
15744 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15745 j.m_data.m_value.string->size());
15746 break;
15747 }
15748
15749 case value_t::array:
15750 {
15751 if (add_prefix)
15752 {
15753 oa->write_character(to_char_type('['));
15754 }
15755
15756 bool prefix_required = true;
15757 if (use_type && !j.m_data.m_value.array->empty())
15758 {
15759 JSON_ASSERT(use_count);
15760 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15761 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
15762 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15763 {
15764 return ubjson_prefix(v, use_bjdata) == first_prefix;
15765 });
15766
15767 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15768
15769 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15770 {
15771 prefix_required = false;
15772 oa->write_character(to_char_type('$'));
15773 oa->write_character(first_prefix);
15774 }
15775 }
15776
15777 if (use_count)
15778 {
15779 oa->write_character(to_char_type('#'));
15780 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
15781 }
15782
15783 for (const auto& el : *j.m_data.m_value.array)
15784 {
15785 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
15786 }
15787
15788 if (!use_count)
15789 {
15790 oa->write_character(to_char_type(']'));
15791 }
15792
15793 break;
15794 }
15795
15796 case value_t::binary:
15797 {
15798 if (add_prefix)
15799 {
15800 oa->write_character(to_char_type('['));
15801 }
15802
15803 if (use_type && !j.m_data.m_value.binary->empty())
15804 {
15805 JSON_ASSERT(use_count);
15806 oa->write_character(to_char_type('$'));
15807 oa->write_character('U');
15808 }
15809
15810 if (use_count)
15811 {
15812 oa->write_character(to_char_type('#'));
15813 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
15814 }
15815
15816 if (use_type)
15817 {
15818 oa->write_characters(
15819 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15820 j.m_data.m_value.binary->size());
15821 }
15822 else
15823 {
15824 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
15825 {
15826 oa->write_character(to_char_type('U'));
15827 oa->write_character(j.m_data.m_value.binary->data()[i]);
15828 }
15829 }
15830
15831 if (!use_count)
15832 {
15833 oa->write_character(to_char_type(']'));
15834 }
15835
15836 break;
15837 }
15838
15839 case value_t::object:
15840 {
15841 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())
15842 {
15843 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)
15844 {
15845 break;
15846 }
15847 }
15848
15849 if (add_prefix)
15850 {
15851 oa->write_character(to_char_type('{'));
15852 }
15853
15854 bool prefix_required = true;
15855 if (use_type && !j.m_data.m_value.object->empty())
15856 {
15857 JSON_ASSERT(use_count);
15858 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15859 const bool same_prefix = std::all_of(j.begin(), j.end(),
15860 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15861 {
15862 return ubjson_prefix(v, use_bjdata) == first_prefix;
15863 });
15864
15865 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15866
15867 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15868 {
15869 prefix_required = false;
15870 oa->write_character(to_char_type('$'));
15871 oa->write_character(first_prefix);
15872 }
15873 }
15874
15875 if (use_count)
15876 {
15877 oa->write_character(to_char_type('#'));
15878 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
15879 }
15880
15881 for (const auto& el : *j.m_data.m_value.object)
15882 {
15883 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
15884 oa->write_characters(
15885 reinterpret_cast<const CharType*>(el.first.c_str()),
15886 el.first.size());
15887 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
15888 }
15889
15890 if (!use_count)
15891 {
15892 oa->write_character(to_char_type('}'));
15893 }
15894
15895 break;
15896 }
15897
15898 case value_t::discarded:
15899 default:
15900 break;
15901 }
15902 }
15903
15904 private:
15906 // BSON //
15908
15913 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
15914 {
15915 const auto it = name.find(static_cast<typename string_t::value_type>(0));
15916 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
15917 {
15918 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
15919 static_cast<void>(j);
15920 }
15921
15922 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
15923 }
15924
15928 void write_bson_entry_header(const string_t& name,
15929 const std::uint8_t element_type)
15930 {
15931 oa->write_character(to_char_type(element_type)); // boolean
15932 oa->write_characters(
15933 reinterpret_cast<const CharType*>(name.c_str()),
15934 name.size() + 1u);
15935 }
15936
15940 void write_bson_boolean(const string_t& name,
15941 const bool value)
15942 {
15943 write_bson_entry_header(name, 0x08);
15944 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
15945 }
15946
15950 void write_bson_double(const string_t& name,
15951 const double value)
15952 {
15953 write_bson_entry_header(name, 0x01);
15954 write_number<double>(value, true);
15955 }
15956
15960 static std::size_t calc_bson_string_size(const string_t& value)
15961 {
15962 return sizeof(std::int32_t) + value.size() + 1ul;
15963 }
15964
15968 void write_bson_string(const string_t& name,
15969 const string_t& value)
15970 {
15971 write_bson_entry_header(name, 0x02);
15972
15973 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
15974 oa->write_characters(
15975 reinterpret_cast<const CharType*>(value.c_str()),
15976 value.size() + 1);
15977 }
15978
15982 void write_bson_null(const string_t& name)
15983 {
15984 write_bson_entry_header(name, 0x0A);
15985 }
15986
15990 static std::size_t calc_bson_integer_size(const std::int64_t value)
15991 {
15992 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
15993 ? sizeof(std::int32_t)
15994 : sizeof(std::int64_t);
15995 }
15996
16000 void write_bson_integer(const string_t& name,
16001 const std::int64_t value)
16002 {
16003 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16004 {
16005 write_bson_entry_header(name, 0x10); // int32
16006 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16007 }
16008 else
16009 {
16010 write_bson_entry_header(name, 0x12); // int64
16011 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16012 }
16013 }
16014
16018 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16019 {
16020 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16021 ? sizeof(std::int32_t)
16022 : sizeof(std::int64_t);
16023 }
16024
16028 void write_bson_unsigned(const string_t& name,
16029 const BasicJsonType& j)
16030 {
16031 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16032 {
16033 write_bson_entry_header(name, 0x10 /* int32 */);
16034 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16035 }
16036 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16037 {
16038 write_bson_entry_header(name, 0x12 /* int64 */);
16039 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16040 }
16041 else
16042 {
16043 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));
16044 }
16045 }
16046
16050 void write_bson_object_entry(const string_t& name,
16051 const typename BasicJsonType::object_t& value)
16052 {
16053 write_bson_entry_header(name, 0x03); // object
16054 write_bson_object(value);
16055 }
16056
16060 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16061 {
16062 std::size_t array_index = 0ul;
16063
16064 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)
16065 {
16066 return result + calc_bson_element_size(std::to_string(array_index++), el);
16067 });
16068
16069 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16070 }
16071
16075 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16076 {
16077 return sizeof(std::int32_t) + value.size() + 1ul;
16078 }
16079
16083 void write_bson_array(const string_t& name,
16084 const typename BasicJsonType::array_t& value)
16085 {
16086 write_bson_entry_header(name, 0x04); // array
16087 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16088
16089 std::size_t array_index = 0ul;
16090
16091 for (const auto& el : value)
16092 {
16093 write_bson_element(std::to_string(array_index++), el);
16094 }
16095
16096 oa->write_character(to_char_type(0x00));
16097 }
16098
16102 void write_bson_binary(const string_t& name,
16103 const binary_t& value)
16104 {
16105 write_bson_entry_header(name, 0x05);
16106
16107 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16108 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16109
16110 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16111 }
16112
16117 static std::size_t calc_bson_element_size(const string_t& name,
16118 const BasicJsonType& j)
16119 {
16120 const auto header_size = calc_bson_entry_header_size(name, j);
16121 switch (j.type())
16122 {
16123 case value_t::object:
16124 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16125
16126 case value_t::array:
16127 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16128
16129 case value_t::binary:
16130 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16131
16132 case value_t::boolean:
16133 return header_size + 1ul;
16134
16135 case value_t::number_float:
16136 return header_size + 8ul;
16137
16138 case value_t::number_integer:
16139 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16140
16141 case value_t::number_unsigned:
16142 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16143
16144 case value_t::string:
16145 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16146
16147 case value_t::null:
16148 return header_size + 0ul;
16149
16150 // LCOV_EXCL_START
16151 case value_t::discarded:
16152 default:
16153 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16154 return 0ul;
16155 // LCOV_EXCL_STOP
16156 }
16157 }
16158
16165 void write_bson_element(const string_t& name,
16166 const BasicJsonType& j)
16167 {
16168 switch (j.type())
16169 {
16170 case value_t::object:
16171 return write_bson_object_entry(name, *j.m_data.m_value.object);
16172
16173 case value_t::array:
16174 return write_bson_array(name, *j.m_data.m_value.array);
16175
16176 case value_t::binary:
16177 return write_bson_binary(name, *j.m_data.m_value.binary);
16178
16179 case value_t::boolean:
16180 return write_bson_boolean(name, j.m_data.m_value.boolean);
16181
16182 case value_t::number_float:
16183 return write_bson_double(name, j.m_data.m_value.number_float);
16184
16185 case value_t::number_integer:
16186 return write_bson_integer(name, j.m_data.m_value.number_integer);
16187
16188 case value_t::number_unsigned:
16189 return write_bson_unsigned(name, j);
16190
16191 case value_t::string:
16192 return write_bson_string(name, *j.m_data.m_value.string);
16193
16194 case value_t::null:
16195 return write_bson_null(name);
16196
16197 // LCOV_EXCL_START
16198 case value_t::discarded:
16199 default:
16200 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16201 return;
16202 // LCOV_EXCL_STOP
16203 }
16204 }
16205
16212 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
16213 {
16214 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
16215 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
16216 {
16217 return result += calc_bson_element_size(el.first, el.second);
16218 });
16219
16220 return sizeof(std::int32_t) + document_size + 1ul;
16221 }
16222
16227 void write_bson_object(const typename BasicJsonType::object_t& value)
16228 {
16229 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
16230
16231 for (const auto& el : value)
16232 {
16233 write_bson_element(el.first, el.second);
16234 }
16235
16236 oa->write_character(to_char_type(0x00));
16237 }
16238
16240 // CBOR //
16242
16243 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
16244 {
16245 return to_char_type(0xFA); // Single-Precision Float
16246 }
16247
16248 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
16249 {
16250 return to_char_type(0xFB); // Double-Precision Float
16251 }
16252
16254 // MsgPack //
16256
16257 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
16258 {
16259 return to_char_type(0xCA); // float 32
16260 }
16261
16262 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
16263 {
16264 return to_char_type(0xCB); // float 64
16265 }
16266
16268 // UBJSON //
16270
16271 // UBJSON: write number (floating point)
16272 template<typename NumberType, typename std::enable_if<
16273 std::is_floating_point<NumberType>::value, int>::type = 0>
16274 void write_number_with_ubjson_prefix(const NumberType n,
16275 const bool add_prefix,
16276 const bool use_bjdata)
16277 {
16278 if (add_prefix)
16279 {
16280 oa->write_character(get_ubjson_float_prefix(n));
16281 }
16282 write_number(n, use_bjdata);
16283 }
16284
16285 // UBJSON: write number (unsigned integer)
16286 template<typename NumberType, typename std::enable_if<
16287 std::is_unsigned<NumberType>::value, int>::type = 0>
16288 void write_number_with_ubjson_prefix(const NumberType n,
16289 const bool add_prefix,
16290 const bool use_bjdata)
16291 {
16292 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16293 {
16294 if (add_prefix)
16295 {
16296 oa->write_character(to_char_type('i')); // int8
16297 }
16298 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16299 }
16300 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
16301 {
16302 if (add_prefix)
16303 {
16304 oa->write_character(to_char_type('U')); // uint8
16305 }
16306 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16307 }
16308 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16309 {
16310 if (add_prefix)
16311 {
16312 oa->write_character(to_char_type('I')); // int16
16313 }
16314 write_number(static_cast<std::int16_t>(n), use_bjdata);
16315 }
16316 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
16317 {
16318 if (add_prefix)
16319 {
16320 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16321 }
16322 write_number(static_cast<std::uint16_t>(n), use_bjdata);
16323 }
16324 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16325 {
16326 if (add_prefix)
16327 {
16328 oa->write_character(to_char_type('l')); // int32
16329 }
16330 write_number(static_cast<std::int32_t>(n), use_bjdata);
16331 }
16332 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
16333 {
16334 if (add_prefix)
16335 {
16336 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16337 }
16338 write_number(static_cast<std::uint32_t>(n), use_bjdata);
16339 }
16340 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16341 {
16342 if (add_prefix)
16343 {
16344 oa->write_character(to_char_type('L')); // int64
16345 }
16346 write_number(static_cast<std::int64_t>(n), use_bjdata);
16347 }
16348 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
16349 {
16350 if (add_prefix)
16351 {
16352 oa->write_character(to_char_type('M')); // uint64 - bjdata only
16353 }
16354 write_number(static_cast<std::uint64_t>(n), use_bjdata);
16355 }
16356 else
16357 {
16358 if (add_prefix)
16359 {
16360 oa->write_character(to_char_type('H')); // high-precision number
16361 }
16362
16363 const auto number = BasicJsonType(n).dump();
16364 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16365 for (std::size_t i = 0; i < number.size(); ++i)
16366 {
16367 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16368 }
16369 }
16370 }
16371
16372 // UBJSON: write number (signed integer)
16373 template < typename NumberType, typename std::enable_if <
16374 std::is_signed<NumberType>::value&&
16375 !std::is_floating_point<NumberType>::value, int >::type = 0 >
16376 void write_number_with_ubjson_prefix(const NumberType n,
16377 const bool add_prefix,
16378 const bool use_bjdata)
16379 {
16380 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
16381 {
16382 if (add_prefix)
16383 {
16384 oa->write_character(to_char_type('i')); // int8
16385 }
16386 write_number(static_cast<std::int8_t>(n), use_bjdata);
16387 }
16388 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)()))
16389 {
16390 if (add_prefix)
16391 {
16392 oa->write_character(to_char_type('U')); // uint8
16393 }
16394 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16395 }
16396 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
16397 {
16398 if (add_prefix)
16399 {
16400 oa->write_character(to_char_type('I')); // int16
16401 }
16402 write_number(static_cast<std::int16_t>(n), use_bjdata);
16403 }
16404 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)())))
16405 {
16406 if (add_prefix)
16407 {
16408 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16409 }
16410 write_number(static_cast<uint16_t>(n), use_bjdata);
16411 }
16412 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
16413 {
16414 if (add_prefix)
16415 {
16416 oa->write_character(to_char_type('l')); // int32
16417 }
16418 write_number(static_cast<std::int32_t>(n), use_bjdata);
16419 }
16420 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)())))
16421 {
16422 if (add_prefix)
16423 {
16424 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16425 }
16426 write_number(static_cast<uint32_t>(n), use_bjdata);
16427 }
16428 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
16429 {
16430 if (add_prefix)
16431 {
16432 oa->write_character(to_char_type('L')); // int64
16433 }
16434 write_number(static_cast<std::int64_t>(n), use_bjdata);
16435 }
16436 // LCOV_EXCL_START
16437 else
16438 {
16439 if (add_prefix)
16440 {
16441 oa->write_character(to_char_type('H')); // high-precision number
16442 }
16443
16444 const auto number = BasicJsonType(n).dump();
16445 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16446 for (std::size_t i = 0; i < number.size(); ++i)
16447 {
16448 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16449 }
16450 }
16451 // LCOV_EXCL_STOP
16452 }
16453
16457 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
16458 {
16459 switch (j.type())
16460 {
16461 case value_t::null:
16462 return 'Z';
16463
16464 case value_t::boolean:
16465 return j.m_data.m_value.boolean ? 'T' : 'F';
16466
16467 case value_t::number_integer:
16468 {
16469 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)())
16470 {
16471 return 'i';
16472 }
16473 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)())
16474 {
16475 return 'U';
16476 }
16477 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)())
16478 {
16479 return 'I';
16480 }
16481 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)()))
16482 {
16483 return 'u';
16484 }
16485 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)())
16486 {
16487 return 'l';
16488 }
16489 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)()))
16490 {
16491 return 'm';
16492 }
16493 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)())
16494 {
16495 return 'L';
16496 }
16497 // anything else is treated as high-precision number
16498 return 'H'; // LCOV_EXCL_LINE
16499 }
16500
16501 case value_t::number_unsigned:
16502 {
16503 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16504 {
16505 return 'i';
16506 }
16507 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
16508 {
16509 return 'U';
16510 }
16511 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16512 {
16513 return 'I';
16514 }
16515 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
16516 {
16517 return 'u';
16518 }
16519 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16520 {
16521 return 'l';
16522 }
16523 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
16524 {
16525 return 'm';
16526 }
16527 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16528 {
16529 return 'L';
16530 }
16531 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16532 {
16533 return 'M';
16534 }
16535 // anything else is treated as high-precision number
16536 return 'H'; // LCOV_EXCL_LINE
16537 }
16538
16539 case value_t::number_float:
16540 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
16541
16542 case value_t::string:
16543 return 'S';
16544
16545 case value_t::array: // fallthrough
16546 case value_t::binary:
16547 return '[';
16548
16549 case value_t::object:
16550 return '{';
16551
16552 case value_t::discarded:
16553 default: // discarded values
16554 return 'N';
16555 }
16556 }
16557
16558 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
16559 {
16560 return 'd'; // float 32
16561 }
16562
16563 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
16564 {
16565 return 'D'; // float 64
16566 }
16567
16571 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
16572 {
16573 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
16574 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
16575 };
16576
16577 string_t key = "_ArrayType_";
16578 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
16579 if (it == bjdtype.end())
16580 {
16581 return true;
16582 }
16583 CharType dtype = it->second;
16584
16585 key = "_ArraySize_";
16586 std::size_t len = (value.at(key).empty() ? 0 : 1);
16587 for (const auto& el : value.at(key))
16588 {
16589 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
16590 }
16591
16592 key = "_ArrayData_";
16593 if (value.at(key).size() != len)
16594 {
16595 return true;
16596 }
16597
16598 oa->write_character('[');
16599 oa->write_character('$');
16600 oa->write_character(dtype);
16601 oa->write_character('#');
16602
16603 key = "_ArraySize_";
16604 write_ubjson(value.at(key), use_count, use_type, true, true);
16605
16606 key = "_ArrayData_";
16607 if (dtype == 'U' || dtype == 'C')
16608 {
16609 for (const auto& el : value.at(key))
16610 {
16611 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
16612 }
16613 }
16614 else if (dtype == 'i')
16615 {
16616 for (const auto& el : value.at(key))
16617 {
16618 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
16619 }
16620 }
16621 else if (dtype == 'u')
16622 {
16623 for (const auto& el : value.at(key))
16624 {
16625 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
16626 }
16627 }
16628 else if (dtype == 'I')
16629 {
16630 for (const auto& el : value.at(key))
16631 {
16632 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
16633 }
16634 }
16635 else if (dtype == 'm')
16636 {
16637 for (const auto& el : value.at(key))
16638 {
16639 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
16640 }
16641 }
16642 else if (dtype == 'l')
16643 {
16644 for (const auto& el : value.at(key))
16645 {
16646 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
16647 }
16648 }
16649 else if (dtype == 'M')
16650 {
16651 for (const auto& el : value.at(key))
16652 {
16653 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
16654 }
16655 }
16656 else if (dtype == 'L')
16657 {
16658 for (const auto& el : value.at(key))
16659 {
16660 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
16661 }
16662 }
16663 else if (dtype == 'd')
16664 {
16665 for (const auto& el : value.at(key))
16666 {
16667 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
16668 }
16669 }
16670 else if (dtype == 'D')
16671 {
16672 for (const auto& el : value.at(key))
16673 {
16674 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
16675 }
16676 }
16677 return false;
16678 }
16679
16681 // Utility functions //
16683
16684 /*
16685 @brief write a number to output input
16686 @param[in] n number of type @a NumberType
16687 @param[in] OutputIsLittleEndian Set to true if output data is
16688 required to be little endian
16689 @tparam NumberType the type of the number
16690
16691 @note This function needs to respect the system's endianness, because bytes
16692 in CBOR, MessagePack, and UBJSON are stored in network order (big
16693 endian) and therefore need reordering on little endian systems.
16694 On the other hand, BSON and BJData use little endian and should reorder
16695 on big endian systems.
16696 */
16697 template<typename NumberType>
16698 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
16699 {
16700 // step 1: write number to array of length NumberType
16701 std::array<CharType, sizeof(NumberType)> vec{};
16702 std::memcpy(vec.data(), &n, sizeof(NumberType));
16703
16704 // step 2: write array to output (with possible reordering)
16705 if (is_little_endian != OutputIsLittleEndian)
16706 {
16707 // reverse byte order prior to conversion if necessary
16708 std::reverse(vec.begin(), vec.end());
16709 }
16710
16711 oa->write_characters(vec.data(), sizeof(NumberType));
16712 }
16713
16714 void write_compact_float(const number_float_t n, detail::input_format_t format)
16715 {
16716#ifdef __GNUC__
16717#pragma GCC diagnostic push
16718#pragma GCC diagnostic ignored "-Wfloat-equal"
16719#endif
16720 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
16721 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
16722 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
16723 {
16724 oa->write_character(format == detail::input_format_t::cbor
16725 ? get_cbor_float_prefix(static_cast<float>(n))
16726 : get_msgpack_float_prefix(static_cast<float>(n)));
16727 write_number(static_cast<float>(n));
16728 }
16729 else
16730 {
16731 oa->write_character(format == detail::input_format_t::cbor
16732 ? get_cbor_float_prefix(n)
16733 : get_msgpack_float_prefix(n));
16734 write_number(n);
16735 }
16736#ifdef __GNUC__
16737#pragma GCC diagnostic pop
16738#endif
16739 }
16740
16741 public:
16742 // The following to_char_type functions are implement the conversion
16743 // between uint8_t and CharType. In case CharType is not unsigned,
16744 // such a conversion is required to allow values greater than 128.
16745 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
16746 template < typename C = CharType,
16747 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
16748 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16749 {
16750 return *reinterpret_cast<char*>(&x);
16751 }
16752
16753 template < typename C = CharType,
16754 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
16755 static CharType to_char_type(std::uint8_t x) noexcept
16756 {
16757 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
16758 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
16759 CharType result;
16760 std::memcpy(&result, &x, sizeof(x));
16761 return result;
16762 }
16763
16764 template<typename C = CharType,
16765 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
16766 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16767 {
16768 return x;
16769 }
16770
16771 template < typename InputCharType, typename C = CharType,
16772 enable_if_t <
16773 std::is_signed<C>::value &&
16774 std::is_signed<char>::value &&
16775 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
16776 > * = nullptr >
16777 static constexpr CharType to_char_type(InputCharType x) noexcept
16778 {
16779 return x;
16780 }
16781
16782 private:
16784 const bool is_little_endian = little_endianness();
16785
16787 output_adapter_t<CharType> oa = nullptr;
16788};
16789
16790} // namespace detail
16792
16793// #include <nlohmann/detail/output/output_adapters.hpp>
16794
16795// #include <nlohmann/detail/output/serializer.hpp>
16796// __ _____ _____ _____
16797// __| | __| | | | JSON for Modern C++
16798// | | |__ | | | | | | version 3.11.2
16799// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16800//
16801// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de>
16802// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
16803// SPDX-License-Identifier: MIT
16804
16805
16806
16807#include <algorithm> // reverse, remove, fill, find, none_of
16808#include <array> // array
16809#include <clocale> // localeconv, lconv
16810#include <cmath> // labs, isfinite, isnan, signbit
16811#include <cstddef> // size_t, ptrdiff_t
16812#include <cstdint> // uint8_t
16813#include <cstdio> // snprintf
16814#include <limits> // numeric_limits
16815#include <string> // string, char_traits
16816#include <iomanip> // setfill, setw
16817#include <type_traits> // is_same
16818#include <utility> // move
16819
16820// #include <nlohmann/detail/conversions/to_chars.hpp>
16821// __ _____ _____ _____
16822// __| | __| | | | JSON for Modern C++
16823// | | |__ | | | | | | version 3.11.2
16824// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16825//
16826// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
16827// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
16828// SPDX-License-Identifier: MIT
16829
16830
16831
16832#include <array> // array
16833#include <cmath> // signbit, isfinite
16834#include <cstdint> // intN_t, uintN_t
16835#include <cstring> // memcpy, memmove
16836#include <limits> // numeric_limits
16837#include <type_traits> // conditional
16838
16839// #include <nlohmann/detail/macro_scope.hpp>
16840
16841
16843namespace detail
16844{
16845
16865namespace dtoa_impl
16866{
16867
16868template<typename Target, typename Source>
16869Target reinterpret_bits(const Source source)
16870{
16871 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
16872
16873 Target target;
16874 std::memcpy(&target, &source, sizeof(Source));
16875 return target;
16876}
16877
16878struct diyfp // f * 2^e
16879{
16880 static constexpr int kPrecision = 64; // = q
16881
16882 std::uint64_t f = 0;
16883 int e = 0;
16884
16885 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
16886
16891 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
16892 {
16893 JSON_ASSERT(x.e == y.e);
16894 JSON_ASSERT(x.f >= y.f);
16895
16896 return {x.f - y.f, x.e};
16897 }
16898
16903 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
16904 {
16905 static_assert(kPrecision == 64, "internal error");
16906
16907 // Computes:
16908 // f = round((x.f * y.f) / 2^q)
16909 // e = x.e + y.e + q
16910
16911 // Emulate the 64-bit * 64-bit multiplication:
16912 //
16913 // p = u * v
16914 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
16915 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
16916 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
16917 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
16918 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
16919 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
16920 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
16921 //
16922 // (Since Q might be larger than 2^32 - 1)
16923 //
16924 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
16925 //
16926 // (Q_hi + H does not overflow a 64-bit int)
16927 //
16928 // = p_lo + 2^64 p_hi
16929
16930 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
16931 const std::uint64_t u_hi = x.f >> 32u;
16932 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
16933 const std::uint64_t v_hi = y.f >> 32u;
16934
16935 const std::uint64_t p0 = u_lo * v_lo;
16936 const std::uint64_t p1 = u_lo * v_hi;
16937 const std::uint64_t p2 = u_hi * v_lo;
16938 const std::uint64_t p3 = u_hi * v_hi;
16939
16940 const std::uint64_t p0_hi = p0 >> 32u;
16941 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
16942 const std::uint64_t p1_hi = p1 >> 32u;
16943 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
16944 const std::uint64_t p2_hi = p2 >> 32u;
16945
16946 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
16947
16948 // The full product might now be computed as
16949 //
16950 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
16951 // p_lo = p0_lo + (Q << 32)
16952 //
16953 // But in this particular case here, the full p_lo is not required.
16954 // Effectively we only need to add the highest bit in p_lo to p_hi (and
16955 // Q_hi + 1 does not overflow).
16956
16957 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
16958
16959 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
16960
16961 return {h, x.e + y.e + 64};
16962 }
16963
16968 static diyfp normalize(diyfp x) noexcept
16969 {
16970 JSON_ASSERT(x.f != 0);
16971
16972 while ((x.f >> 63u) == 0)
16973 {
16974 x.f <<= 1u;
16975 x.e--;
16976 }
16977
16978 return x;
16979 }
16980
16985 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
16986 {
16987 const int delta = x.e - target_exponent;
16988
16989 JSON_ASSERT(delta >= 0);
16990 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
16991
16992 return {x.f << delta, target_exponent};
16993 }
16994};
16995
16996struct boundaries
16997{
16998 diyfp w;
16999 diyfp minus;
17000 diyfp plus;
17001};
17002
17009template<typename FloatType>
17010boundaries compute_boundaries(FloatType value)
17011{
17012 JSON_ASSERT(std::isfinite(value));
17013 JSON_ASSERT(value > 0);
17014
17015 // Convert the IEEE representation into a diyfp.
17016 //
17017 // If v is denormal:
17018 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17019 // If v is normalized:
17020 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17021
17022 static_assert(std::numeric_limits<FloatType>::is_iec559,
17023 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17024
17025 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17026 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17027 constexpr int kMinExp = 1 - kBias;
17028 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17029
17030 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17031
17032 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17033 const std::uint64_t E = bits >> (kPrecision - 1);
17034 const std::uint64_t F = bits & (kHiddenBit - 1);
17035
17036 const bool is_denormal = E == 0;
17037 const diyfp v = is_denormal
17038 ? diyfp(F, kMinExp)
17039 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17040
17041 // Compute the boundaries m- and m+ of the floating-point value
17042 // v = f * 2^e.
17043 //
17044 // Determine v- and v+, the floating-point predecessor and successor if v,
17045 // respectively.
17046 //
17047 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17048 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17049 //
17050 // v+ = v + 2^e
17051 //
17052 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17053 // between m- and m+ round to v, regardless of how the input rounding
17054 // algorithm breaks ties.
17055 //
17056 // ---+-------------+-------------+-------------+-------------+--- (A)
17057 // v- m- v m+ v+
17058 //
17059 // -----------------+------+------+-------------+-------------+--- (B)
17060 // v- m- v m+ v+
17061
17062 const bool lower_boundary_is_closer = F == 0 && E > 1;
17063 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
17064 const diyfp m_minus = lower_boundary_is_closer
17065 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
17066 : diyfp(2 * v.f - 1, v.e - 1); // (A)
17067
17068 // Determine the normalized w+ = m+.
17069 const diyfp w_plus = diyfp::normalize(m_plus);
17070
17071 // Determine w- = m- such that e_(w-) = e_(w+).
17072 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17073
17074 return {diyfp::normalize(v), w_minus, w_plus};
17075}
17076
17077// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17078// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17079// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17080//
17081// alpha <= e = e_c + e_w + q <= gamma
17082//
17083// or
17084//
17085// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17086// <= f_c * f_w * 2^gamma
17087//
17088// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17089//
17090// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17091//
17092// or
17093//
17094// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17095//
17096// The choice of (alpha,gamma) determines the size of the table and the form of
17097// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17098// in practice:
17099//
17100// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17101// processed independently: An integral part p1, and a fractional part p2:
17102//
17103// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17104// = (f div 2^-e) + (f mod 2^-e) * 2^e
17105// = p1 + p2 * 2^e
17106//
17107// The conversion of p1 into decimal form requires a series of divisions and
17108// modulos by (a power of) 10. These operations are faster for 32-bit than for
17109// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17110// achieved by choosing
17111//
17112// -e >= 32 or e <= -32 := gamma
17113//
17114// In order to convert the fractional part
17115//
17116// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17117//
17118// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17119// d[-i] are extracted in order:
17120//
17121// (10 * p2) div 2^-e = d[-1]
17122// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17123//
17124// The multiplication by 10 must not overflow. It is sufficient to choose
17125//
17126// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17127//
17128// Since p2 = f mod 2^-e < 2^-e,
17129//
17130// -e <= 60 or e >= -60 := alpha
17131
17132constexpr int kAlpha = -60;
17133constexpr int kGamma = -32;
17134
17135struct cached_power // c = f * 2^e ~= 10^k
17136{
17137 std::uint64_t f;
17138 int e;
17139 int k;
17140};
17141
17149inline cached_power get_cached_power_for_binary_exponent(int e)
17150{
17151 // Now
17152 //
17153 // alpha <= e_c + e + q <= gamma (1)
17154 // ==> f_c * 2^alpha <= c * 2^e * 2^q
17155 //
17156 // and since the c's are normalized, 2^(q-1) <= f_c,
17157 //
17158 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
17159 // ==> 2^(alpha - e - 1) <= c
17160 //
17161 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
17162 //
17163 // k = ceil( log_10( 2^(alpha - e - 1) ) )
17164 // = ceil( (alpha - e - 1) * log_10(2) )
17165 //
17166 // From the paper:
17167 // "In theory the result of the procedure could be wrong since c is rounded,
17168 // and the computation itself is approximated [...]. In practice, however,
17169 // this simple function is sufficient."
17170 //
17171 // For IEEE double precision floating-point numbers converted into
17172 // normalized diyfp's w = f * 2^e, with q = 64,
17173 //
17174 // e >= -1022 (min IEEE exponent)
17175 // -52 (p - 1)
17176 // -52 (p - 1, possibly normalize denormal IEEE numbers)
17177 // -11 (normalize the diyfp)
17178 // = -1137
17179 //
17180 // and
17181 //
17182 // e <= +1023 (max IEEE exponent)
17183 // -52 (p - 1)
17184 // -11 (normalize the diyfp)
17185 // = 960
17186 //
17187 // This binary exponent range [-1137,960] results in a decimal exponent
17188 // range [-307,324]. One does not need to store a cached power for each
17189 // k in this range. For each such k it suffices to find a cached power
17190 // such that the exponent of the product lies in [alpha,gamma].
17191 // This implies that the difference of the decimal exponents of adjacent
17192 // table entries must be less than or equal to
17193 //
17194 // floor( (gamma - alpha) * log_10(2) ) = 8.
17195 //
17196 // (A smaller distance gamma-alpha would require a larger table.)
17197
17198 // NB:
17199 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
17200
17201 constexpr int kCachedPowersMinDecExp = -300;
17202 constexpr int kCachedPowersDecStep = 8;
17203
17204 static constexpr std::array<cached_power, 79> kCachedPowers =
17205 {
17206 {
17207 { 0xAB70FE17C79AC6CA, -1060, -300 },
17208 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
17209 { 0xBE5691EF416BD60C, -1007, -284 },
17210 { 0x8DD01FAD907FFC3C, -980, -276 },
17211 { 0xD3515C2831559A83, -954, -268 },
17212 { 0x9D71AC8FADA6C9B5, -927, -260 },
17213 { 0xEA9C227723EE8BCB, -901, -252 },
17214 { 0xAECC49914078536D, -874, -244 },
17215 { 0x823C12795DB6CE57, -847, -236 },
17216 { 0xC21094364DFB5637, -821, -228 },
17217 { 0x9096EA6F3848984F, -794, -220 },
17218 { 0xD77485CB25823AC7, -768, -212 },
17219 { 0xA086CFCD97BF97F4, -741, -204 },
17220 { 0xEF340A98172AACE5, -715, -196 },
17221 { 0xB23867FB2A35B28E, -688, -188 },
17222 { 0x84C8D4DFD2C63F3B, -661, -180 },
17223 { 0xC5DD44271AD3CDBA, -635, -172 },
17224 { 0x936B9FCEBB25C996, -608, -164 },
17225 { 0xDBAC6C247D62A584, -582, -156 },
17226 { 0xA3AB66580D5FDAF6, -555, -148 },
17227 { 0xF3E2F893DEC3F126, -529, -140 },
17228 { 0xB5B5ADA8AAFF80B8, -502, -132 },
17229 { 0x87625F056C7C4A8B, -475, -124 },
17230 { 0xC9BCFF6034C13053, -449, -116 },
17231 { 0x964E858C91BA2655, -422, -108 },
17232 { 0xDFF9772470297EBD, -396, -100 },
17233 { 0xA6DFBD9FB8E5B88F, -369, -92 },
17234 { 0xF8A95FCF88747D94, -343, -84 },
17235 { 0xB94470938FA89BCF, -316, -76 },
17236 { 0x8A08F0F8BF0F156B, -289, -68 },
17237 { 0xCDB02555653131B6, -263, -60 },
17238 { 0x993FE2C6D07B7FAC, -236, -52 },
17239 { 0xE45C10C42A2B3B06, -210, -44 },
17240 { 0xAA242499697392D3, -183, -36 },
17241 { 0xFD87B5F28300CA0E, -157, -28 },
17242 { 0xBCE5086492111AEB, -130, -20 },
17243 { 0x8CBCCC096F5088CC, -103, -12 },
17244 { 0xD1B71758E219652C, -77, -4 },
17245 { 0x9C40000000000000, -50, 4 },
17246 { 0xE8D4A51000000000, -24, 12 },
17247 { 0xAD78EBC5AC620000, 3, 20 },
17248 { 0x813F3978F8940984, 30, 28 },
17249 { 0xC097CE7BC90715B3, 56, 36 },
17250 { 0x8F7E32CE7BEA5C70, 83, 44 },
17251 { 0xD5D238A4ABE98068, 109, 52 },
17252 { 0x9F4F2726179A2245, 136, 60 },
17253 { 0xED63A231D4C4FB27, 162, 68 },
17254 { 0xB0DE65388CC8ADA8, 189, 76 },
17255 { 0x83C7088E1AAB65DB, 216, 84 },
17256 { 0xC45D1DF942711D9A, 242, 92 },
17257 { 0x924D692CA61BE758, 269, 100 },
17258 { 0xDA01EE641A708DEA, 295, 108 },
17259 { 0xA26DA3999AEF774A, 322, 116 },
17260 { 0xF209787BB47D6B85, 348, 124 },
17261 { 0xB454E4A179DD1877, 375, 132 },
17262 { 0x865B86925B9BC5C2, 402, 140 },
17263 { 0xC83553C5C8965D3D, 428, 148 },
17264 { 0x952AB45CFA97A0B3, 455, 156 },
17265 { 0xDE469FBD99A05FE3, 481, 164 },
17266 { 0xA59BC234DB398C25, 508, 172 },
17267 { 0xF6C69A72A3989F5C, 534, 180 },
17268 { 0xB7DCBF5354E9BECE, 561, 188 },
17269 { 0x88FCF317F22241E2, 588, 196 },
17270 { 0xCC20CE9BD35C78A5, 614, 204 },
17271 { 0x98165AF37B2153DF, 641, 212 },
17272 { 0xE2A0B5DC971F303A, 667, 220 },
17273 { 0xA8D9D1535CE3B396, 694, 228 },
17274 { 0xFB9B7CD9A4A7443C, 720, 236 },
17275 { 0xBB764C4CA7A44410, 747, 244 },
17276 { 0x8BAB8EEFB6409C1A, 774, 252 },
17277 { 0xD01FEF10A657842C, 800, 260 },
17278 { 0x9B10A4E5E9913129, 827, 268 },
17279 { 0xE7109BFBA19C0C9D, 853, 276 },
17280 { 0xAC2820D9623BF429, 880, 284 },
17281 { 0x80444B5E7AA7CF85, 907, 292 },
17282 { 0xBF21E44003ACDD2D, 933, 300 },
17283 { 0x8E679C2F5E44FF8F, 960, 308 },
17284 { 0xD433179D9C8CB841, 986, 316 },
17285 { 0x9E19DB92B4E31BA9, 1013, 324 },
17286 }
17287 };
17288
17289 // This computation gives exactly the same results for k as
17290 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
17291 // for |e| <= 1500, but doesn't require floating-point operations.
17292 // NB: log_10(2) ~= 78913 / 2^18
17293 JSON_ASSERT(e >= -1500);
17294 JSON_ASSERT(e <= 1500);
17295 const int f = kAlpha - e - 1;
17296 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
17297
17298 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
17299 JSON_ASSERT(index >= 0);
17300 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
17301
17302 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
17303 JSON_ASSERT(kAlpha <= cached.e + e + 64);
17304 JSON_ASSERT(kGamma >= cached.e + e + 64);
17305
17306 return cached;
17307}
17308
17313inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
17314{
17315 // LCOV_EXCL_START
17316 if (n >= 1000000000)
17317 {
17318 pow10 = 1000000000;
17319 return 10;
17320 }
17321 // LCOV_EXCL_STOP
17322 if (n >= 100000000)
17323 {
17324 pow10 = 100000000;
17325 return 9;
17326 }
17327 if (n >= 10000000)
17328 {
17329 pow10 = 10000000;
17330 return 8;
17331 }
17332 if (n >= 1000000)
17333 {
17334 pow10 = 1000000;
17335 return 7;
17336 }
17337 if (n >= 100000)
17338 {
17339 pow10 = 100000;
17340 return 6;
17341 }
17342 if (n >= 10000)
17343 {
17344 pow10 = 10000;
17345 return 5;
17346 }
17347 if (n >= 1000)
17348 {
17349 pow10 = 1000;
17350 return 4;
17351 }
17352 if (n >= 100)
17353 {
17354 pow10 = 100;
17355 return 3;
17356 }
17357 if (n >= 10)
17358 {
17359 pow10 = 10;
17360 return 2;
17361 }
17362
17363 pow10 = 1;
17364 return 1;
17365}
17366
17367inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
17368 std::uint64_t rest, std::uint64_t ten_k)
17369{
17370 JSON_ASSERT(len >= 1);
17371 JSON_ASSERT(dist <= delta);
17372 JSON_ASSERT(rest <= delta);
17373 JSON_ASSERT(ten_k > 0);
17374
17375 // <--------------------------- delta ---->
17376 // <---- dist --------->
17377 // --------------[------------------+-------------------]--------------
17378 // M- w M+
17379 //
17380 // ten_k
17381 // <------>
17382 // <---- rest ---->
17383 // --------------[------------------+----+--------------]--------------
17384 // w V
17385 // = buf * 10^k
17386 //
17387 // ten_k represents a unit-in-the-last-place in the decimal representation
17388 // stored in buf.
17389 // Decrement buf by ten_k while this takes buf closer to w.
17390
17391 // The tests are written in this order to avoid overflow in unsigned
17392 // integer arithmetic.
17393
17394 while (rest < dist
17395 && delta - rest >= ten_k
17396 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
17397 {
17398 JSON_ASSERT(buf[len - 1] != '0');
17399 buf[len - 1]--;
17400 rest += ten_k;
17401 }
17402}
17403
17408inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
17409 diyfp M_minus, diyfp w, diyfp M_plus)
17410{
17411 static_assert(kAlpha >= -60, "internal error");
17412 static_assert(kGamma <= -32, "internal error");
17413
17414 // Generates the digits (and the exponent) of a decimal floating-point
17415 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
17416 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
17417 //
17418 // <--------------------------- delta ---->
17419 // <---- dist --------->
17420 // --------------[------------------+-------------------]--------------
17421 // M- w M+
17422 //
17423 // Grisu2 generates the digits of M+ from left to right and stops as soon as
17424 // V is in [M-,M+].
17425
17426 JSON_ASSERT(M_plus.e >= kAlpha);
17427 JSON_ASSERT(M_plus.e <= kGamma);
17428
17429 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
17430 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
17431
17432 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
17433 //
17434 // M+ = f * 2^e
17435 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
17436 // = ((p1 ) * 2^-e + (p2 )) * 2^e
17437 // = p1 + p2 * 2^e
17438
17439 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
17440
17441 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.)
17442 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
17443
17444 // 1)
17445 //
17446 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
17447
17448 JSON_ASSERT(p1 > 0);
17449
17450 std::uint32_t pow10{};
17451 const int k = find_largest_pow10(p1, pow10);
17452
17453 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
17454 //
17455 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
17456 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
17457 //
17458 // M+ = p1 + p2 * 2^e
17459 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
17460 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
17461 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
17462 //
17463 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
17464 //
17465 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
17466 //
17467 // but stop as soon as
17468 //
17469 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
17470
17471 int n = k;
17472 while (n > 0)
17473 {
17474 // Invariants:
17475 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
17476 // pow10 = 10^(n-1) <= p1 < 10^n
17477 //
17478 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
17479 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
17480 //
17481 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
17482 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
17483 //
17484 JSON_ASSERT(d <= 9);
17485 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17486 //
17487 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
17488 //
17489 p1 = r;
17490 n--;
17491 //
17492 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
17493 // pow10 = 10^n
17494 //
17495
17496 // Now check if enough digits have been generated.
17497 // Compute
17498 //
17499 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
17500 //
17501 // Note:
17502 // Since rest and delta share the same exponent e, it suffices to
17503 // compare the significands.
17504 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
17505 if (rest <= delta)
17506 {
17507 // V = buffer * 10^n, with M- <= V <= M+.
17508
17509 decimal_exponent += n;
17510
17511 // We may now just stop. But instead look if the buffer could be
17512 // decremented to bring V closer to w.
17513 //
17514 // pow10 = 10^n is now 1 ulp in the decimal representation V.
17515 // The rounding procedure works with diyfp's with an implicit
17516 // exponent of e.
17517 //
17518 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
17519 //
17520 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
17521 grisu2_round(buffer, length, dist, delta, rest, ten_n);
17522
17523 return;
17524 }
17525
17526 pow10 /= 10;
17527 //
17528 // pow10 = 10^(n-1) <= p1 < 10^n
17529 // Invariants restored.
17530 }
17531
17532 // 2)
17533 //
17534 // The digits of the integral part have been generated:
17535 //
17536 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
17537 // = buffer + p2 * 2^e
17538 //
17539 // Now generate the digits of the fractional part p2 * 2^e.
17540 //
17541 // Note:
17542 // No decimal point is generated: the exponent is adjusted instead.
17543 //
17544 // p2 actually represents the fraction
17545 //
17546 // p2 * 2^e
17547 // = p2 / 2^-e
17548 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
17549 //
17550 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
17551 //
17552 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
17553 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
17554 //
17555 // using
17556 //
17557 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
17558 // = ( d) * 2^-e + ( r)
17559 //
17560 // or
17561 // 10^m * p2 * 2^e = d + r * 2^e
17562 //
17563 // i.e.
17564 //
17565 // M+ = buffer + p2 * 2^e
17566 // = buffer + 10^-m * (d + r * 2^e)
17567 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
17568 //
17569 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
17570
17571 JSON_ASSERT(p2 > delta);
17572
17573 int m = 0;
17574 for (;;)
17575 {
17576 // Invariant:
17577 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
17578 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
17579 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
17580 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
17581 //
17582 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
17583 p2 *= 10;
17584 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
17585 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
17586 //
17587 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
17588 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
17589 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
17590 //
17591 JSON_ASSERT(d <= 9);
17592 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17593 //
17594 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
17595 //
17596 p2 = r;
17597 m++;
17598 //
17599 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
17600 // Invariant restored.
17601
17602 // Check if enough digits have been generated.
17603 //
17604 // 10^-m * p2 * 2^e <= delta * 2^e
17605 // p2 * 2^e <= 10^m * delta * 2^e
17606 // p2 <= 10^m * delta
17607 delta *= 10;
17608 dist *= 10;
17609 if (p2 <= delta)
17610 {
17611 break;
17612 }
17613 }
17614
17615 // V = buffer * 10^-m, with M- <= V <= M+.
17616
17617 decimal_exponent -= m;
17618
17619 // 1 ulp in the decimal representation is now 10^-m.
17620 // Since delta and dist are now scaled by 10^m, we need to do the
17621 // same with ulp in order to keep the units in sync.
17622 //
17623 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
17624 //
17625 const std::uint64_t ten_m = one.f;
17626 grisu2_round(buffer, length, dist, delta, p2, ten_m);
17627
17628 // By construction this algorithm generates the shortest possible decimal
17629 // number (Loitsch, Theorem 6.2) which rounds back to w.
17630 // For an input number of precision p, at least
17631 //
17632 // N = 1 + ceil(p * log_10(2))
17633 //
17634 // decimal digits are sufficient to identify all binary floating-point
17635 // numbers (Matula, "In-and-Out conversions").
17636 // This implies that the algorithm does not produce more than N decimal
17637 // digits.
17638 //
17639 // N = 17 for p = 53 (IEEE double precision)
17640 // N = 9 for p = 24 (IEEE single precision)
17641}
17642
17649inline void grisu2(char* buf, int& len, int& decimal_exponent,
17650 diyfp m_minus, diyfp v, diyfp m_plus)
17651{
17652 JSON_ASSERT(m_plus.e == m_minus.e);
17653 JSON_ASSERT(m_plus.e == v.e);
17654
17655 // --------(-----------------------+-----------------------)-------- (A)
17656 // m- v m+
17657 //
17658 // --------------------(-----------+-----------------------)-------- (B)
17659 // m- v m+
17660 //
17661 // First scale v (and m- and m+) such that the exponent is in the range
17662 // [alpha, gamma].
17663
17664 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
17665
17666 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
17667
17668 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
17669 const diyfp w = diyfp::mul(v, c_minus_k);
17670 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17671 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
17672
17673 // ----(---+---)---------------(---+---)---------------(---+---)----
17674 // w- w w+
17675 // = c*m- = c*v = c*m+
17676 //
17677 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
17678 // w+ are now off by a small amount.
17679 // In fact:
17680 //
17681 // w - v * 10^k < 1 ulp
17682 //
17683 // To account for this inaccuracy, add resp. subtract 1 ulp.
17684 //
17685 // --------+---[---------------(---+---)---------------]---+--------
17686 // w- M- w M+ w+
17687 //
17688 // Now any number in [M-, M+] (bounds included) will round to w when input,
17689 // regardless of how the input rounding algorithm breaks ties.
17690 //
17691 // And digit_gen generates the shortest possible such number in [M-, M+].
17692 // Note that this does not mean that Grisu2 always generates the shortest
17693 // possible number in the interval (m-, m+).
17694 const diyfp M_minus(w_minus.f + 1, w_minus.e);
17695 const diyfp M_plus (w_plus.f - 1, w_plus.e );
17696
17697 decimal_exponent = -cached.k; // = -(-k) = k
17698
17699 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
17700}
17701
17707template<typename FloatType>
17709void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
17710{
17711 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17712 "internal error: not enough precision");
17713
17714 JSON_ASSERT(std::isfinite(value));
17715 JSON_ASSERT(value > 0);
17716
17717 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
17718 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
17719 // decimal representations are not exactly "short".
17720 //
17721 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
17722 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
17723 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
17724 // does.
17725 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
17726 // representation using the corresponding std::from_chars function recovers value exactly". That
17727 // indicates that single precision floating-point numbers should be recovered using
17728 // 'std::strtof'.
17729 //
17730 // NB: If the neighbors are computed for single-precision numbers, there is a single float
17731 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
17732 // value is off by 1 ulp.
17733#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
17734 const boundaries w = compute_boundaries(static_cast<double>(value));
17735#else
17736 const boundaries w = compute_boundaries(value);
17737#endif
17738
17739 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
17740}
17741
17749inline char* append_exponent(char* buf, int e)
17750{
17751 JSON_ASSERT(e > -1000);
17752 JSON_ASSERT(e < 1000);
17753
17754 if (e < 0)
17755 {
17756 e = -e;
17757 *buf++ = '-';
17758 }
17759 else
17760 {
17761 *buf++ = '+';
17762 }
17763
17764 auto k = static_cast<std::uint32_t>(e);
17765 if (k < 10)
17766 {
17767 // Always print at least two digits in the exponent.
17768 // This is for compatibility with printf("%g").
17769 *buf++ = '0';
17770 *buf++ = static_cast<char>('0' + k);
17771 }
17772 else if (k < 100)
17773 {
17774 *buf++ = static_cast<char>('0' + k / 10);
17775 k %= 10;
17776 *buf++ = static_cast<char>('0' + k);
17777 }
17778 else
17779 {
17780 *buf++ = static_cast<char>('0' + k / 100);
17781 k %= 100;
17782 *buf++ = static_cast<char>('0' + k / 10);
17783 k %= 10;
17784 *buf++ = static_cast<char>('0' + k);
17785 }
17786
17787 return buf;
17788}
17789
17801inline char* format_buffer(char* buf, int len, int decimal_exponent,
17802 int min_exp, int max_exp)
17803{
17804 JSON_ASSERT(min_exp < 0);
17805 JSON_ASSERT(max_exp > 0);
17806
17807 const int k = len;
17808 const int n = len + decimal_exponent;
17809
17810 // v = buf * 10^(n-k)
17811 // k is the length of the buffer (number of decimal digits)
17812 // n is the position of the decimal point relative to the start of the buffer.
17813
17814 if (k <= n && n <= max_exp)
17815 {
17816 // digits[000]
17817 // len <= max_exp + 2
17818
17819 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
17820 // Make it look like a floating-point number (#362, #378)
17821 buf[n + 0] = '.';
17822 buf[n + 1] = '0';
17823 return buf + (static_cast<size_t>(n) + 2);
17824 }
17825
17826 if (0 < n && n <= max_exp)
17827 {
17828 // dig.its
17829 // len <= max_digits10 + 1
17830
17831 JSON_ASSERT(k > n);
17832
17833 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
17834 buf[n] = '.';
17835 return buf + (static_cast<size_t>(k) + 1U);
17836 }
17837
17838 if (min_exp < n && n <= 0)
17839 {
17840 // 0.[000]digits
17841 // len <= 2 + (-min_exp - 1) + max_digits10
17842
17843 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
17844 buf[0] = '0';
17845 buf[1] = '.';
17846 std::memset(buf + 2, '0', static_cast<size_t>(-n));
17847 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
17848 }
17849
17850 if (k == 1)
17851 {
17852 // dE+123
17853 // len <= 1 + 5
17854
17855 buf += 1;
17856 }
17857 else
17858 {
17859 // d.igitsE+123
17860 // len <= max_digits10 + 1 + 5
17861
17862 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
17863 buf[1] = '.';
17864 buf += 1 + static_cast<size_t>(k);
17865 }
17866
17867 *buf++ = 'e';
17868 return append_exponent(buf, n - 1);
17869}
17870
17871} // namespace dtoa_impl
17872
17883template<typename FloatType>
17886char* to_chars(char* first, const char* last, FloatType value)
17887{
17888 static_cast<void>(last); // maybe unused - fix warning
17889 JSON_ASSERT(std::isfinite(value));
17890
17891 // Use signbit(value) instead of (value < 0) since signbit works for -0.
17892 if (std::signbit(value))
17893 {
17894 value = -value;
17895 *first++ = '-';
17896 }
17897
17898#ifdef __GNUC__
17899#pragma GCC diagnostic push
17900#pragma GCC diagnostic ignored "-Wfloat-equal"
17901#endif
17902 if (value == 0) // +-0
17903 {
17904 *first++ = '0';
17905 // Make it look like a floating-point number (#362, #378)
17906 *first++ = '.';
17907 *first++ = '0';
17908 return first;
17909 }
17910#ifdef __GNUC__
17911#pragma GCC diagnostic pop
17912#endif
17913
17914 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
17915
17916 // Compute v = buffer * 10^decimal_exponent.
17917 // The decimal digits are stored in the buffer, which needs to be interpreted
17918 // as an unsigned decimal integer.
17919 // len is the length of the buffer, i.e. the number of decimal digits.
17920 int len = 0;
17921 int decimal_exponent = 0;
17922 dtoa_impl::grisu2(first, len, decimal_exponent, value);
17923
17924 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
17925
17926 // Format the buffer like printf("%.*g", prec, value)
17927 constexpr int kMinExp = -4;
17928 // Use digits10 here to increase compatibility with version 2.
17929 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
17930
17931 JSON_ASSERT(last - first >= kMaxExp + 2);
17932 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
17933 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
17934
17935 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
17936}
17937
17938} // namespace detail
17940
17941// #include <nlohmann/detail/exceptions.hpp>
17942
17943// #include <nlohmann/detail/macro_scope.hpp>
17944
17945// #include <nlohmann/detail/meta/cpp_future.hpp>
17946
17947// #include <nlohmann/detail/output/binary_writer.hpp>
17948
17949// #include <nlohmann/detail/output/output_adapters.hpp>
17950
17951// #include <nlohmann/detail/string_concat.hpp>
17952
17953// #include <nlohmann/detail/value_t.hpp>
17954
17955
17957namespace detail
17958{
17959
17961// serialization //
17963
17966{
17967 strict,
17968 replace,
17969 ignore
17970};
17971
17972template<typename BasicJsonType>
17974{
17975 using string_t = typename BasicJsonType::string_t;
17976 using number_float_t = typename BasicJsonType::number_float_t;
17977 using number_integer_t = typename BasicJsonType::number_integer_t;
17978 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
17979 using binary_char_t = typename BasicJsonType::binary_t::value_type;
17980 static constexpr std::uint8_t UTF8_ACCEPT = 0;
17981 static constexpr std::uint8_t UTF8_REJECT = 1;
17982
17983 public:
17989 serializer(output_adapter_t<char> s, const char ichar,
17991 : o(std::move(s))
17992 , loc(std::localeconv())
17993 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
17994 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
17995 , indent_char(ichar)
17997 , error_handler(error_handler_)
17998 {}
17999
18000 // delete because of pointer members
18001 serializer(const serializer&) = delete;
18005 ~serializer() = default;
18006
18029 void dump(const BasicJsonType& val,
18030 const bool pretty_print,
18031 const bool ensure_ascii,
18032 const unsigned int indent_step,
18033 const unsigned int current_indent = 0)
18034 {
18035 switch (val.m_data.m_type)
18036 {
18037 case value_t::object:
18038 {
18039 if (val.m_data.m_value.object->empty())
18040 {
18041 o->write_characters("{}", 2);
18042 return;
18043 }
18044
18045 if (pretty_print)
18046 {
18047 o->write_characters("{\n", 2);
18048
18049 // variable to hold indentation for recursive calls
18050 const auto new_indent = current_indent + indent_step;
18051 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18052 {
18053 indent_string.resize(indent_string.size() * 2, ' ');
18054 }
18055
18056 // first n-1 elements
18057 auto i = val.m_data.m_value.object->cbegin();
18058 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18059 {
18060 o->write_characters(indent_string.c_str(), new_indent);
18061 o->write_character('\"');
18062 dump_escaped(i->first, ensure_ascii);
18063 o->write_characters("\": ", 3);
18064 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18065 o->write_characters(",\n", 2);
18066 }
18067
18068 // last element
18069 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18070 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18071 o->write_characters(indent_string.c_str(), new_indent);
18072 o->write_character('\"');
18073 dump_escaped(i->first, ensure_ascii);
18074 o->write_characters("\": ", 3);
18075 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18076
18077 o->write_character('\n');
18078 o->write_characters(indent_string.c_str(), current_indent);
18079 o->write_character('}');
18080 }
18081 else
18082 {
18083 o->write_character('{');
18084
18085 // first n-1 elements
18086 auto i = val.m_data.m_value.object->cbegin();
18087 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18088 {
18089 o->write_character('\"');
18090 dump_escaped(i->first, ensure_ascii);
18091 o->write_characters("\":", 2);
18092 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18093 o->write_character(',');
18094 }
18095
18096 // last element
18097 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18098 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18099 o->write_character('\"');
18100 dump_escaped(i->first, ensure_ascii);
18101 o->write_characters("\":", 2);
18102 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18103
18104 o->write_character('}');
18105 }
18106
18107 return;
18108 }
18109
18110 case value_t::array:
18111 {
18112 if (val.m_data.m_value.array->empty())
18113 {
18114 o->write_characters("[]", 2);
18115 return;
18116 }
18117
18118 if (pretty_print)
18119 {
18120 o->write_characters("[\n", 2);
18121
18122 // variable to hold indentation for recursive calls
18123 const auto new_indent = current_indent + indent_step;
18124 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18125 {
18126 indent_string.resize(indent_string.size() * 2, ' ');
18127 }
18128
18129 // first n-1 elements
18130 for (auto i = val.m_data.m_value.array->cbegin();
18131 i != val.m_data.m_value.array->cend() - 1; ++i)
18132 {
18133 o->write_characters(indent_string.c_str(), new_indent);
18134 dump(*i, true, ensure_ascii, indent_step, new_indent);
18135 o->write_characters(",\n", 2);
18136 }
18137
18138 // last element
18139 JSON_ASSERT(!val.m_data.m_value.array->empty());
18140 o->write_characters(indent_string.c_str(), new_indent);
18141 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18142
18143 o->write_character('\n');
18144 o->write_characters(indent_string.c_str(), current_indent);
18145 o->write_character(']');
18146 }
18147 else
18148 {
18149 o->write_character('[');
18150
18151 // first n-1 elements
18152 for (auto i = val.m_data.m_value.array->cbegin();
18153 i != val.m_data.m_value.array->cend() - 1; ++i)
18154 {
18155 dump(*i, false, ensure_ascii, indent_step, current_indent);
18156 o->write_character(',');
18157 }
18158
18159 // last element
18160 JSON_ASSERT(!val.m_data.m_value.array->empty());
18161 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
18162
18163 o->write_character(']');
18164 }
18165
18166 return;
18167 }
18168
18169 case value_t::string:
18170 {
18171 o->write_character('\"');
18172 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
18173 o->write_character('\"');
18174 return;
18175 }
18176
18177 case value_t::binary:
18178 {
18179 if (pretty_print)
18180 {
18181 o->write_characters("{\n", 2);
18182
18183 // variable to hold indentation for recursive calls
18184 const auto new_indent = current_indent + indent_step;
18185 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18186 {
18187 indent_string.resize(indent_string.size() * 2, ' ');
18188 }
18189
18190 o->write_characters(indent_string.c_str(), new_indent);
18191
18192 o->write_characters("\"bytes\": [", 10);
18193
18194 if (!val.m_data.m_value.binary->empty())
18195 {
18196 for (auto i = val.m_data.m_value.binary->cbegin();
18197 i != val.m_data.m_value.binary->cend() - 1; ++i)
18198 {
18199 dump_integer(*i);
18200 o->write_characters(", ", 2);
18201 }
18202 dump_integer(val.m_data.m_value.binary->back());
18203 }
18204
18205 o->write_characters("],\n", 3);
18206 o->write_characters(indent_string.c_str(), new_indent);
18207
18208 o->write_characters("\"subtype\": ", 11);
18209 if (val.m_data.m_value.binary->has_subtype())
18210 {
18211 dump_integer(val.m_data.m_value.binary->subtype());
18212 }
18213 else
18214 {
18215 o->write_characters("null", 4);
18216 }
18217 o->write_character('\n');
18218 o->write_characters(indent_string.c_str(), current_indent);
18219 o->write_character('}');
18220 }
18221 else
18222 {
18223 o->write_characters("{\"bytes\":[", 10);
18224
18225 if (!val.m_data.m_value.binary->empty())
18226 {
18227 for (auto i = val.m_data.m_value.binary->cbegin();
18228 i != val.m_data.m_value.binary->cend() - 1; ++i)
18229 {
18230 dump_integer(*i);
18231 o->write_character(',');
18232 }
18233 dump_integer(val.m_data.m_value.binary->back());
18234 }
18235
18236 o->write_characters("],\"subtype\":", 12);
18237 if (val.m_data.m_value.binary->has_subtype())
18238 {
18239 dump_integer(val.m_data.m_value.binary->subtype());
18240 o->write_character('}');
18241 }
18242 else
18243 {
18244 o->write_characters("null}", 5);
18245 }
18246 }
18247 return;
18248 }
18249
18250 case value_t::boolean:
18251 {
18252 if (val.m_data.m_value.boolean)
18253 {
18254 o->write_characters("true", 4);
18255 }
18256 else
18257 {
18258 o->write_characters("false", 5);
18259 }
18260 return;
18261 }
18262
18264 {
18265 dump_integer(val.m_data.m_value.number_integer);
18266 return;
18267 }
18268
18270 {
18271 dump_integer(val.m_data.m_value.number_unsigned);
18272 return;
18273 }
18274
18276 {
18277 dump_float(val.m_data.m_value.number_float);
18278 return;
18279 }
18280
18281 case value_t::discarded:
18282 {
18283 o->write_characters("<discarded>", 11);
18284 return;
18285 }
18286
18287 case value_t::null:
18288 {
18289 o->write_characters("null", 4);
18290 return;
18291 }
18292
18293 default: // LCOV_EXCL_LINE
18294 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18295 }
18296 }
18297
18313 void dump_escaped(const string_t& s, const bool ensure_ascii)
18314 {
18315 std::uint32_t codepoint{};
18316 std::uint8_t state = UTF8_ACCEPT;
18317 std::size_t bytes = 0; // number of bytes written to string_buffer
18318
18319 // number of bytes written at the point of the last valid byte
18321 std::size_t undumped_chars = 0;
18322
18323 for (std::size_t i = 0; i < s.size(); ++i)
18324 {
18325 const auto byte = static_cast<std::uint8_t>(s[i]);
18326
18327 switch (decode(state, codepoint, byte))
18328 {
18329 case UTF8_ACCEPT: // decode found a new code point
18330 {
18331 switch (codepoint)
18332 {
18333 case 0x08: // backspace
18334 {
18335 string_buffer[bytes++] = '\\';
18336 string_buffer[bytes++] = 'b';
18337 break;
18338 }
18339
18340 case 0x09: // horizontal tab
18341 {
18342 string_buffer[bytes++] = '\\';
18343 string_buffer[bytes++] = 't';
18344 break;
18345 }
18346
18347 case 0x0A: // newline
18348 {
18349 string_buffer[bytes++] = '\\';
18350 string_buffer[bytes++] = 'n';
18351 break;
18352 }
18353
18354 case 0x0C: // formfeed
18355 {
18356 string_buffer[bytes++] = '\\';
18357 string_buffer[bytes++] = 'f';
18358 break;
18359 }
18360
18361 case 0x0D: // carriage return
18362 {
18363 string_buffer[bytes++] = '\\';
18364 string_buffer[bytes++] = 'r';
18365 break;
18366 }
18367
18368 case 0x22: // quotation mark
18369 {
18370 string_buffer[bytes++] = '\\';
18371 string_buffer[bytes++] = '\"';
18372 break;
18373 }
18374
18375 case 0x5C: // reverse solidus
18376 {
18377 string_buffer[bytes++] = '\\';
18378 string_buffer[bytes++] = '\\';
18379 break;
18380 }
18381
18382 default:
18383 {
18384 // escape control characters (0x00..0x1F) or, if
18385 // ensure_ascii parameter is used, non-ASCII characters
18386 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
18387 {
18388 if (codepoint <= 0xFFFF)
18389 {
18390 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18391 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
18392 static_cast<std::uint16_t>(codepoint)));
18393 bytes += 6;
18394 }
18395 else
18396 {
18397 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18398 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
18399 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
18400 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
18401 bytes += 12;
18402 }
18403 }
18404 else
18405 {
18406 // copy byte to buffer (all previous bytes
18407 // been copied have in default case above)
18408 string_buffer[bytes++] = s[i];
18409 }
18410 break;
18411 }
18412 }
18413
18414 // write buffer and reset index; there must be 13 bytes
18415 // left, as this is the maximal number of bytes to be
18416 // written ("\uxxxx\uxxxx\0") for one code point
18417 if (string_buffer.size() - bytes < 13)
18418 {
18419 o->write_characters(string_buffer.data(), bytes);
18420 bytes = 0;
18421 }
18422
18423 // remember the byte position of this accept
18425 undumped_chars = 0;
18426 break;
18427 }
18428
18429 case UTF8_REJECT: // decode found invalid UTF-8 byte
18430 {
18431 switch (error_handler)
18432 {
18434 {
18435 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
18436 }
18437
18440 {
18441 // in case we saw this character the first time, we
18442 // would like to read it again, because the byte
18443 // may be OK for itself, but just not OK for the
18444 // previous sequence
18445 if (undumped_chars > 0)
18446 {
18447 --i;
18448 }
18449
18450 // reset length buffer to the last accepted index;
18451 // thus removing/ignoring the invalid characters
18453
18455 {
18456 // add a replacement character
18457 if (ensure_ascii)
18458 {
18459 string_buffer[bytes++] = '\\';
18460 string_buffer[bytes++] = 'u';
18461 string_buffer[bytes++] = 'f';
18462 string_buffer[bytes++] = 'f';
18463 string_buffer[bytes++] = 'f';
18464 string_buffer[bytes++] = 'd';
18465 }
18466 else
18467 {
18468 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
18469 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
18470 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
18471 }
18472
18473 // write buffer and reset index; there must be 13 bytes
18474 // left, as this is the maximal number of bytes to be
18475 // written ("\uxxxx\uxxxx\0") for one code point
18476 if (string_buffer.size() - bytes < 13)
18477 {
18478 o->write_characters(string_buffer.data(), bytes);
18479 bytes = 0;
18480 }
18481
18483 }
18484
18485 undumped_chars = 0;
18486
18487 // continue processing the string
18488 state = UTF8_ACCEPT;
18489 break;
18490 }
18491
18492 default: // LCOV_EXCL_LINE
18493 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18494 }
18495 break;
18496 }
18497
18498 default: // decode found yet incomplete multi-byte code point
18499 {
18500 if (!ensure_ascii)
18501 {
18502 // code point will not be escaped - copy byte to buffer
18503 string_buffer[bytes++] = s[i];
18504 }
18506 break;
18507 }
18508 }
18509 }
18510
18511 // we finished processing the string
18512 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
18513 {
18514 // write buffer
18515 if (bytes > 0)
18516 {
18517 o->write_characters(string_buffer.data(), bytes);
18518 }
18519 }
18520 else
18521 {
18522 // we finish reading, but do not accept: string was incomplete
18523 switch (error_handler)
18524 {
18526 {
18527 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));
18528 }
18529
18531 {
18532 // write all accepted bytes
18533 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18534 break;
18535 }
18536
18538 {
18539 // write all accepted bytes
18540 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18541 // add a replacement character
18542 if (ensure_ascii)
18543 {
18544 o->write_characters("\\ufffd", 6);
18545 }
18546 else
18547 {
18548 o->write_characters("\xEF\xBF\xBD", 3);
18549 }
18550 break;
18551 }
18552
18553 default: // LCOV_EXCL_LINE
18554 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18555 }
18556 }
18557 }
18558
18559 private:
18568 inline unsigned int count_digits(number_unsigned_t x) noexcept
18569 {
18570 unsigned int n_digits = 1;
18571 for (;;)
18572 {
18573 if (x < 10)
18574 {
18575 return n_digits;
18576 }
18577 if (x < 100)
18578 {
18579 return n_digits + 1;
18580 }
18581 if (x < 1000)
18582 {
18583 return n_digits + 2;
18584 }
18585 if (x < 10000)
18586 {
18587 return n_digits + 3;
18588 }
18589 x = x / 10000u;
18590 n_digits += 4;
18591 }
18592 }
18593
18599 static std::string hex_bytes(std::uint8_t byte)
18600 {
18601 std::string result = "FF";
18602 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
18603 result[0] = nibble_to_hex[byte / 16];
18604 result[1] = nibble_to_hex[byte % 16];
18605 return result;
18606 }
18607
18608 // templates to avoid warnings about useless casts
18609 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
18610 bool is_negative_number(NumberType x)
18611 {
18612 return x < 0;
18613 }
18614
18615 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
18616 bool is_negative_number(NumberType /*unused*/)
18617 {
18618 return false;
18619 }
18620
18630 template < typename NumberType, detail::enable_if_t <
18631 std::is_integral<NumberType>::value ||
18632 std::is_same<NumberType, number_unsigned_t>::value ||
18633 std::is_same<NumberType, number_integer_t>::value ||
18634 std::is_same<NumberType, binary_char_t>::value,
18635 int > = 0 >
18636 void dump_integer(NumberType x)
18637 {
18638 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18639 {
18640 {
18641 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
18642 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
18643 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
18644 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
18645 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
18646 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
18647 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
18648 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
18649 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
18650 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
18651 }
18652 };
18653
18654 // special case for "0"
18655 if (x == 0)
18656 {
18657 o->write_character('0');
18658 return;
18659 }
18660
18661 // use a pointer to fill the buffer
18662 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18663
18664 number_unsigned_t abs_value;
18665
18666 unsigned int n_chars{};
18667
18668 if (is_negative_number(x))
18669 {
18670 *buffer_ptr = '-';
18671 abs_value = remove_sign(static_cast<number_integer_t>(x));
18672
18673 // account one more byte for the minus sign
18674 n_chars = 1 + count_digits(abs_value);
18675 }
18676 else
18677 {
18678 abs_value = static_cast<number_unsigned_t>(x);
18679 n_chars = count_digits(abs_value);
18680 }
18681
18682 // spare 1 byte for '\0'
18683 JSON_ASSERT(n_chars < number_buffer.size() - 1);
18684
18685 // jump to the end to generate the string from backward,
18686 // so we later avoid reversing the result
18687 buffer_ptr += n_chars;
18688
18689 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
18690 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
18691 while (abs_value >= 100)
18692 {
18693 const auto digits_index = static_cast<unsigned>((abs_value % 100));
18694 abs_value /= 100;
18695 *(--buffer_ptr) = digits_to_99[digits_index][1];
18696 *(--buffer_ptr) = digits_to_99[digits_index][0];
18697 }
18698
18699 if (abs_value >= 10)
18700 {
18701 const auto digits_index = static_cast<unsigned>(abs_value);
18702 *(--buffer_ptr) = digits_to_99[digits_index][1];
18703 *(--buffer_ptr) = digits_to_99[digits_index][0];
18704 }
18705 else
18706 {
18707 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
18708 }
18709
18710 o->write_characters(number_buffer.data(), n_chars);
18711 }
18712
18721 void dump_float(number_float_t x)
18722 {
18723 // NaN / inf
18724 if (!std::isfinite(x))
18725 {
18726 o->write_characters("null", 4);
18727 return;
18728 }
18729
18730 // If number_float_t is an IEEE-754 single or double precision number,
18731 // use the Grisu2 algorithm to produce short numbers which are
18732 // guaranteed to round-trip, using strtof and strtod, resp.
18733 //
18734 // NB: The test below works if <long double> == <double>.
18735 static constexpr bool is_ieee_single_or_double
18736 = (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) ||
18737 (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);
18738
18739 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
18740 }
18741
18742 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
18743 {
18744 auto* begin = number_buffer.data();
18745 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
18746
18747 o->write_characters(begin, static_cast<size_t>(end - begin));
18748 }
18749
18750 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
18751 {
18752 // get number of digits for a float -> text -> float round-trip
18753 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
18754
18755 // the actual conversion
18756 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18757 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
18758
18759 // negative value indicates an error
18760 JSON_ASSERT(len > 0);
18761 // check if buffer was large enough
18762 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
18763
18764 // erase thousands separator
18765 if (thousands_sep != '\0')
18766 {
18767 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
18768 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
18769 std::fill(end, number_buffer.end(), '\0');
18770 JSON_ASSERT((end - number_buffer.begin()) <= len);
18771 len = (end - number_buffer.begin());
18772 }
18773
18774 // convert decimal point to '.'
18775 if (decimal_point != '\0' && decimal_point != '.')
18776 {
18777 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
18778 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
18779 if (dec_pos != number_buffer.end())
18780 {
18781 *dec_pos = '.';
18782 }
18783 }
18784
18785 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
18786
18787 // determine if we need to append ".0"
18788 const bool value_is_int_like =
18789 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
18790 [](char c)
18791 {
18792 return c == '.' || c == 'e';
18793 });
18794
18795 if (value_is_int_like)
18796 {
18797 o->write_characters(".0", 2);
18798 }
18799 }
18800
18822 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
18823 {
18824 static const std::array<std::uint8_t, 400> utf8d =
18825 {
18826 {
18827 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
18828 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
18829 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
18830 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
18831 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
18832 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
18833 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
18834 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
18835 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
18836 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
18837 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
18838 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
18839 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
18840 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
18841 }
18842 };
18843
18844 JSON_ASSERT(byte < utf8d.size());
18845 const std::uint8_t type = utf8d[byte];
18846
18847 codep = (state != UTF8_ACCEPT)
18848 ? (byte & 0x3fu) | (codep << 6u)
18849 : (0xFFu >> type) & (byte);
18850
18851 const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
18852 JSON_ASSERT(index < utf8d.size());
18853 state = utf8d[index];
18854 return state;
18855 }
18856
18857 /*
18858 * Overload to make the compiler happy while it is instantiating
18859 * dump_integer for number_unsigned_t.
18860 * Must never be called.
18861 */
18862 number_unsigned_t remove_sign(number_unsigned_t x)
18863 {
18864 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18865 return x; // LCOV_EXCL_LINE
18866 }
18867
18868 /*
18869 * Helper function for dump_integer
18870 *
18871 * This function takes a negative signed integer and returns its absolute
18872 * value as unsigned integer. The plus/minus shuffling is necessary as we can
18873 * not directly remove the sign of an arbitrary signed integer as the
18874 * absolute values of INT_MIN and INT_MAX are usually not the same. See
18875 * #1708 for details.
18876 */
18877 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
18878 {
18879 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
18880 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
18881 }
18882
18883 private:
18885 output_adapter_t<char> o = nullptr;
18886
18888 std::array<char, 64> number_buffer{{}};
18889
18891 const std::lconv* loc = nullptr;
18893 const char thousands_sep = '\0';
18895 const char decimal_point = '\0';
18896
18898 std::array<char, 512> string_buffer{{}};
18899
18901 const char indent_char;
18904
18907};
18908
18909} // namespace detail
18911
18912// #include <nlohmann/detail/value_t.hpp>
18913
18914// #include <nlohmann/json_fwd.hpp>
18915
18916// #include <nlohmann/ordered_map.hpp>
18917// __ _____ _____ _____
18918// __| | __| | | | JSON for Modern C++
18919// | | |__ | | | | | | version 3.11.2
18920// |_____|_____|_____|_|___| https://github.com/nlohmann/json
18921//
18922// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
18923// SPDX-License-Identifier: MIT
18924
18925
18926
18927#include <functional> // equal_to, less
18928#include <initializer_list> // initializer_list
18929#include <iterator> // input_iterator_tag, iterator_traits
18930#include <memory> // allocator
18931#include <stdexcept> // for out_of_range
18932#include <type_traits> // enable_if, is_convertible
18933#include <utility> // pair
18934#include <vector> // vector
18935
18936// #include <nlohmann/detail/macro_scope.hpp>
18937
18938// #include <nlohmann/detail/meta/type_traits.hpp>
18939
18940
18942
18945template <class Key, class T, class IgnoredLess = std::less<Key>,
18946 class Allocator = std::allocator<std::pair<const Key, T>>>
18947 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
18948{
18949 using key_type = Key;
18950 using mapped_type = T;
18951 using Container = std::vector<std::pair<const Key, T>, Allocator>;
18952 using iterator = typename Container::iterator;
18953 using const_iterator = typename Container::const_iterator;
18954 using size_type = typename Container::size_type;
18955 using value_type = typename Container::value_type;
18956#ifdef JSON_HAS_CPP_14
18957 using key_compare = std::equal_to<>;
18958#else
18959 using key_compare = std::equal_to<Key>;
18960#endif
18961
18962 // Explicit constructors instead of `using Container::Container`
18963 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
18964 ordered_map() noexcept(noexcept(Container())) : Container{} {}
18965 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
18966 template <class It>
18967 ordered_map(It first, It last, const Allocator& alloc = Allocator())
18968 : Container{first, last, alloc} {}
18969 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
18970 : Container{init, alloc} {}
18971
18972 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
18973 {
18974 for (auto it = this->begin(); it != this->end(); ++it)
18975 {
18976 if (m_compare(it->first, key))
18977 {
18978 return {it, false};
18979 }
18980 }
18981 Container::emplace_back(key, std::forward<T>(t));
18982 return {std::prev(this->end()), true};
18983 }
18984
18985 template<class KeyType, detail::enable_if_t<
18987 std::pair<iterator, bool> emplace(KeyType && key, T && t)
18988 {
18989 for (auto it = this->begin(); it != this->end(); ++it)
18990 {
18991 if (m_compare(it->first, key))
18992 {
18993 return {it, false};
18994 }
18995 }
18996 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
18997 return {std::prev(this->end()), true};
18998 }
18999
19000 T& operator[](const key_type& key)
19001 {
19002 return emplace(key, T{}).first->second;
19003 }
19004
19005 template<class KeyType, detail::enable_if_t<
19007 T & operator[](KeyType && key)
19008 {
19009 return emplace(std::forward<KeyType>(key), T{}).first->second;
19010 }
19011
19012 const T& operator[](const key_type& key) const
19013 {
19014 return at(key);
19015 }
19016
19017 template<class KeyType, detail::enable_if_t<
19019 const T & operator[](KeyType && key) const
19020 {
19021 return at(std::forward<KeyType>(key));
19022 }
19023
19024 T& at(const key_type& key)
19025 {
19026 for (auto it = this->begin(); it != this->end(); ++it)
19027 {
19028 if (m_compare(it->first, key))
19029 {
19030 return it->second;
19031 }
19032 }
19033
19034 JSON_THROW(std::out_of_range("key not found"));
19035 }
19036
19037 template<class KeyType, detail::enable_if_t<
19039 T & at(KeyType && key)
19040 {
19041 for (auto it = this->begin(); it != this->end(); ++it)
19042 {
19043 if (m_compare(it->first, key))
19044 {
19045 return it->second;
19046 }
19047 }
19048
19049 JSON_THROW(std::out_of_range("key not found"));
19050 }
19051
19052 const T& at(const key_type& key) const
19053 {
19054 for (auto it = this->begin(); it != this->end(); ++it)
19055 {
19056 if (m_compare(it->first, key))
19057 {
19058 return it->second;
19059 }
19060 }
19061
19062 JSON_THROW(std::out_of_range("key not found"));
19063 }
19064
19065 template<class KeyType, detail::enable_if_t<
19067 const T & at(KeyType && key) const
19068 {
19069 for (auto it = this->begin(); it != this->end(); ++it)
19070 {
19071 if (m_compare(it->first, key))
19072 {
19073 return it->second;
19074 }
19075 }
19076
19077 JSON_THROW(std::out_of_range("key not found"));
19078 }
19079
19081 {
19082 for (auto it = this->begin(); it != this->end(); ++it)
19083 {
19084 if (m_compare(it->first, key))
19085 {
19086 // Since we cannot move const Keys, re-construct them in place
19087 for (auto next = it; ++next != this->end(); ++it)
19088 {
19089 it->~value_type(); // Destroy but keep allocation
19090 new (&*it) value_type{std::move(*next)};
19091 }
19092 Container::pop_back();
19093 return 1;
19094 }
19095 }
19096 return 0;
19097 }
19098
19099 template<class KeyType, detail::enable_if_t<
19101 size_type erase(KeyType && key)
19102 {
19103 for (auto it = this->begin(); it != this->end(); ++it)
19104 {
19105 if (m_compare(it->first, key))
19106 {
19107 // Since we cannot move const Keys, re-construct them in place
19108 for (auto next = it; ++next != this->end(); ++it)
19109 {
19110 it->~value_type(); // Destroy but keep allocation
19111 new (&*it) value_type{std::move(*next)};
19112 }
19113 Container::pop_back();
19114 return 1;
19115 }
19116 }
19117 return 0;
19118 }
19119
19121 {
19122 return erase(pos, std::next(pos));
19123 }
19124
19126 {
19127 if (first == last)
19128 {
19129 return first;
19130 }
19131
19132 const auto elements_affected = std::distance(first, last);
19133 const auto offset = std::distance(Container::begin(), first);
19134
19135 // This is the start situation. We need to delete elements_affected
19136 // elements (3 in this example: e, f, g), and need to return an
19137 // iterator past the last deleted element (h in this example).
19138 // Note that offset is the distance from the start of the vector
19139 // to first. We will need this later.
19140
19141 // [ a, b, c, d, e, f, g, h, i, j ]
19142 // ^ ^
19143 // first last
19144
19145 // Since we cannot move const Keys, we re-construct them in place.
19146 // We start at first and re-construct (viz. copy) the elements from
19147 // the back of the vector. Example for first iteration:
19148
19149 // ,--------.
19150 // v | destroy e and re-construct with h
19151 // [ a, b, c, d, e, f, g, h, i, j ]
19152 // ^ ^
19153 // it it + elements_affected
19154
19155 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19156 {
19157 it->~value_type(); // destroy but keep allocation
19158 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
19159 }
19160
19161 // [ a, b, c, d, h, i, j, h, i, j ]
19162 // ^ ^
19163 // first last
19164
19165 // remove the unneeded elements at the end of the vector
19166 Container::resize(this->size() - static_cast<size_type>(elements_affected));
19167
19168 // [ a, b, c, d, h, i, j ]
19169 // ^ ^
19170 // first last
19171
19172 // first is now pointing past the last deleted element, but we cannot
19173 // use this iterator, because it may have been invalidated by the
19174 // resize call. Instead, we can return begin() + offset.
19175 return Container::begin() + offset;
19176 }
19177
19178 size_type count(const key_type& key) const
19179 {
19180 for (auto it = this->begin(); it != this->end(); ++it)
19181 {
19182 if (m_compare(it->first, key))
19183 {
19184 return 1;
19185 }
19186 }
19187 return 0;
19188 }
19189
19190 template<class KeyType, detail::enable_if_t<
19192 size_type count(KeyType && key) const
19193 {
19194 for (auto it = this->begin(); it != this->end(); ++it)
19195 {
19196 if (m_compare(it->first, key))
19197 {
19198 return 1;
19199 }
19200 }
19201 return 0;
19202 }
19203
19205 {
19206 for (auto it = this->begin(); it != this->end(); ++it)
19207 {
19208 if (m_compare(it->first, key))
19209 {
19210 return it;
19211 }
19212 }
19213 return Container::end();
19214 }
19215
19216 template<class KeyType, detail::enable_if_t<
19218 iterator find(KeyType && key)
19219 {
19220 for (auto it = this->begin(); it != this->end(); ++it)
19221 {
19222 if (m_compare(it->first, key))
19223 {
19224 return it;
19225 }
19226 }
19227 return Container::end();
19228 }
19229
19230 const_iterator find(const key_type& key) const
19231 {
19232 for (auto it = this->begin(); it != this->end(); ++it)
19233 {
19234 if (m_compare(it->first, key))
19235 {
19236 return it;
19237 }
19238 }
19239 return Container::end();
19240 }
19241
19242 std::pair<iterator, bool> insert( value_type&& value )
19243 {
19244 return emplace(value.first, std::move(value.second));
19245 }
19246
19247 std::pair<iterator, bool> insert( const value_type& value )
19248 {
19249 for (auto it = this->begin(); it != this->end(); ++it)
19250 {
19251 if (m_compare(it->first, value.first))
19252 {
19253 return {it, false};
19254 }
19255 }
19256 Container::push_back(value);
19257 return {--this->end(), true};
19258 }
19259
19260 template<typename InputIt>
19261 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
19262 std::input_iterator_tag>::value>::type;
19263
19264 template<typename InputIt, typename = require_input_iter<InputIt>>
19265 void insert(InputIt first, InputIt last)
19266 {
19267 for (auto it = first; it != last; ++it)
19268 {
19269 insert(*it);
19270 }
19271 }
19272
19273private:
19275};
19276
19278
19279
19280#if defined(JSON_HAS_CPP_17)
19281 #include <any>
19282 #include <string_view>
19283#endif
19284
19291
19311class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
19312 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
19313{
19314 private:
19315 template<detail::value_t> friend struct detail::external_constructor;
19316
19317 template<typename>
19318 friend class ::nlohmann::json_pointer;
19319 // can be restored when json_pointer backwards compatibility is removed
19320 // friend ::nlohmann::json_pointer<StringType>;
19321
19322 template<typename BasicJsonType, typename InputType>
19323 friend class ::nlohmann::detail::parser;
19324 friend ::nlohmann::detail::serializer<basic_json>;
19325 template<typename BasicJsonType>
19326 friend class ::nlohmann::detail::iter_impl;
19327 template<typename BasicJsonType, typename CharType>
19328 friend class ::nlohmann::detail::binary_writer;
19329 template<typename BasicJsonType, typename InputType, typename SAX>
19330 friend class ::nlohmann::detail::binary_reader;
19331 template<typename BasicJsonType>
19332 friend class ::nlohmann::detail::json_sax_dom_parser;
19333 template<typename BasicJsonType>
19334 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
19335 friend class ::nlohmann::detail::exception;
19336
19338 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
19339 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
19340
19342 // convenience aliases for types residing in namespace detail;
19343 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
19344
19345 template<typename InputAdapterType>
19346 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
19347 InputAdapterType adapter,
19348 detail::parser_callback_t<basic_json>cb = nullptr,
19349 const bool allow_exceptions = true,
19350 const bool ignore_comments = false
19351 )
19352 {
19353 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
19354 std::move(cb), allow_exceptions, ignore_comments);
19355 }
19356
19357 private:
19358 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
19359 template<typename BasicJsonType>
19360 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
19361 template<typename BasicJsonType>
19362 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
19363 template<typename Iterator>
19364 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
19365 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
19366
19367 template<typename CharType>
19368 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
19369
19370 template<typename InputType>
19371 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
19372 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
19373
19375 using serializer = ::nlohmann::detail::serializer<basic_json>;
19376
19377 public:
19380 using json_pointer = ::nlohmann::json_pointer<StringType>;
19381 template<typename T, typename SFINAE>
19382 using json_serializer = JSONSerializer<T, SFINAE>;
19388 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
19389
19390 using input_format_t = detail::input_format_t;
19393
19395 // exceptions //
19397
19401
19408
19410
19411
19413 // container types //
19415
19420
19423
19428
19430 using difference_type = std::ptrdiff_t;
19432 using size_type = std::size_t;
19433
19435 using allocator_type = AllocatorType<basic_json>;
19436
19438 using pointer = typename std::allocator_traits<allocator_type>::pointer;
19440 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
19441
19443 using iterator = iter_impl<basic_json>;
19445 using const_iterator = iter_impl<const basic_json>;
19447 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
19449 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
19450
19452
19453
19457 {
19458 return allocator_type();
19459 }
19460
19465 {
19466 basic_json result;
19467
19468 result["copyright"] = "(C) 2013-2022 Niels Lohmann";
19469 result["name"] = "JSON for Modern C++";
19470 result["url"] = "https://github.com/nlohmann/json";
19471 result["version"]["string"] =
19472 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
19473 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
19474 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19475 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
19476 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
19477 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
19478
19479#ifdef _WIN32
19480 result["platform"] = "win32";
19481#elif defined __linux__
19482 result["platform"] = "linux";
19483#elif defined __APPLE__
19484 result["platform"] = "apple";
19485#elif defined __unix__
19486 result["platform"] = "unix";
19487#else
19488 result["platform"] = "unknown";
19489#endif
19490
19491#if defined(__ICC) || defined(__INTEL_COMPILER)
19492 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
19493#elif defined(__clang__)
19494 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
19495#elif defined(__GNUC__) || defined(__GNUG__)
19496 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
19497 std::to_string(__GNUC__), '.',
19498 std::to_string(__GNUC_MINOR__), '.',
19499 std::to_string(__GNUC_PATCHLEVEL__))
19500 }
19501 };
19502#elif defined(__HP_cc) || defined(__HP_aCC)
19503 result["compiler"] = "hp"
19504#elif defined(__IBMCPP__)
19505 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
19506#elif defined(_MSC_VER)
19507 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
19508#elif defined(__PGI)
19509 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
19510#elif defined(__SUNPRO_CC)
19511 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
19512#else
19513 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
19514#endif
19515
19516
19517#if defined(_MSVC_LANG)
19518 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
19519#elif defined(__cplusplus)
19520 result["compiler"]["c++"] = std::to_string(__cplusplus);
19521#else
19522 result["compiler"]["c++"] = "unknown";
19523#endif
19524 return result;
19525 }
19526
19527
19529 // JSON value data types //
19531
19536
19541#if defined(JSON_HAS_CPP_14)
19542 // use of transparent comparator avoids unnecessary repeated construction of temporaries
19543 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
19544 using default_object_comparator_t = std::less<>;
19545#else
19546 using default_object_comparator_t = std::less<StringType>;
19547#endif
19548
19551 using object_t = ObjectType<StringType,
19552 basic_json,
19554 AllocatorType<std::pair<const StringType,
19555 basic_json>>>;
19556
19559 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19560
19563 using string_t = StringType;
19564
19567 using boolean_t = BooleanType;
19568
19571 using number_integer_t = NumberIntegerType;
19572
19575 using number_unsigned_t = NumberUnsignedType;
19576
19579 using number_float_t = NumberFloatType;
19580
19583 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19584
19588
19590
19591 private:
19592
19594 template<typename T, typename... Args>
19596 static T* create(Args&& ... args)
19597 {
19598 AllocatorType<T> alloc;
19599 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19600
19601 auto deleter = [&](T * obj)
19602 {
19603 AllocatorTraits::deallocate(alloc, obj, 1);
19604 };
19605 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19606 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19607 JSON_ASSERT(obj != nullptr);
19608 return obj.release();
19609 }
19610
19612 // JSON value storage //
19614
19641 union json_value
19642 {
19646 array_t* array;
19648 string_t* string;
19650 binary_t* binary;
19652 boolean_t boolean;
19654 number_integer_t number_integer;
19656 number_unsigned_t number_unsigned;
19658 number_float_t number_float;
19659
19661 json_value() = default;
19663 json_value(boolean_t v) noexcept : boolean(v) {}
19665 json_value(number_integer_t v) noexcept : number_integer(v) {}
19667 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19669 json_value(number_float_t v) noexcept : number_float(v) {}
19671 json_value(value_t t)
19672 {
19673 switch (t)
19674 {
19675 case value_t::object:
19676 {
19677 object = create<object_t>();
19678 break;
19679 }
19680
19681 case value_t::array:
19682 {
19683 array = create<array_t>();
19684 break;
19685 }
19686
19687 case value_t::string:
19688 {
19689 string = create<string_t>("");
19690 break;
19691 }
19692
19693 case value_t::binary:
19694 {
19695 binary = create<binary_t>();
19696 break;
19697 }
19698
19699 case value_t::boolean:
19700 {
19701 boolean = static_cast<boolean_t>(false);
19702 break;
19703 }
19704
19705 case value_t::number_integer:
19706 {
19707 number_integer = static_cast<number_integer_t>(0);
19708 break;
19709 }
19710
19711 case value_t::number_unsigned:
19712 {
19713 number_unsigned = static_cast<number_unsigned_t>(0);
19714 break;
19715 }
19716
19717 case value_t::number_float:
19718 {
19719 number_float = static_cast<number_float_t>(0.0);
19720 break;
19721 }
19722
19723 case value_t::null:
19724 {
19725 object = nullptr; // silence warning, see #821
19726 break;
19727 }
19728
19729 case value_t::discarded:
19730 default:
19731 {
19732 object = nullptr; // silence warning, see #821
19733 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
19734 {
19735 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.2", nullptr)); // LCOV_EXCL_LINE
19736 }
19737 break;
19738 }
19739 }
19740 }
19741
19743 json_value(const string_t& value) : string(create<string_t>(value)) {}
19744
19746 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
19747
19749 json_value(const object_t& value) : object(create<object_t>(value)) {}
19750
19752 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
19753
19755 json_value(const array_t& value) : array(create<array_t>(value)) {}
19756
19758 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
19759
19761 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
19762
19764 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
19765
19767 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
19768
19770 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
19771
19772 void destroy(value_t t)
19773 {
19774 if (
19775 (t == value_t::object && object == nullptr) ||
19776 (t == value_t::array && array == nullptr) ||
19777 (t == value_t::string && string == nullptr) ||
19778 (t == value_t::binary && binary == nullptr)
19779 )
19780 {
19781 //not initialized (e.g. due to exception in the ctor)
19782 return;
19783 }
19784 if (t == value_t::array || t == value_t::object)
19785 {
19786 // flatten the current json_value to a heap-allocated stack
19787 std::vector<basic_json> stack;
19788
19789 // move the top-level items to stack
19790 if (t == value_t::array)
19791 {
19792 stack.reserve(array->size());
19793 std::move(array->begin(), array->end(), std::back_inserter(stack));
19794 }
19795 else
19796 {
19797 stack.reserve(object->size());
19798 for (auto&& it : *object)
19799 {
19800 stack.push_back(std::move(it.second));
19801 }
19802 }
19803
19804 while (!stack.empty())
19805 {
19806 // move the last item to local variable to be processed
19807 basic_json current_item(std::move(stack.back()));
19808 stack.pop_back();
19809
19810 // if current_item is array/object, move
19811 // its children to the stack to be processed later
19812 if (current_item.is_array())
19813 {
19814 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
19815
19816 current_item.m_data.m_value.array->clear();
19817 }
19818 else if (current_item.is_object())
19819 {
19820 for (auto&& it : *current_item.m_data.m_value.object)
19821 {
19822 stack.push_back(std::move(it.second));
19823 }
19824
19825 current_item.m_data.m_value.object->clear();
19826 }
19827
19828 // it's now safe that current_item get destructed
19829 // since it doesn't have any children
19830 }
19831 }
19832
19833 switch (t)
19834 {
19835 case value_t::object:
19836 {
19837 AllocatorType<object_t> alloc;
19838 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
19839 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
19840 break;
19841 }
19842
19843 case value_t::array:
19844 {
19845 AllocatorType<array_t> alloc;
19846 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
19847 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
19848 break;
19849 }
19850
19851 case value_t::string:
19852 {
19853 AllocatorType<string_t> alloc;
19854 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
19855 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
19856 break;
19857 }
19858
19859 case value_t::binary:
19860 {
19861 AllocatorType<binary_t> alloc;
19862 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
19863 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
19864 break;
19865 }
19866
19867 case value_t::null:
19868 case value_t::boolean:
19869 case value_t::number_integer:
19870 case value_t::number_unsigned:
19871 case value_t::number_float:
19872 case value_t::discarded:
19873 default:
19874 {
19875 break;
19876 }
19877 }
19878 }
19879 };
19880
19881 private:
19900 void assert_invariant(bool check_parents = true) const noexcept
19901 {
19902 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
19903 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
19904 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
19905 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
19906
19907#if JSON_DIAGNOSTICS
19908 JSON_TRY
19909 {
19910 // cppcheck-suppress assertWithSideEffect
19911 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
19912 {
19913 return j.m_parent == this;
19914 }));
19915 }
19916 JSON_CATCH(...) {} // LCOV_EXCL_LINE
19917#endif
19918 static_cast<void>(check_parents);
19919 }
19920
19921 void set_parents()
19922 {
19923#if JSON_DIAGNOSTICS
19924 switch (m_data.m_type)
19925 {
19926 case value_t::array:
19927 {
19928 for (auto& element : *m_data.m_value.array)
19929 {
19930 element.m_parent = this;
19931 }
19932 break;
19933 }
19934
19935 case value_t::object:
19936 {
19937 for (auto& element : *m_data.m_value.object)
19938 {
19939 element.second.m_parent = this;
19940 }
19941 break;
19942 }
19943
19944 case value_t::null:
19945 case value_t::string:
19946 case value_t::boolean:
19947 case value_t::number_integer:
19948 case value_t::number_unsigned:
19949 case value_t::number_float:
19950 case value_t::binary:
19951 case value_t::discarded:
19952 default:
19953 break;
19954 }
19955#endif
19956 }
19957
19958 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
19959 {
19960#if JSON_DIAGNOSTICS
19961 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
19962 {
19963 (it + i)->m_parent = this;
19964 }
19965#else
19966 static_cast<void>(count_set_parents);
19967#endif
19968 return it;
19969 }
19970
19971 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
19972 {
19973#if JSON_DIAGNOSTICS
19974 if (old_capacity != static_cast<std::size_t>(-1))
19975 {
19976 // see https://github.com/nlohmann/json/issues/2838
19977 JSON_ASSERT(type() == value_t::array);
19978 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
19979 {
19980 // capacity has changed: update all parents
19981 set_parents();
19982 return j;
19983 }
19984 }
19985
19986 // ordered_json uses a vector internally, so pointers could have
19987 // been invalidated; see https://github.com/nlohmann/json/issues/2962
19988#ifdef JSON_HEDLEY_MSVC_VERSION
19989#pragma warning(push )
19990#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
19991#endif
19993 {
19994 set_parents();
19995 return j;
19996 }
19997#ifdef JSON_HEDLEY_MSVC_VERSION
19998#pragma warning( pop )
19999#endif
20000
20001 j.m_parent = this;
20002#else
20003 static_cast<void>(j);
20004 static_cast<void>(old_capacity);
20005#endif
20006 return j;
20007 }
20008
20009 public:
20011 // JSON parser callback //
20013
20016 using parse_event_t = detail::parse_event_t;
20017
20020 using parser_callback_t = detail::parser_callback_t<basic_json>;
20021
20023 // constructors //
20025
20030
20034 : m_data(v)
20035 {
20036 assert_invariant();
20037 }
20038
20041 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20042 : basic_json(value_t::null)
20043 {
20044 assert_invariant();
20045 }
20046
20049 template < typename CompatibleType,
20053 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20054 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20055 std::forward<CompatibleType>(val))))
20056 {
20057 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20058 set_parents();
20059 assert_invariant();
20060 }
20061
20064 template < typename BasicJsonType,
20066 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20067 basic_json(const BasicJsonType& val)
20068 {
20069 using other_boolean_t = typename BasicJsonType::boolean_t;
20070 using other_number_float_t = typename BasicJsonType::number_float_t;
20071 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20072 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20073 using other_string_t = typename BasicJsonType::string_t;
20074 using other_object_t = typename BasicJsonType::object_t;
20075 using other_array_t = typename BasicJsonType::array_t;
20076 using other_binary_t = typename BasicJsonType::binary_t;
20077
20078 switch (val.type())
20079 {
20080 case value_t::boolean:
20081 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20082 break;
20083 case value_t::number_float:
20084 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20085 break;
20086 case value_t::number_integer:
20087 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20088 break;
20089 case value_t::number_unsigned:
20090 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20091 break;
20092 case value_t::string:
20093 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20094 break;
20095 case value_t::object:
20096 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20097 break;
20098 case value_t::array:
20099 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20100 break;
20101 case value_t::binary:
20102 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20103 break;
20104 case value_t::null:
20105 *this = nullptr;
20106 break;
20107 case value_t::discarded:
20108 m_data.m_type = value_t::discarded;
20109 break;
20110 default: // LCOV_EXCL_LINE
20111 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20112 }
20113 JSON_ASSERT(m_data.m_type == val.type());
20114 set_parents();
20115 assert_invariant();
20116 }
20117
20121 bool type_deduction = true,
20122 value_t manual_type = value_t::array)
20123 {
20124 // check if each element is an array with two elements whose first
20125 // element is a string
20126 bool is_an_object = std::all_of(init.begin(), init.end(),
20127 [](const detail::json_ref<basic_json>& element_ref)
20128 {
20129 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
20130 });
20131
20132 // adjust type if type deduction is not wanted
20133 if (!type_deduction)
20134 {
20135 // if array is wanted, do not create an object though possible
20136 if (manual_type == value_t::array)
20137 {
20138 is_an_object = false;
20139 }
20140
20141 // if object is wanted but impossible, throw an exception
20142 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20143 {
20144 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
20145 }
20146 }
20147
20148 if (is_an_object)
20149 {
20150 // the initializer list is a list of pairs -> create object
20151 m_data.m_type = value_t::object;
20152 m_data.m_value = value_t::object;
20153
20154 for (auto& element_ref : init)
20155 {
20156 auto element = element_ref.moved_or_copied();
20157 m_data.m_value.object->emplace(
20158 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
20159 std::move((*element.m_data.m_value.array)[1]));
20160 }
20161 }
20162 else
20163 {
20164 // the initializer list describes an array -> create array
20165 m_data.m_type = value_t::array;
20166 m_data.m_value.array = create<array_t>(init.begin(), init.end());
20167 }
20168
20169 set_parents();
20170 assert_invariant();
20171 }
20172
20176 static basic_json binary(const typename binary_t::container_type& init)
20177 {
20178 auto res = basic_json();
20179 res.m_data.m_type = value_t::binary;
20180 res.m_data.m_value = init;
20181 return res;
20182 }
20183
20187 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
20188 {
20189 auto res = basic_json();
20190 res.m_data.m_type = value_t::binary;
20191 res.m_data.m_value = binary_t(init, subtype);
20192 return res;
20193 }
20194
20198 static basic_json binary(typename binary_t::container_type&& init)
20199 {
20200 auto res = basic_json();
20201 res.m_data.m_type = value_t::binary;
20202 res.m_data.m_value = std::move(init);
20203 return res;
20204 }
20205
20209 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
20210 {
20211 auto res = basic_json();
20212 res.m_data.m_type = value_t::binary;
20213 res.m_data.m_value = binary_t(std::move(init), subtype);
20214 return res;
20215 }
20216
20221 {
20222 return basic_json(init, false, value_t::array);
20223 }
20224
20229 {
20230 return basic_json(init, false, value_t::object);
20231 }
20232
20236 m_data{cnt, val}
20237 {
20238 set_parents();
20239 assert_invariant();
20240 }
20241
20244 template < class InputIT, typename std::enable_if <
20245 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
20246 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
20247 basic_json(InputIT first, InputIT last)
20248 {
20249 JSON_ASSERT(first.m_object != nullptr);
20250 JSON_ASSERT(last.m_object != nullptr);
20251
20252 // make sure iterator fits the current value
20253 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20254 {
20255 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
20256 }
20257
20258 // copy type from first iterator
20259 m_data.m_type = first.m_object->m_data.m_type;
20260
20261 // check if iterator range is complete for primitive values
20262 switch (m_data.m_type)
20263 {
20264 case value_t::boolean:
20265 case value_t::number_float:
20266 case value_t::number_integer:
20267 case value_t::number_unsigned:
20268 case value_t::string:
20269 {
20270 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
20271 || !last.m_it.primitive_iterator.is_end()))
20272 {
20273 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
20274 }
20275 break;
20276 }
20277
20278 case value_t::null:
20279 case value_t::object:
20280 case value_t::array:
20281 case value_t::binary:
20282 case value_t::discarded:
20283 default:
20284 break;
20285 }
20286
20287 switch (m_data.m_type)
20288 {
20289 case value_t::number_integer:
20290 {
20291 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
20292 break;
20293 }
20294
20295 case value_t::number_unsigned:
20296 {
20297 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
20298 break;
20299 }
20300
20301 case value_t::number_float:
20302 {
20303 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
20304 break;
20305 }
20306
20307 case value_t::boolean:
20308 {
20309 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
20310 break;
20311 }
20312
20313 case value_t::string:
20314 {
20315 m_data.m_value = *first.m_object->m_data.m_value.string;
20316 break;
20317 }
20318
20319 case value_t::object:
20320 {
20321 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
20322 last.m_it.object_iterator);
20323 break;
20324 }
20325
20326 case value_t::array:
20327 {
20328 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
20329 last.m_it.array_iterator);
20330 break;
20331 }
20332
20333 case value_t::binary:
20334 {
20335 m_data.m_value = *first.m_object->m_data.m_value.binary;
20336 break;
20337 }
20338
20339 case value_t::null:
20340 case value_t::discarded:
20341 default:
20342 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
20343 }
20344
20345 set_parents();
20346 assert_invariant();
20347 }
20348
20349
20351 // other constructors and destructor //
20353
20354 template<typename JsonRef,
20356 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
20357 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
20358
20362 : json_base_class_t(other)
20363 {
20364 m_data.m_type = other.m_data.m_type;
20365 // check of passed value is valid
20366 other.assert_invariant();
20367
20368 switch (m_data.m_type)
20369 {
20370 case value_t::object:
20371 {
20372 m_data.m_value = *other.m_data.m_value.object;
20373 break;
20374 }
20375
20376 case value_t::array:
20377 {
20378 m_data.m_value = *other.m_data.m_value.array;
20379 break;
20380 }
20381
20382 case value_t::string:
20383 {
20384 m_data.m_value = *other.m_data.m_value.string;
20385 break;
20386 }
20387
20388 case value_t::boolean:
20389 {
20390 m_data.m_value = other.m_data.m_value.boolean;
20391 break;
20392 }
20393
20394 case value_t::number_integer:
20395 {
20396 m_data.m_value = other.m_data.m_value.number_integer;
20397 break;
20398 }
20399
20400 case value_t::number_unsigned:
20401 {
20402 m_data.m_value = other.m_data.m_value.number_unsigned;
20403 break;
20404 }
20405
20406 case value_t::number_float:
20407 {
20408 m_data.m_value = other.m_data.m_value.number_float;
20409 break;
20410 }
20411
20412 case value_t::binary:
20413 {
20414 m_data.m_value = *other.m_data.m_value.binary;
20415 break;
20416 }
20417
20418 case value_t::null:
20419 case value_t::discarded:
20420 default:
20421 break;
20422 }
20423
20424 set_parents();
20425 assert_invariant();
20426 }
20427
20430 basic_json(basic_json&& other) noexcept
20431 : json_base_class_t(std::forward<json_base_class_t>(other)),
20432 m_data(std::move(other.m_data))
20433 {
20434 // check that passed value is valid
20435 other.assert_invariant(false);
20436
20437 // invalidate payload
20438 other.m_data.m_type = value_t::null;
20439 other.m_data.m_value = {};
20440
20441 set_parents();
20442 assert_invariant();
20443 }
20444
20448 std::is_nothrow_move_constructible<value_t>::value&&
20449 std::is_nothrow_move_assignable<value_t>::value&&
20450 std::is_nothrow_move_constructible<json_value>::value&&
20451 std::is_nothrow_move_assignable<json_value>::value&&
20452 std::is_nothrow_move_assignable<json_base_class_t>::value
20453 )
20454 {
20455 // check that passed value is valid
20456 other.assert_invariant();
20457
20458 using std::swap;
20459 swap(m_data.m_type, other.m_data.m_type);
20460 swap(m_data.m_value, other.m_data.m_value);
20461 json_base_class_t::operator=(std::move(other));
20462
20463 set_parents();
20464 assert_invariant();
20465 return *this;
20466 }
20467
20470 ~basic_json() noexcept
20471 {
20472 assert_invariant(false);
20473 }
20474
20476
20477 public:
20479 // object inspection //
20481
20485
20488 string_t dump(const int indent = -1,
20489 const char indent_char = ' ',
20490 const bool ensure_ascii = false,
20491 const error_handler_t error_handler = error_handler_t::strict) const
20492 {
20493 string_t result;
20494 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
20495
20496 if (indent >= 0)
20497 {
20498 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
20499 }
20500 else
20501 {
20502 s.dump(*this, false, ensure_ascii, 0);
20503 }
20504
20505 return result;
20506 }
20507
20510 constexpr value_t type() const noexcept
20511 {
20512 return m_data.m_type;
20513 }
20514
20517 constexpr bool is_primitive() const noexcept
20518 {
20519 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20520 }
20521
20524 constexpr bool is_structured() const noexcept
20525 {
20526 return is_array() || is_object();
20527 }
20528
20531 constexpr bool is_null() const noexcept
20532 {
20533 return m_data.m_type == value_t::null;
20534 }
20535
20538 constexpr bool is_boolean() const noexcept
20539 {
20540 return m_data.m_type == value_t::boolean;
20541 }
20542
20545 constexpr bool is_number() const noexcept
20546 {
20547 return is_number_integer() || is_number_float();
20548 }
20549
20552 constexpr bool is_number_integer() const noexcept
20553 {
20554 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
20555 }
20556
20559 constexpr bool is_number_unsigned() const noexcept
20560 {
20561 return m_data.m_type == value_t::number_unsigned;
20562 }
20563
20566 constexpr bool is_number_float() const noexcept
20567 {
20568 return m_data.m_type == value_t::number_float;
20569 }
20570
20573 constexpr bool is_object() const noexcept
20574 {
20575 return m_data.m_type == value_t::object;
20576 }
20577
20580 constexpr bool is_array() const noexcept
20581 {
20582 return m_data.m_type == value_t::array;
20583 }
20584
20587 constexpr bool is_string() const noexcept
20588 {
20589 return m_data.m_type == value_t::string;
20590 }
20591
20594 constexpr bool is_binary() const noexcept
20595 {
20596 return m_data.m_type == value_t::binary;
20597 }
20598
20601 constexpr bool is_discarded() const noexcept
20602 {
20603 return m_data.m_type == value_t::discarded;
20604 }
20605
20608 constexpr operator value_t() const noexcept
20609 {
20610 return m_data.m_type;
20611 }
20612
20614
20615 private:
20617 // value access //
20619
20621 boolean_t get_impl(boolean_t* /*unused*/) const
20622 {
20624 {
20625 return m_data.m_value.boolean;
20626 }
20627
20628 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
20629 }
20630
20632 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
20633 {
20634 return is_object() ? m_data.m_value.object : nullptr;
20635 }
20636
20638 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
20639 {
20640 return is_object() ? m_data.m_value.object : nullptr;
20641 }
20642
20644 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
20645 {
20646 return is_array() ? m_data.m_value.array : nullptr;
20647 }
20648
20650 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
20651 {
20652 return is_array() ? m_data.m_value.array : nullptr;
20653 }
20654
20656 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
20657 {
20658 return is_string() ? m_data.m_value.string : nullptr;
20659 }
20660
20662 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
20663 {
20664 return is_string() ? m_data.m_value.string : nullptr;
20665 }
20666
20668 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
20669 {
20670 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20671 }
20672
20674 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
20675 {
20676 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20677 }
20678
20680 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
20681 {
20682 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20683 }
20684
20686 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
20687 {
20688 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20689 }
20690
20692 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
20693 {
20694 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20695 }
20696
20698 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
20699 {
20700 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20701 }
20702
20704 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
20705 {
20706 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20707 }
20708
20710 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
20711 {
20712 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20713 }
20714
20716 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
20717 {
20718 return is_binary() ? m_data.m_value.binary : nullptr;
20719 }
20720
20722 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
20723 {
20724 return is_binary() ? m_data.m_value.binary : nullptr;
20725 }
20726
20738 template<typename ReferenceType, typename ThisType>
20739 static ReferenceType get_ref_impl(ThisType& obj)
20740 {
20741 // delegate the call to get_ptr<>()
20742 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
20743
20744 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
20745 {
20746 return *ptr;
20747 }
20748
20749 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
20750 }
20751
20752 public:
20756
20759 template<typename PointerType, typename std::enable_if<
20760 std::is_pointer<PointerType>::value, int>::type = 0>
20761 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20762 {
20763 // delegate the call to get_impl_ptr<>()
20764 return get_impl_ptr(static_cast<PointerType>(nullptr));
20765 }
20766
20769 template < typename PointerType, typename std::enable_if <
20770 std::is_pointer<PointerType>::value&&
20771 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
20772 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20773 {
20774 // delegate the call to get_impl_ptr<>() const
20775 return get_impl_ptr(static_cast<PointerType>(nullptr));
20776 }
20777
20778 private:
20817 template < typename ValueType,
20821 int > = 0 >
20822 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
20823 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
20824 {
20825 auto ret = ValueType();
20826 JSONSerializer<ValueType>::from_json(*this, ret);
20827 return ret;
20828 }
20829
20860 template < typename ValueType,
20863 int > = 0 >
20864 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
20865 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
20866 {
20867 return JSONSerializer<ValueType>::from_json(*this);
20868 }
20869
20885 template < typename BasicJsonType,
20888 int > = 0 >
20889 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
20890 {
20891 return *this;
20892 }
20893
20908 template<typename BasicJsonType,
20910 std::is_same<BasicJsonType, basic_json_t>::value,
20911 int> = 0>
20912 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
20913 {
20914 return *this;
20915 }
20916
20921 template<typename PointerType,
20923 std::is_pointer<PointerType>::value,
20924 int> = 0>
20925 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
20926 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
20927 {
20928 // delegate the call to get_ptr
20929 return get_ptr<PointerType>();
20930 }
20931
20932 public:
20956 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
20957#if defined(JSON_HAS_CPP_14)
20958 constexpr
20959#endif
20960 auto get() const noexcept(
20961 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
20962 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
20963 {
20964 // we cannot static_assert on ValueTypeCV being non-const, because
20965 // there is support for get<const basic_json_t>(), which is why we
20966 // still need the uncvref
20967 static_assert(!std::is_reference<ValueTypeCV>::value,
20968 "get() cannot be used with reference types, you might want to use get_ref()");
20969 return get_impl<ValueType>(detail::priority_tag<4> {});
20970 }
20971
20999 template<typename PointerType, typename std::enable_if<
21000 std::is_pointer<PointerType>::value, int>::type = 0>
21001 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21002 {
21003 // delegate the call to get_ptr
21004 return get_ptr<PointerType>();
21005 }
21006
21009 template < typename ValueType,
21013 int > = 0 >
21014 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21015 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21016 {
21017 JSONSerializer<ValueType>::from_json(*this, v);
21018 return v;
21019 }
21020
21021 // specialization to allow calling get_to with a basic_json value
21022 // see https://github.com/nlohmann/json/issues/2175
21023 template<typename ValueType,
21026 int> = 0>
21027 ValueType & get_to(ValueType& v) const
21028 {
21029 v = *this;
21030 return v;
21031 }
21032
21033 template <
21034 typename T, std::size_t N,
21035 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21038 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21039 noexcept(noexcept(JSONSerializer<Array>::from_json(
21040 std::declval<const basic_json_t&>(), v)))
21041 {
21042 JSONSerializer<Array>::from_json(*this, v);
21043 return v;
21044 }
21045
21048 template<typename ReferenceType, typename std::enable_if<
21049 std::is_reference<ReferenceType>::value, int>::type = 0>
21050 ReferenceType get_ref()
21051 {
21052 // delegate call to get_ref_impl
21053 return get_ref_impl<ReferenceType>(*this);
21054 }
21055
21058 template < typename ReferenceType, typename std::enable_if <
21059 std::is_reference<ReferenceType>::value&&
21060 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21061 ReferenceType get_ref() const
21062 {
21063 // delegate call to get_ref_impl
21064 return get_ref_impl<ReferenceType>(*this);
21065 }
21066
21096 template < typename ValueType, typename std::enable_if <
21104#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21106#endif
21107#if defined(JSON_HAS_CPP_17)
21109#endif
21111 >::value, int >::type = 0 >
21112 JSON_EXPLICIT operator ValueType() const
21113 {
21114 // delegate the call to get<>() const
21115 return get<ValueType>();
21116 }
21117
21121 {
21122 if (!is_binary())
21123 {
21124 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21125 }
21126
21127 return *get_ptr<binary_t*>();
21128 }
21129
21132 const binary_t& get_binary() const
21133 {
21134 if (!is_binary())
21135 {
21136 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21137 }
21138
21139 return *get_ptr<const binary_t*>();
21140 }
21141
21143
21144
21146 // element access //
21148
21152
21156 {
21157 // at only works for arrays
21159 {
21160 JSON_TRY
21161 {
21162 return set_parent(m_data.m_value.array->at(idx));
21163 }
21164 JSON_CATCH (std::out_of_range&)
21165 {
21166 // create better exception explanation
21167 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21168 }
21169 }
21170 else
21171 {
21172 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21173 }
21174 }
21175
21179 {
21180 // at only works for arrays
21182 {
21183 JSON_TRY
21184 {
21185 return m_data.m_value.array->at(idx);
21186 }
21187 JSON_CATCH (std::out_of_range&)
21188 {
21189 // create better exception explanation
21190 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21191 }
21192 }
21193 else
21194 {
21195 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21196 }
21197 }
21198
21201 reference at(const typename object_t::key_type& key)
21202 {
21203 // at only works for objects
21205 {
21206 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21207 }
21208
21209 auto it = m_data.m_value.object->find(key);
21210 if (it == m_data.m_value.object->end())
21211 {
21212 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21213 }
21214 return set_parent(it->second);
21215 }
21216
21219 template<class KeyType, detail::enable_if_t<
21221 reference at(KeyType && key)
21222 {
21223 // at only works for objects
21225 {
21226 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21227 }
21228
21229 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21230 if (it == m_data.m_value.object->end())
21231 {
21232 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21233 }
21234 return set_parent(it->second);
21235 }
21236
21239 const_reference at(const typename object_t::key_type& key) const
21240 {
21241 // at only works for objects
21243 {
21244 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21245 }
21246
21247 auto it = m_data.m_value.object->find(key);
21248 if (it == m_data.m_value.object->end())
21249 {
21250 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21251 }
21252 return it->second;
21253 }
21254
21257 template<class KeyType, detail::enable_if_t<
21259 const_reference at(KeyType && key) const
21260 {
21261 // at only works for objects
21263 {
21264 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21265 }
21266
21267 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21268 if (it == m_data.m_value.object->end())
21269 {
21270 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21271 }
21272 return it->second;
21273 }
21274
21278 {
21279 // implicitly convert null value to an empty array
21280 if (is_null())
21281 {
21282 m_data.m_type = value_t::array;
21283 m_data.m_value.array = create<array_t>();
21284 assert_invariant();
21285 }
21286
21287 // operator[] only works for arrays
21289 {
21290 // fill up array with null values if given idx is outside range
21291 if (idx >= m_data.m_value.array->size())
21292 {
21293#if JSON_DIAGNOSTICS
21294 // remember array size & capacity before resizing
21295 const auto old_size = m_data.m_value.array->size();
21296 const auto old_capacity = m_data.m_value.array->capacity();
21297#endif
21298 m_data.m_value.array->resize(idx + 1);
21299
21300#if JSON_DIAGNOSTICS
21301 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
21302 {
21303 // capacity has changed: update all parents
21304 set_parents();
21305 }
21306 else
21307 {
21308 // set parent for values added above
21309 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
21310 }
21311#endif
21312 assert_invariant();
21313 }
21314
21315 return m_data.m_value.array->operator[](idx);
21316 }
21317
21318 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21319 }
21320
21324 {
21325 // const operator[] only works for arrays
21327 {
21328 return m_data.m_value.array->operator[](idx);
21329 }
21330
21331 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21332 }
21333
21336 reference operator[](typename object_t::key_type key)
21337 {
21338 // implicitly convert null value to an empty object
21339 if (is_null())
21340 {
21341 m_data.m_type = value_t::object;
21342 m_data.m_value.object = create<object_t>();
21343 assert_invariant();
21344 }
21345
21346 // operator[] only works for objects
21348 {
21349 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
21350 return set_parent(result.first->second);
21351 }
21352
21353 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21354 }
21355
21358 const_reference operator[](const typename object_t::key_type& key) const
21359 {
21360 // const operator[] only works for objects
21362 {
21363 auto it = m_data.m_value.object->find(key);
21364 JSON_ASSERT(it != m_data.m_value.object->end());
21365 return it->second;
21366 }
21367
21368 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21369 }
21370
21371 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
21372 // (they seemingly cannot be constrained to resolve the ambiguity)
21373 template<typename T>
21375 {
21376 return operator[](typename object_t::key_type(key));
21377 }
21378
21379 template<typename T>
21381 {
21382 return operator[](typename object_t::key_type(key));
21383 }
21384
21387 template<class KeyType, detail::enable_if_t<
21389 reference operator[](KeyType && key)
21390 {
21391 // implicitly convert null value to an empty object
21392 if (is_null())
21393 {
21394 m_data.m_type = value_t::object;
21395 m_data.m_value.object = create<object_t>();
21396 assert_invariant();
21397 }
21398
21399 // operator[] only works for objects
21401 {
21402 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
21403 return set_parent(result.first->second);
21404 }
21405
21406 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21407 }
21408
21411 template<class KeyType, detail::enable_if_t<
21413 const_reference operator[](KeyType && key) const
21414 {
21415 // const operator[] only works for objects
21417 {
21418 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21419 JSON_ASSERT(it != m_data.m_value.object->end());
21420 return it->second;
21421 }
21422
21423 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21424 }
21425
21426 private:
21427 template<typename KeyType>
21428 using is_comparable_with_object_key = detail::is_comparable <
21429 object_comparator_t, const typename object_t::key_type&, KeyType >;
21430
21431 template<typename ValueType>
21432 using value_return_type = std::conditional <
21434 string_t, typename std::decay<ValueType>::type >;
21435
21436 public:
21439 template < class ValueType, detail::enable_if_t <
21442 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21443 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
21444 {
21445 // value only works for objects
21447 {
21448 // if key is found, return value and given default value otherwise
21449 const auto it = find(key);
21450 if (it != end())
21451 {
21452 return it->template get<ValueType>();
21453 }
21454
21455 return default_value;
21456 }
21457
21458 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21459 }
21460
21463 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21467 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21468 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
21469 {
21470 // value only works for objects
21472 {
21473 // if key is found, return value and given default value otherwise
21474 const auto it = find(key);
21475 if (it != end())
21476 {
21477 return it->template get<ReturnType>();
21478 }
21479
21480 return std::forward<ValueType>(default_value);
21481 }
21482
21483 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21484 }
21485
21488 template < class ValueType, class KeyType, detail::enable_if_t <
21491 && is_comparable_with_object_key<KeyType>::value
21493 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21494 ValueType value(KeyType && key, const ValueType& default_value) const
21495 {
21496 // value only works for objects
21498 {
21499 // if key is found, return value and given default value otherwise
21500 const auto it = find(std::forward<KeyType>(key));
21501 if (it != end())
21502 {
21503 return it->template get<ValueType>();
21504 }
21505
21506 return default_value;
21507 }
21508
21509 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21510 }
21511
21514 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
21518 && is_comparable_with_object_key<KeyType>::value
21520 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21521 ReturnType value(KeyType && key, ValueType && default_value) const
21522 {
21523 // value only works for objects
21525 {
21526 // if key is found, return value and given default value otherwise
21527 const auto it = find(std::forward<KeyType>(key));
21528 if (it != end())
21529 {
21530 return it->template get<ReturnType>();
21531 }
21532
21533 return std::forward<ValueType>(default_value);
21534 }
21535
21536 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21537 }
21538
21541 template < class ValueType, detail::enable_if_t <
21543 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21544 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
21545 {
21546 // value only works for objects
21548 {
21549 // if pointer resolves a value, return it or use default value
21550 JSON_TRY
21551 {
21552 return ptr.get_checked(this).template get<ValueType>();
21553 }
21555 {
21556 return default_value;
21557 }
21558 }
21559
21560 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21561 }
21562
21565 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21568 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21569 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
21570 {
21571 // value only works for objects
21573 {
21574 // if pointer resolves a value, return it or use default value
21575 JSON_TRY
21576 {
21577 return ptr.get_checked(this).template get<ReturnType>();
21578 }
21580 {
21581 return std::forward<ValueType>(default_value);
21582 }
21583 }
21584
21585 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21586 }
21587
21588 template < class ValueType, class BasicJsonType, detail::enable_if_t <
21591 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21592 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21593 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
21594 {
21595 return value(ptr.convert(), default_value);
21596 }
21597
21598 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
21602 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21603 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21604 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
21605 {
21606 return value(ptr.convert(), std::forward<ValueType>(default_value));
21607 }
21608
21612 {
21613 return *begin();
21614 }
21615
21619 {
21620 return *cbegin();
21621 }
21622
21626 {
21627 auto tmp = end();
21628 --tmp;
21629 return *tmp;
21630 }
21631
21635 {
21636 auto tmp = cend();
21637 --tmp;
21638 return *tmp;
21639 }
21640
21643 template < class IteratorType, detail::enable_if_t <
21644 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21645 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21646 IteratorType erase(IteratorType pos)
21647 {
21648 // make sure iterator fits the current value
21649 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
21650 {
21651 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21652 }
21653
21654 IteratorType result = end();
21655
21656 switch (m_data.m_type)
21657 {
21658 case value_t::boolean:
21659 case value_t::number_float:
21660 case value_t::number_integer:
21661 case value_t::number_unsigned:
21662 case value_t::string:
21663 case value_t::binary:
21664 {
21665 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
21666 {
21667 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
21668 }
21669
21670 if (is_string())
21671 {
21672 AllocatorType<string_t> alloc;
21673 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21674 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21675 m_data.m_value.string = nullptr;
21676 }
21677 else if (is_binary())
21678 {
21679 AllocatorType<binary_t> alloc;
21680 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21681 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21682 m_data.m_value.binary = nullptr;
21683 }
21684
21685 m_data.m_type = value_t::null;
21686 assert_invariant();
21687 break;
21688 }
21689
21690 case value_t::object:
21691 {
21692 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
21693 break;
21694 }
21695
21696 case value_t::array:
21697 {
21698 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
21699 break;
21700 }
21701
21702 case value_t::null:
21703 case value_t::discarded:
21704 default:
21705 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21706 }
21707
21708 return result;
21709 }
21710
21713 template < class IteratorType, detail::enable_if_t <
21714 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21715 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21716 IteratorType erase(IteratorType first, IteratorType last)
21717 {
21718 // make sure iterator fits the current value
21719 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
21720 {
21721 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
21722 }
21723
21724 IteratorType result = end();
21725
21726 switch (m_data.m_type)
21727 {
21728 case value_t::boolean:
21729 case value_t::number_float:
21730 case value_t::number_integer:
21731 case value_t::number_unsigned:
21732 case value_t::string:
21733 case value_t::binary:
21734 {
21735 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
21736 || !last.m_it.primitive_iterator.is_end()))
21737 {
21738 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
21739 }
21740
21741 if (is_string())
21742 {
21743 AllocatorType<string_t> alloc;
21744 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21745 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21746 m_data.m_value.string = nullptr;
21747 }
21748 else if (is_binary())
21749 {
21750 AllocatorType<binary_t> alloc;
21751 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21752 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21753 m_data.m_value.binary = nullptr;
21754 }
21755
21756 m_data.m_type = value_t::null;
21757 assert_invariant();
21758 break;
21759 }
21760
21761 case value_t::object:
21762 {
21763 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
21764 last.m_it.object_iterator);
21765 break;
21766 }
21767
21768 case value_t::array:
21769 {
21770 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
21771 last.m_it.array_iterator);
21772 break;
21773 }
21774
21775 case value_t::null:
21776 case value_t::discarded:
21777 default:
21778 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21779 }
21780
21781 return result;
21782 }
21783
21784 private:
21785 template < typename KeyType, detail::enable_if_t <
21787 size_type erase_internal(KeyType && key)
21788 {
21789 // this erase only works for objects
21791 {
21792 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21793 }
21794
21795 return m_data.m_value.object->erase(std::forward<KeyType>(key));
21796 }
21797
21798 template < typename KeyType, detail::enable_if_t <
21800 size_type erase_internal(KeyType && key)
21801 {
21802 // this erase only works for objects
21804 {
21805 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21806 }
21807
21808 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21809 if (it != m_data.m_value.object->end())
21810 {
21811 m_data.m_value.object->erase(it);
21812 return 1;
21813 }
21814 return 0;
21815 }
21816
21817 public:
21818
21821 size_type erase(const typename object_t::key_type& key)
21822 {
21823 // the indirection via erase_internal() is added to avoid making this
21824 // function a template and thus de-rank it during overload resolution
21825 return erase_internal(key);
21826 }
21827
21830 template<class KeyType, detail::enable_if_t<
21832 size_type erase(KeyType && key)
21833 {
21834 return erase_internal(std::forward<KeyType>(key));
21835 }
21836
21839 void erase(const size_type idx)
21840 {
21841 // this erase only works for arrays
21843 {
21844 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
21845 {
21846 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21847 }
21848
21849 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
21850 }
21851 else
21852 {
21853 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21854 }
21855 }
21856
21858
21859
21861 // lookup //
21863
21866
21869 iterator find(const typename object_t::key_type& key)
21870 {
21871 auto result = end();
21872
21873 if (is_object())
21874 {
21875 result.m_it.object_iterator = m_data.m_value.object->find(key);
21876 }
21877
21878 return result;
21879 }
21880
21883 const_iterator find(const typename object_t::key_type& key) const
21884 {
21885 auto result = cend();
21886
21887 if (is_object())
21888 {
21889 result.m_it.object_iterator = m_data.m_value.object->find(key);
21890 }
21891
21892 return result;
21893 }
21894
21897 template<class KeyType, detail::enable_if_t<
21899 iterator find(KeyType && key)
21900 {
21901 auto result = end();
21902
21903 if (is_object())
21904 {
21905 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
21906 }
21907
21908 return result;
21909 }
21910
21913 template<class KeyType, detail::enable_if_t<
21915 const_iterator find(KeyType && key) const
21916 {
21917 auto result = cend();
21918
21919 if (is_object())
21920 {
21921 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
21922 }
21923
21924 return result;
21925 }
21926
21929 size_type count(const typename object_t::key_type& key) const
21930 {
21931 // return 0 for all nonobject types
21932 return is_object() ? m_data.m_value.object->count(key) : 0;
21933 }
21934
21937 template<class KeyType, detail::enable_if_t<
21939 size_type count(KeyType && key) const
21940 {
21941 // return 0 for all nonobject types
21942 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
21943 }
21944
21947 bool contains(const typename object_t::key_type& key) const
21948 {
21949 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
21950 }
21951
21954 template<class KeyType, detail::enable_if_t<
21956 bool contains(KeyType && key) const
21957 {
21958 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
21959 }
21960
21963 bool contains(const json_pointer& ptr) const
21964 {
21965 return ptr.contains(this);
21966 }
21967
21968 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
21969 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21970 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
21971 {
21972 return ptr.contains(this);
21973 }
21974
21976
21977
21979 // iterators //
21981
21984
21987 iterator begin() noexcept
21988 {
21989 iterator result(this);
21990 result.set_begin();
21991 return result;
21992 }
21993
21996 const_iterator begin() const noexcept
21997 {
21998 return cbegin();
21999 }
22000
22003 const_iterator cbegin() const noexcept
22004 {
22005 const_iterator result(this);
22006 result.set_begin();
22007 return result;
22008 }
22009
22012 iterator end() noexcept
22013 {
22014 iterator result(this);
22015 result.set_end();
22016 return result;
22017 }
22018
22021 const_iterator end() const noexcept
22022 {
22023 return cend();
22024 }
22025
22028 const_iterator cend() const noexcept
22029 {
22030 const_iterator result(this);
22031 result.set_end();
22032 return result;
22033 }
22034
22038 {
22039 return reverse_iterator(end());
22040 }
22041
22045 {
22046 return crbegin();
22047 }
22048
22052 {
22053 return reverse_iterator(begin());
22054 }
22055
22059 {
22060 return crend();
22061 }
22062
22066 {
22067 return const_reverse_iterator(cend());
22068 }
22069
22073 {
22075 }
22076
22077 public:
22084 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22085 {
22086 return ref.items();
22087 }
22088
22095 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
22096 {
22097 return ref.items();
22098 }
22099
22102 iteration_proxy<iterator> items() noexcept
22103 {
22104 return iteration_proxy<iterator>(*this);
22105 }
22106
22109 iteration_proxy<const_iterator> items() const noexcept
22110 {
22111 return iteration_proxy<const_iterator>(*this);
22112 }
22113
22115
22116
22118 // capacity //
22120
22123
22126 bool empty() const noexcept
22127 {
22128 switch (m_data.m_type)
22129 {
22130 case value_t::null:
22131 {
22132 // null values are empty
22133 return true;
22134 }
22135
22136 case value_t::array:
22137 {
22138 // delegate call to array_t::empty()
22139 return m_data.m_value.array->empty();
22140 }
22141
22142 case value_t::object:
22143 {
22144 // delegate call to object_t::empty()
22145 return m_data.m_value.object->empty();
22146 }
22147
22148 case value_t::string:
22149 case value_t::boolean:
22150 case value_t::number_integer:
22151 case value_t::number_unsigned:
22152 case value_t::number_float:
22153 case value_t::binary:
22154 case value_t::discarded:
22155 default:
22156 {
22157 // all other types are nonempty
22158 return false;
22159 }
22160 }
22161 }
22162
22165 size_type size() const noexcept
22166 {
22167 switch (m_data.m_type)
22168 {
22169 case value_t::null:
22170 {
22171 // null values are empty
22172 return 0;
22173 }
22174
22175 case value_t::array:
22176 {
22177 // delegate call to array_t::size()
22178 return m_data.m_value.array->size();
22179 }
22180
22181 case value_t::object:
22182 {
22183 // delegate call to object_t::size()
22184 return m_data.m_value.object->size();
22185 }
22186
22187 case value_t::string:
22188 case value_t::boolean:
22189 case value_t::number_integer:
22190 case value_t::number_unsigned:
22191 case value_t::number_float:
22192 case value_t::binary:
22193 case value_t::discarded:
22194 default:
22195 {
22196 // all other types have size 1
22197 return 1;
22198 }
22199 }
22200 }
22201
22204 size_type max_size() const noexcept
22205 {
22206 switch (m_data.m_type)
22207 {
22208 case value_t::array:
22209 {
22210 // delegate call to array_t::max_size()
22211 return m_data.m_value.array->max_size();
22212 }
22213
22214 case value_t::object:
22215 {
22216 // delegate call to object_t::max_size()
22217 return m_data.m_value.object->max_size();
22218 }
22219
22220 case value_t::null:
22221 case value_t::string:
22222 case value_t::boolean:
22223 case value_t::number_integer:
22224 case value_t::number_unsigned:
22225 case value_t::number_float:
22226 case value_t::binary:
22227 case value_t::discarded:
22228 default:
22229 {
22230 // all other types have max_size() == size()
22231 return size();
22232 }
22233 }
22234 }
22235
22237
22238
22240 // modifiers //
22242
22245
22248 void clear() noexcept
22249 {
22250 switch (m_data.m_type)
22251 {
22252 case value_t::number_integer:
22253 {
22254 m_data.m_value.number_integer = 0;
22255 break;
22256 }
22257
22258 case value_t::number_unsigned:
22259 {
22260 m_data.m_value.number_unsigned = 0;
22261 break;
22262 }
22263
22264 case value_t::number_float:
22265 {
22266 m_data.m_value.number_float = 0.0;
22267 break;
22268 }
22269
22270 case value_t::boolean:
22271 {
22272 m_data.m_value.boolean = false;
22273 break;
22274 }
22275
22276 case value_t::string:
22277 {
22278 m_data.m_value.string->clear();
22279 break;
22280 }
22281
22282 case value_t::binary:
22283 {
22284 m_data.m_value.binary->clear();
22285 break;
22286 }
22287
22288 case value_t::array:
22289 {
22290 m_data.m_value.array->clear();
22291 break;
22292 }
22293
22294 case value_t::object:
22295 {
22296 m_data.m_value.object->clear();
22297 break;
22298 }
22299
22300 case value_t::null:
22301 case value_t::discarded:
22302 default:
22303 break;
22304 }
22305 }
22306
22310 {
22311 // push_back only works for null objects or arrays
22312 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22313 {
22314 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22315 }
22316
22317 // transform null object into an array
22318 if (is_null())
22319 {
22320 m_data.m_type = value_t::array;
22321 m_data.m_value = value_t::array;
22322 assert_invariant();
22323 }
22324
22325 // add element to array (move semantics)
22326 const auto old_capacity = m_data.m_value.array->capacity();
22327 m_data.m_value.array->push_back(std::move(val));
22328 set_parent(m_data.m_value.array->back(), old_capacity);
22329 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
22330 }
22331
22335 {
22336 push_back(std::move(val));
22337 return *this;
22338 }
22339
22342 void push_back(const basic_json& val)
22343 {
22344 // push_back only works for null objects or arrays
22345 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22346 {
22347 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22348 }
22349
22350 // transform null object into an array
22351 if (is_null())
22352 {
22353 m_data.m_type = value_t::array;
22354 m_data.m_value = value_t::array;
22355 assert_invariant();
22356 }
22357
22358 // add element to array
22359 const auto old_capacity = m_data.m_value.array->capacity();
22360 m_data.m_value.array->push_back(val);
22361 set_parent(m_data.m_value.array->back(), old_capacity);
22362 }
22363
22367 {
22368 push_back(val);
22369 return *this;
22370 }
22371
22374 void push_back(const typename object_t::value_type& val)
22375 {
22376 // push_back only works for null objects or objects
22377 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22378 {
22379 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22380 }
22381
22382 // transform null object into an object
22383 if (is_null())
22384 {
22385 m_data.m_type = value_t::object;
22386 m_data.m_value = value_t::object;
22387 assert_invariant();
22388 }
22389
22390 // add element to object
22391 auto res = m_data.m_value.object->insert(val);
22392 set_parent(res.first->second);
22393 }
22394
22397 reference operator+=(const typename object_t::value_type& val)
22398 {
22399 push_back(val);
22400 return *this;
22401 }
22402
22406 {
22407 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
22408 {
22409 basic_json&& key = init.begin()->moved_or_copied();
22410 push_back(typename object_t::value_type(
22411 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
22412 }
22413 else
22414 {
22415 push_back(basic_json(init));
22416 }
22417 }
22418
22422 {
22423 push_back(init);
22424 return *this;
22425 }
22426
22429 template<class... Args>
22430 reference emplace_back(Args&& ... args)
22431 {
22432 // emplace_back only works for null objects or arrays
22433 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22434 {
22435 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
22436 }
22437
22438 // transform null object into an array
22439 if (is_null())
22440 {
22441 m_data.m_type = value_t::array;
22442 m_data.m_value = value_t::array;
22443 assert_invariant();
22444 }
22445
22446 // add element to array (perfect forwarding)
22447 const auto old_capacity = m_data.m_value.array->capacity();
22448 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
22449 return set_parent(m_data.m_value.array->back(), old_capacity);
22450 }
22451
22454 template<class... Args>
22455 std::pair<iterator, bool> emplace(Args&& ... args)
22456 {
22457 // emplace only works for null objects or arrays
22458 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22459 {
22460 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
22461 }
22462
22463 // transform null object into an object
22464 if (is_null())
22465 {
22466 m_data.m_type = value_t::object;
22467 m_data.m_value = value_t::object;
22468 assert_invariant();
22469 }
22470
22471 // add element to array (perfect forwarding)
22472 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
22473 set_parent(res.first->second);
22474
22475 // create result iterator and set iterator to the result of emplace
22476 auto it = begin();
22477 it.m_it.object_iterator = res.first;
22478
22479 // return pair of iterator and boolean
22480 return {it, res.second};
22481 }
22482
22486 template<typename... Args>
22488 {
22489 iterator result(this);
22490 JSON_ASSERT(m_data.m_value.array != nullptr);
22491
22492 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
22493 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
22494 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
22495
22496 // This could have been written as:
22497 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
22498 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
22499
22500 set_parents();
22501 return result;
22502 }
22503
22507 {
22508 // insert only works for arrays
22510 {
22511 // check if iterator pos fits to this JSON value
22512 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22513 {
22514 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22515 }
22516
22517 // insert to array and return iterator
22518 return insert_iterator(pos, val);
22519 }
22520
22521 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22522 }
22523
22527 {
22528 return insert(pos, val);
22529 }
22530
22534 {
22535 // insert only works for arrays
22537 {
22538 // check if iterator pos fits to this JSON value
22539 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22540 {
22541 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22542 }
22543
22544 // insert to array and return iterator
22545 return insert_iterator(pos, cnt, val);
22546 }
22547
22548 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22549 }
22550
22554 {
22555 // insert only works for arrays
22557 {
22558 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22559 }
22560
22561 // check if iterator pos fits to this JSON value
22562 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22563 {
22564 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22565 }
22566
22567 // check if range iterators belong to the same JSON object
22568 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22569 {
22570 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22571 }
22572
22573 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
22574 {
22575 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
22576 }
22577
22578 // insert to array and return iterator
22579 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22580 }
22581
22585 {
22586 // insert only works for arrays
22588 {
22589 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22590 }
22591
22592 // check if iterator pos fits to this JSON value
22593 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22594 {
22595 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22596 }
22597
22598 // insert to array and return iterator
22599 return insert_iterator(pos, ilist.begin(), ilist.end());
22600 }
22601
22605 {
22606 // insert only works for objects
22608 {
22609 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22610 }
22611
22612 // check if range iterators belong to the same JSON object
22613 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22614 {
22615 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22616 }
22617
22618 // passed iterators must belong to objects
22619 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22620 {
22621 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
22622 }
22623
22624 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22625 }
22626
22629 void update(const_reference j, bool merge_objects = false)
22630 {
22631 update(j.begin(), j.end(), merge_objects);
22632 }
22633
22636 void update(const_iterator first, const_iterator last, bool merge_objects = false)
22637 {
22638 // implicitly convert null value to an empty object
22639 if (is_null())
22640 {
22641 m_data.m_type = value_t::object;
22642 m_data.m_value.object = create<object_t>();
22643 assert_invariant();
22644 }
22645
22647 {
22648 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
22649 }
22650
22651 // check if range iterators belong to the same JSON object
22652 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22653 {
22654 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22655 }
22656
22657 // passed iterators must belong to objects
22658 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22659 {
22660 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
22661 }
22662
22663 for (auto it = first; it != last; ++it)
22664 {
22665 if (merge_objects && it.value().is_object())
22666 {
22667 auto it2 = m_data.m_value.object->find(it.key());
22668 if (it2 != m_data.m_value.object->end())
22669 {
22670 it2->second.update(it.value(), true);
22671 continue;
22672 }
22673 }
22674 m_data.m_value.object->operator[](it.key()) = it.value();
22675#if JSON_DIAGNOSTICS
22676 m_data.m_value.object->operator[](it.key()).m_parent = this;
22677#endif
22678 }
22679 }
22680
22683 void swap(reference other) noexcept (
22684 std::is_nothrow_move_constructible<value_t>::value&&
22685 std::is_nothrow_move_assignable<value_t>::value&&
22686 std::is_nothrow_move_constructible<json_value>::value&&
22687 std::is_nothrow_move_assignable<json_value>::value
22688 )
22689 {
22690 std::swap(m_data.m_type, other.m_data.m_type);
22691 std::swap(m_data.m_value, other.m_data.m_value);
22692
22693 set_parents();
22694 other.set_parents();
22695 assert_invariant();
22696 }
22697
22700 friend void swap(reference left, reference right) noexcept (
22701 std::is_nothrow_move_constructible<value_t>::value&&
22702 std::is_nothrow_move_assignable<value_t>::value&&
22703 std::is_nothrow_move_constructible<json_value>::value&&
22704 std::is_nothrow_move_assignable<json_value>::value
22705 )
22706 {
22707 left.swap(right);
22708 }
22709
22712 void swap(array_t& other) // NOLINT(bugprone-exception-escape)
22713 {
22714 // swap only works for arrays
22716 {
22717 using std::swap;
22718 swap(*(m_data.m_value.array), other);
22719 }
22720 else
22721 {
22722 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
22723 }
22724 }
22725
22728 void swap(object_t& other) // NOLINT(bugprone-exception-escape)
22729 {
22730 // swap only works for objects
22732 {
22733 using std::swap;
22734 swap(*(m_data.m_value.object), other);
22735 }
22736 else
22737 {
22738 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
22739 }
22740 }
22741
22744 void swap(string_t& other) // NOLINT(bugprone-exception-escape)
22745 {
22746 // swap only works for strings
22748 {
22749 using std::swap;
22750 swap(*(m_data.m_value.string), other);
22751 }
22752 else
22753 {
22754 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
22755 }
22756 }
22757
22760 void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
22761 {
22762 // swap only works for strings
22764 {
22765 using std::swap;
22766 swap(*(m_data.m_value.binary), other);
22767 }
22768 else
22769 {
22770 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
22771 }
22772 }
22773
22776 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
22777 {
22778 // swap only works for strings
22780 {
22781 using std::swap;
22782 swap(*(m_data.m_value.binary), other);
22783 }
22784 else
22785 {
22786 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
22787 }
22788 }
22789
22791
22793 // lexicographical comparison operators //
22795
22798
22799 // note parentheses around operands are necessary; see
22800 // https://github.com/nlohmann/json/issues/1530
22801#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
22802 const auto lhs_type = lhs.type(); \
22803 const auto rhs_type = rhs.type(); \
22804 \
22805 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
22806 { \
22807 switch (lhs_type) \
22808 { \
22809 case value_t::array: \
22810 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
22811 \
22812 case value_t::object: \
22813 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
22814 \
22815 case value_t::null: \
22816 return (null_result); \
22817 \
22818 case value_t::string: \
22819 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
22820 \
22821 case value_t::boolean: \
22822 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
22823 \
22824 case value_t::number_integer: \
22825 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
22826 \
22827 case value_t::number_unsigned: \
22828 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
22829 \
22830 case value_t::number_float: \
22831 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
22832 \
22833 case value_t::binary: \
22834 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
22835 \
22836 case value_t::discarded: \
22837 default: \
22838 return (unordered_result); \
22839 } \
22840 } \
22841 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
22842 { \
22843 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
22844 } \
22845 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
22846 { \
22847 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
22848 } \
22849 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
22850 { \
22851 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
22852 } \
22853 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
22854 { \
22855 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
22856 } \
22857 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
22858 { \
22859 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
22860 } \
22861 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
22862 { \
22863 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
22864 } \
22865 else if(compares_unordered(lhs, rhs))\
22866 {\
22867 return (unordered_result);\
22868 }\
22869 \
22870 return (default_result);
22871
22873 // returns true if:
22874 // - any operand is NaN and the other operand is of number type
22875 // - any operand is discarded
22876 // in legacy mode, discarded values are considered ordered if
22877 // an operation is computed as an odd number of inverses of others
22878 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
22879 {
22880 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
22881 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
22882 {
22883 return true;
22884 }
22885#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22886 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
22887#else
22888 static_cast<void>(inverse);
22889 return lhs.is_discarded() || rhs.is_discarded();
22890#endif
22891 }
22892
22893 private:
22894 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
22895 {
22896 return compares_unordered(*this, rhs, inverse);
22897 }
22898
22899 public:
22900#if JSON_HAS_THREE_WAY_COMPARISON
22903 bool operator==(const_reference rhs) const noexcept
22904 {
22905#ifdef __GNUC__
22906#pragma GCC diagnostic push
22907#pragma GCC diagnostic ignored "-Wfloat-equal"
22908#endif
22909 const_reference lhs = *this;
22910 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
22911#ifdef __GNUC__
22912#pragma GCC diagnostic pop
22913#endif
22914 }
22915
22918 template<typename ScalarType>
22919 requires std::is_scalar_v<ScalarType>
22920 bool operator==(ScalarType rhs) const noexcept
22921 {
22922 return *this == basic_json(rhs);
22923 }
22924
22927 bool operator!=(const_reference rhs) const noexcept
22928 {
22929 if (compares_unordered(rhs, true))
22930 {
22931 return false;
22932 }
22933 return !operator==(rhs);
22934 }
22935
22938 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
22939 {
22940 const_reference lhs = *this;
22941 // default_result is used if we cannot compare values. In that case,
22942 // we compare types.
22943 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
22944 std::partial_ordering::equivalent,
22945 std::partial_ordering::unordered,
22946 lhs_type <=> rhs_type) // *NOPAD*
22947 }
22948
22951 template<typename ScalarType>
22952 requires std::is_scalar_v<ScalarType>
22953 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
22954 {
22955 return *this <=> basic_json(rhs); // *NOPAD*
22956 }
22957
22958#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22959 // all operators that are computed as an odd number of inverses of others
22960 // need to be overloaded to emulate the legacy comparison behavior
22961
22965 bool operator<=(const_reference rhs) const noexcept
22966 {
22967 if (compares_unordered(rhs, true))
22968 {
22969 return false;
22970 }
22971 return !(rhs < *this);
22972 }
22973
22976 template<typename ScalarType>
22977 requires std::is_scalar_v<ScalarType>
22978 bool operator<=(ScalarType rhs) const noexcept
22979 {
22980 return *this <= basic_json(rhs);
22981 }
22982
22986 bool operator>=(const_reference rhs) const noexcept
22987 {
22988 if (compares_unordered(rhs, true))
22989 {
22990 return false;
22991 }
22992 return !(*this < rhs);
22993 }
22994
22997 template<typename ScalarType>
22998 requires std::is_scalar_v<ScalarType>
22999 bool operator>=(ScalarType rhs) const noexcept
23000 {
23001 return *this >= basic_json(rhs);
23002 }
23003#endif
23004#else
23007 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23008 {
23009#ifdef __GNUC__
23010#pragma GCC diagnostic push
23011#pragma GCC diagnostic ignored "-Wfloat-equal"
23012#endif
23013 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23014#ifdef __GNUC__
23015#pragma GCC diagnostic pop
23016#endif
23017 }
23018
23021 template<typename ScalarType, typename std::enable_if<
23022 std::is_scalar<ScalarType>::value, int>::type = 0>
23023 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23024 {
23025 return lhs == basic_json(rhs);
23026 }
23027
23030 template<typename ScalarType, typename std::enable_if<
23031 std::is_scalar<ScalarType>::value, int>::type = 0>
23032 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23033 {
23034 return basic_json(lhs) == rhs;
23035 }
23036
23039 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23040 {
23041 if (compares_unordered(lhs, rhs, true))
23042 {
23043 return false;
23044 }
23045 return !(lhs == rhs);
23046 }
23047
23050 template<typename ScalarType, typename std::enable_if<
23051 std::is_scalar<ScalarType>::value, int>::type = 0>
23052 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23053 {
23054 return lhs != basic_json(rhs);
23055 }
23056
23059 template<typename ScalarType, typename std::enable_if<
23060 std::is_scalar<ScalarType>::value, int>::type = 0>
23061 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23062 {
23063 return basic_json(lhs) != rhs;
23064 }
23065
23068 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23069 {
23070 // default_result is used if we cannot compare values. In that case,
23071 // we compare types. Note we have to call the operator explicitly,
23072 // because MSVC has problems otherwise.
23073 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23074 }
23075
23078 template<typename ScalarType, typename std::enable_if<
23079 std::is_scalar<ScalarType>::value, int>::type = 0>
23080 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23081 {
23082 return lhs < basic_json(rhs);
23083 }
23084
23087 template<typename ScalarType, typename std::enable_if<
23088 std::is_scalar<ScalarType>::value, int>::type = 0>
23089 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23090 {
23091 return basic_json(lhs) < rhs;
23092 }
23093
23096 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23097 {
23098 if (compares_unordered(lhs, rhs, true))
23099 {
23100 return false;
23101 }
23102 return !(rhs < lhs);
23103 }
23104
23107 template<typename ScalarType, typename std::enable_if<
23108 std::is_scalar<ScalarType>::value, int>::type = 0>
23109 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23110 {
23111 return lhs <= basic_json(rhs);
23112 }
23113
23116 template<typename ScalarType, typename std::enable_if<
23117 std::is_scalar<ScalarType>::value, int>::type = 0>
23118 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23119 {
23120 return basic_json(lhs) <= rhs;
23121 }
23122
23125 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
23126 {
23127 // double inverse
23128 if (compares_unordered(lhs, rhs))
23129 {
23130 return false;
23131 }
23132 return !(lhs <= rhs);
23133 }
23134
23137 template<typename ScalarType, typename std::enable_if<
23138 std::is_scalar<ScalarType>::value, int>::type = 0>
23139 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
23140 {
23141 return lhs > basic_json(rhs);
23142 }
23143
23146 template<typename ScalarType, typename std::enable_if<
23147 std::is_scalar<ScalarType>::value, int>::type = 0>
23148 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
23149 {
23150 return basic_json(lhs) > rhs;
23151 }
23152
23155 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
23156 {
23157 if (compares_unordered(lhs, rhs, true))
23158 {
23159 return false;
23160 }
23161 return !(lhs < rhs);
23162 }
23163
23166 template<typename ScalarType, typename std::enable_if<
23167 std::is_scalar<ScalarType>::value, int>::type = 0>
23168 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
23169 {
23170 return lhs >= basic_json(rhs);
23171 }
23172
23175 template<typename ScalarType, typename std::enable_if<
23176 std::is_scalar<ScalarType>::value, int>::type = 0>
23177 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
23178 {
23179 return basic_json(lhs) >= rhs;
23180 }
23181#endif
23182
23183#undef JSON_IMPLEMENT_OPERATOR
23184
23186
23188 // serialization //
23190
23193#ifndef JSON_NO_IO
23196 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
23197 {
23198 // read width member and use it as indentation parameter if nonzero
23199 const bool pretty_print = o.width() > 0;
23200 const auto indentation = pretty_print ? o.width() : 0;
23201
23202 // reset width to 0 for subsequent calls to this stream
23203 o.width(0);
23204
23205 // do the actual serialization
23206 serializer s(detail::output_adapter<char>(o), o.fill());
23207 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
23208 return o;
23209 }
23210
23217 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
23218 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
23219 {
23220 return o << j;
23221 }
23222#endif // JSON_NO_IO
23224
23225
23227 // deserialization //
23229
23232
23235 template<typename InputType>
23237 static basic_json parse(InputType&& i,
23238 const parser_callback_t cb = nullptr,
23239 const bool allow_exceptions = true,
23240 const bool ignore_comments = false)
23241 {
23242 basic_json result;
23243 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
23244 return result;
23245 }
23246
23249 template<typename IteratorType>
23251 static basic_json parse(IteratorType first,
23252 IteratorType last,
23253 const parser_callback_t cb = nullptr,
23254 const bool allow_exceptions = true,
23255 const bool ignore_comments = false)
23256 {
23257 basic_json result;
23258 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
23259 return result;
23260 }
23261
23263 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
23264 static basic_json parse(detail::span_input_adapter&& i,
23265 const parser_callback_t cb = nullptr,
23266 const bool allow_exceptions = true,
23267 const bool ignore_comments = false)
23268 {
23269 basic_json result;
23270 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
23271 return result;
23272 }
23273
23276 template<typename InputType>
23277 static bool accept(InputType&& i,
23278 const bool ignore_comments = false)
23279 {
23280 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
23281 }
23282
23285 template<typename IteratorType>
23286 static bool accept(IteratorType first, IteratorType last,
23287 const bool ignore_comments = false)
23288 {
23289 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
23290 }
23291
23293 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
23294 static bool accept(detail::span_input_adapter&& i,
23295 const bool ignore_comments = false)
23296 {
23297 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
23298 }
23299
23302 template <typename InputType, typename SAX>
23304 static bool sax_parse(InputType&& i, SAX* sax,
23305 input_format_t format = input_format_t::json,
23306 const bool strict = true,
23307 const bool ignore_comments = false)
23308 {
23309 auto ia = detail::input_adapter(std::forward<InputType>(i));
23310 return format == input_format_t::json
23311 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23312 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23313 }
23314
23317 template<class IteratorType, class SAX>
23319 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23320 input_format_t format = input_format_t::json,
23321 const bool strict = true,
23322 const bool ignore_comments = false)
23323 {
23324 auto ia = detail::input_adapter(std::move(first), std::move(last));
23325 return format == input_format_t::json
23326 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23327 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23328 }
23329
23335 template <typename SAX>
23336 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23338 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
23339 input_format_t format = input_format_t::json,
23340 const bool strict = true,
23341 const bool ignore_comments = false)
23342 {
23343 auto ia = i.get();
23344 return format == input_format_t::json
23345 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23346 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23347 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23348 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23349 }
23350#ifndef JSON_NO_IO
23357 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
23358 friend std::istream& operator<<(basic_json& j, std::istream& i)
23359 {
23360 return operator>>(i, j);
23361 }
23362
23365 friend std::istream& operator>>(std::istream& i, basic_json& j)
23366 {
23367 parser(detail::input_adapter(i)).parse(false, j);
23368 return i;
23369 }
23370#endif // JSON_NO_IO
23372
23374 // convenience functions //
23376
23380 const char* type_name() const noexcept
23381 {
23382 switch (m_data.m_type)
23383 {
23384 case value_t::null:
23385 return "null";
23386 case value_t::object:
23387 return "object";
23388 case value_t::array:
23389 return "array";
23390 case value_t::string:
23391 return "string";
23392 case value_t::boolean:
23393 return "boolean";
23394 case value_t::binary:
23395 return "binary";
23396 case value_t::discarded:
23397 return "discarded";
23398 case value_t::number_integer:
23399 case value_t::number_unsigned:
23400 case value_t::number_float:
23401 default:
23402 return "number";
23403 }
23404 }
23405
23406
23409 // member variables //
23411
23412 struct data
23413 {
23415 value_t m_type = value_t::null;
23416
23418 json_value m_value = {};
23419
23420 data(const value_t v)
23421 : m_type(v), m_value(v)
23422 {
23423 }
23424
23425 data(size_type cnt, const basic_json& val)
23426 : m_type(value_t::array)
23427 {
23428 m_value.array = create<array_t>(cnt, val);
23429 }
23430
23431 data() noexcept = default;
23432 data(data&&) noexcept = default;
23433 data(const data&) noexcept = delete;
23434 data& operator=(data&&) noexcept = delete;
23435 data& operator=(const data&) noexcept = delete;
23436
23437 ~data() noexcept
23438 {
23439 m_value.destroy(m_type);
23440 }
23441 };
23442
23444
23445#if JSON_DIAGNOSTICS
23447 basic_json* m_parent = nullptr;
23448#endif
23449
23451 // binary serialization/deserialization //
23453
23456
23457 public:
23460 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
23461 {
23462 std::vector<std::uint8_t> result;
23463 to_cbor(j, result);
23464 return result;
23465 }
23466
23469 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23470 {
23471 binary_writer<std::uint8_t>(o).write_cbor(j);
23472 }
23473
23476 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
23477 {
23478 binary_writer<char>(o).write_cbor(j);
23479 }
23480
23483 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
23484 {
23485 std::vector<std::uint8_t> result;
23486 to_msgpack(j, result);
23487 return result;
23488 }
23489
23492 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23493 {
23494 binary_writer<std::uint8_t>(o).write_msgpack(j);
23495 }
23496
23499 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
23500 {
23501 binary_writer<char>(o).write_msgpack(j);
23502 }
23503
23506 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
23507 const bool use_size = false,
23508 const bool use_type = false)
23509 {
23510 std::vector<std::uint8_t> result;
23511 to_ubjson(j, result, use_size, use_type);
23512 return result;
23513 }
23514
23517 static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
23518 const bool use_size = false, const bool use_type = false)
23519 {
23520 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
23521 }
23522
23525 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
23526 const bool use_size = false, const bool use_type = false)
23527 {
23528 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23529 }
23530
23533 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
23534 const bool use_size = false,
23535 const bool use_type = false)
23536 {
23537 std::vector<std::uint8_t> result;
23538 to_bjdata(j, result, use_size, use_type);
23539 return result;
23540 }
23541
23544 static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
23545 const bool use_size = false, const bool use_type = false)
23546 {
23547 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
23548 }
23549
23552 static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
23553 const bool use_size = false, const bool use_type = false)
23554 {
23555 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
23556 }
23557
23560 static std::vector<std::uint8_t> to_bson(const basic_json& j)
23561 {
23562 std::vector<std::uint8_t> result;
23563 to_bson(j, result);
23564 return result;
23565 }
23566
23569 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23570 {
23571 binary_writer<std::uint8_t>(o).write_bson(j);
23572 }
23573
23576 static void to_bson(const basic_json& j, detail::output_adapter<char> o)
23577 {
23578 binary_writer<char>(o).write_bson(j);
23579 }
23580
23583 template<typename InputType>
23585 static basic_json from_cbor(InputType&& i,
23586 const bool strict = true,
23587 const bool allow_exceptions = true,
23588 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23589 {
23590 basic_json result;
23591 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23592 auto ia = detail::input_adapter(std::forward<InputType>(i));
23593 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23594 return res ? result : basic_json(value_t::discarded);
23595 }
23596
23599 template<typename IteratorType>
23601 static basic_json from_cbor(IteratorType first, IteratorType last,
23602 const bool strict = true,
23603 const bool allow_exceptions = true,
23604 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23605 {
23606 basic_json result;
23607 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23608 auto ia = detail::input_adapter(std::move(first), std::move(last));
23609 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23610 return res ? result : basic_json(value_t::discarded);
23611 }
23612
23613 template<typename T>
23615 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23616 static basic_json from_cbor(const T* ptr, std::size_t len,
23617 const bool strict = true,
23618 const bool allow_exceptions = true,
23619 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23620 {
23621 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23622 }
23623
23624
23626 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23627 static basic_json from_cbor(detail::span_input_adapter&& i,
23628 const bool strict = true,
23629 const bool allow_exceptions = true,
23630 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23631 {
23632 basic_json result;
23633 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23634 auto ia = i.get();
23635 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23636 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23637 return res ? result : basic_json(value_t::discarded);
23638 }
23639
23642 template<typename InputType>
23644 static basic_json from_msgpack(InputType&& i,
23645 const bool strict = true,
23646 const bool allow_exceptions = true)
23647 {
23648 basic_json result;
23649 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23650 auto ia = detail::input_adapter(std::forward<InputType>(i));
23651 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23652 return res ? result : basic_json(value_t::discarded);
23653 }
23654
23657 template<typename IteratorType>
23659 static basic_json from_msgpack(IteratorType first, IteratorType last,
23660 const bool strict = true,
23661 const bool allow_exceptions = true)
23662 {
23663 basic_json result;
23664 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23665 auto ia = detail::input_adapter(std::move(first), std::move(last));
23666 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23667 return res ? result : basic_json(value_t::discarded);
23668 }
23669
23670 template<typename T>
23672 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23673 static basic_json from_msgpack(const T* ptr, std::size_t len,
23674 const bool strict = true,
23675 const bool allow_exceptions = true)
23676 {
23677 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
23678 }
23679
23681 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23682 static basic_json from_msgpack(detail::span_input_adapter&& i,
23683 const bool strict = true,
23684 const bool allow_exceptions = true)
23685 {
23686 basic_json result;
23687 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23688 auto ia = i.get();
23689 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23690 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23691 return res ? result : basic_json(value_t::discarded);
23692 }
23693
23696 template<typename InputType>
23698 static basic_json from_ubjson(InputType&& i,
23699 const bool strict = true,
23700 const bool allow_exceptions = true)
23701 {
23702 basic_json result;
23703 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23704 auto ia = detail::input_adapter(std::forward<InputType>(i));
23705 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23706 return res ? result : basic_json(value_t::discarded);
23707 }
23708
23711 template<typename IteratorType>
23713 static basic_json from_ubjson(IteratorType first, IteratorType last,
23714 const bool strict = true,
23715 const bool allow_exceptions = true)
23716 {
23717 basic_json result;
23718 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23719 auto ia = detail::input_adapter(std::move(first), std::move(last));
23720 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23721 return res ? result : basic_json(value_t::discarded);
23722 }
23723
23724 template<typename T>
23726 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23727 static basic_json from_ubjson(const T* ptr, std::size_t len,
23728 const bool strict = true,
23729 const bool allow_exceptions = true)
23730 {
23731 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
23732 }
23733
23735 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23736 static basic_json from_ubjson(detail::span_input_adapter&& i,
23737 const bool strict = true,
23738 const bool allow_exceptions = true)
23739 {
23740 basic_json result;
23741 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23742 auto ia = i.get();
23743 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23744 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23745 return res ? result : basic_json(value_t::discarded);
23746 }
23747
23748
23751 template<typename InputType>
23753 static basic_json from_bjdata(InputType&& i,
23754 const bool strict = true,
23755 const bool allow_exceptions = true)
23756 {
23757 basic_json result;
23758 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23759 auto ia = detail::input_adapter(std::forward<InputType>(i));
23760 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23761 return res ? result : basic_json(value_t::discarded);
23762 }
23763
23766 template<typename IteratorType>
23768 static basic_json from_bjdata(IteratorType first, IteratorType last,
23769 const bool strict = true,
23770 const bool allow_exceptions = true)
23771 {
23772 basic_json result;
23773 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23774 auto ia = detail::input_adapter(std::move(first), std::move(last));
23775 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23776 return res ? result : basic_json(value_t::discarded);
23777 }
23778
23781 template<typename InputType>
23783 static basic_json from_bson(InputType&& i,
23784 const bool strict = true,
23785 const bool allow_exceptions = true)
23786 {
23787 basic_json result;
23788 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23789 auto ia = detail::input_adapter(std::forward<InputType>(i));
23790 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23791 return res ? result : basic_json(value_t::discarded);
23792 }
23793
23796 template<typename IteratorType>
23798 static basic_json from_bson(IteratorType first, IteratorType last,
23799 const bool strict = true,
23800 const bool allow_exceptions = true)
23801 {
23802 basic_json result;
23803 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23804 auto ia = detail::input_adapter(std::move(first), std::move(last));
23805 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23806 return res ? result : basic_json(value_t::discarded);
23807 }
23808
23809 template<typename T>
23811 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23812 static basic_json from_bson(const T* ptr, std::size_t len,
23813 const bool strict = true,
23814 const bool allow_exceptions = true)
23815 {
23816 return from_bson(ptr, ptr + len, strict, allow_exceptions);
23817 }
23818
23820 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23821 static basic_json from_bson(detail::span_input_adapter&& i,
23822 const bool strict = true,
23823 const bool allow_exceptions = true)
23824 {
23825 basic_json result;
23826 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23827 auto ia = i.get();
23828 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23829 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23830 return res ? result : basic_json(value_t::discarded);
23831 }
23833
23835 // JSON Pointer support //
23837
23840
23844 {
23845 return ptr.get_unchecked(this);
23846 }
23847
23848 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23849 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23850 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23851 {
23852 return ptr.get_unchecked(this);
23853 }
23854
23858 {
23859 return ptr.get_unchecked(this);
23860 }
23861
23862 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23863 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23864 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23865 {
23866 return ptr.get_unchecked(this);
23867 }
23868
23872 {
23873 return ptr.get_checked(this);
23874 }
23875
23876 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23877 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23878 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23879 {
23880 return ptr.get_checked(this);
23881 }
23882
23886 {
23887 return ptr.get_checked(this);
23888 }
23889
23890 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23891 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23892 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23893 {
23894 return ptr.get_checked(this);
23895 }
23896
23900 {
23901 basic_json result(value_t::object);
23902 json_pointer::flatten("", *this, result);
23903 return result;
23904 }
23905
23909 {
23910 return json_pointer::unflatten(*this);
23911 }
23912
23914
23916 // JSON Patch functions //
23918
23921
23924 void patch_inplace(const basic_json& json_patch)
23925 {
23926 basic_json& result = *this;
23927 // the valid JSON Patch operations
23928 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
23929
23930 const auto get_op = [](const std::string & op)
23931 {
23932 if (op == "add")
23933 {
23934 return patch_operations::add;
23935 }
23936 if (op == "remove")
23937 {
23938 return patch_operations::remove;
23939 }
23940 if (op == "replace")
23941 {
23942 return patch_operations::replace;
23943 }
23944 if (op == "move")
23945 {
23946 return patch_operations::move;
23947 }
23948 if (op == "copy")
23949 {
23950 return patch_operations::copy;
23951 }
23952 if (op == "test")
23953 {
23954 return patch_operations::test;
23955 }
23956
23957 return patch_operations::invalid;
23958 };
23959
23960 // wrapper for "add" operation; add value at ptr
23961 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
23962 {
23963 // adding to the root of the target document means replacing it
23964 if (ptr.empty())
23965 {
23966 result = val;
23967 return;
23968 }
23969
23970 // make sure the top element of the pointer exists
23971 json_pointer const top_pointer = ptr.top();
23972 if (top_pointer != ptr)
23973 {
23974 result.at(top_pointer);
23975 }
23976
23977 // get reference to parent of JSON pointer ptr
23978 const auto last_path = ptr.back();
23979 ptr.pop_back();
23980 // parent must exist when performing patch add per RFC6902 specs
23981 basic_json& parent = result.at(ptr);
23982
23983 switch (parent.m_data.m_type)
23984 {
23985 case value_t::null:
23986 case value_t::object:
23987 {
23988 // use operator[] to add value
23989 parent[last_path] = val;
23990 break;
23991 }
23992
23993 case value_t::array:
23994 {
23995 if (last_path == "-")
23996 {
23997 // special case: append to back
23998 parent.push_back(val);
23999 }
24000 else
24001 {
24002 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24003 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24004 {
24005 // avoid undefined behavior
24006 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24007 }
24008
24009 // default case: insert add offset
24010 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24011 }
24012 break;
24013 }
24014
24015 // if there exists a parent it cannot be primitive
24016 case value_t::string: // LCOV_EXCL_LINE
24017 case value_t::boolean: // LCOV_EXCL_LINE
24018 case value_t::number_integer: // LCOV_EXCL_LINE
24019 case value_t::number_unsigned: // LCOV_EXCL_LINE
24020 case value_t::number_float: // LCOV_EXCL_LINE
24021 case value_t::binary: // LCOV_EXCL_LINE
24022 case value_t::discarded: // LCOV_EXCL_LINE
24023 default: // LCOV_EXCL_LINE
24024 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24025 }
24026 };
24027
24028 // wrapper for "remove" operation; remove value at ptr
24029 const auto operation_remove = [this, &result](json_pointer & ptr)
24030 {
24031 // get reference to parent of JSON pointer ptr
24032 const auto last_path = ptr.back();
24033 ptr.pop_back();
24034 basic_json& parent = result.at(ptr);
24035
24036 // remove child
24037 if (parent.is_object())
24038 {
24039 // perform range check
24040 auto it = parent.find(last_path);
24041 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24042 {
24043 parent.erase(it);
24044 }
24045 else
24046 {
24047 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24048 }
24049 }
24050 else if (parent.is_array())
24051 {
24052 // note erase performs range check
24053 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24054 }
24055 };
24056
24057 // type check: top level value must be an array
24058 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24059 {
24060 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24061 }
24062
24063 // iterate and apply the operations
24064 for (const auto& val : json_patch)
24065 {
24066 // wrapper to get a value for an operation
24067 const auto get_value = [&val](const std::string & op,
24068 const std::string & member,
24069 bool string_type) -> basic_json &
24070 {
24071 // find value
24072 auto it = val.m_data.m_value.object->find(member);
24073
24074 // context-sensitive error message
24075 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
24076
24077 // check if desired value is present
24078 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24079 {
24080 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24081 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24082 }
24083
24084 // check if result is of type string
24085 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24086 {
24087 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24088 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24089 }
24090
24091 // no error: return value
24092 return it->second;
24093 };
24094
24095 // type check: every element of the array must be an object
24096 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24097 {
24098 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24099 }
24100
24101 // collect mandatory members
24102 const auto op = get_value("op", "op", true).template get<std::string>();
24103 const auto path = get_value(op, "path", true).template get<std::string>();
24104 json_pointer ptr(path);
24105
24106 switch (get_op(op))
24107 {
24108 case patch_operations::add:
24109 {
24110 operation_add(ptr, get_value("add", "value", false));
24111 break;
24112 }
24113
24114 case patch_operations::remove:
24115 {
24116 operation_remove(ptr);
24117 break;
24118 }
24119
24120 case patch_operations::replace:
24121 {
24122 // the "path" location must exist - use at()
24123 result.at(ptr) = get_value("replace", "value", false);
24124 break;
24125 }
24126
24127 case patch_operations::move:
24128 {
24129 const auto from_path = get_value("move", "from", true).template get<std::string>();
24130 json_pointer from_ptr(from_path);
24131
24132 // the "from" location must exist - use at()
24133 basic_json const v = result.at(from_ptr);
24134
24135 // The move operation is functionally identical to a
24136 // "remove" operation on the "from" location, followed
24137 // immediately by an "add" operation at the target
24138 // location with the value that was just removed.
24139 operation_remove(from_ptr);
24140 operation_add(ptr, v);
24141 break;
24142 }
24143
24144 case patch_operations::copy:
24145 {
24146 const auto from_path = get_value("copy", "from", true).template get<std::string>();
24147 const json_pointer from_ptr(from_path);
24148
24149 // the "from" location must exist - use at()
24150 basic_json const v = result.at(from_ptr);
24151
24152 // The copy is functionally identical to an "add"
24153 // operation at the target location using the value
24154 // specified in the "from" member.
24155 operation_add(ptr, v);
24156 break;
24157 }
24158
24159 case patch_operations::test:
24160 {
24161 bool success = false;
24162 JSON_TRY
24163 {
24164 // check if "value" matches the one at "path"
24165 // the "path" location must exist - use at()
24166 success = (result.at(ptr) == get_value("test", "value", false));
24167 }
24169 {
24170 // ignore out of range errors: success remains false
24171 }
24172
24173 // throw an exception if test fails
24174 if (JSON_HEDLEY_UNLIKELY(!success))
24175 {
24176 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
24177 }
24178
24179 break;
24180 }
24181
24182 case patch_operations::invalid:
24183 default:
24184 {
24185 // op must be "add", "remove", "replace", "move", "copy", or
24186 // "test"
24187 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
24188 }
24189 }
24190 }
24191 }
24192
24195 basic_json patch(const basic_json& json_patch) const
24196 {
24197 basic_json result = *this;
24198 result.patch_inplace(json_patch);
24199 return result;
24200 }
24201
24205 static basic_json diff(const basic_json& source, const basic_json& target,
24206 const std::string& path = "")
24207 {
24208 // the patch
24209 basic_json result(value_t::array);
24210
24211 // if the values are the same, return empty patch
24212 if (source == target)
24213 {
24214 return result;
24215 }
24216
24217 if (source.type() != target.type())
24218 {
24219 // different types: replace value
24220 result.push_back(
24221 {
24222 {"op", "replace"}, {"path", path}, {"value", target}
24223 });
24224 return result;
24225 }
24226
24227 switch (source.type())
24228 {
24229 case value_t::array:
24230 {
24231 // first pass: traverse common elements
24232 std::size_t i = 0;
24233 while (i < source.size() && i < target.size())
24234 {
24235 // recursive call to compare array values at index i
24236 auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
24237 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24238 ++i;
24239 }
24240
24241 // We now reached the end of at least one array
24242 // in a second pass, traverse the remaining elements
24243
24244 // remove my remaining elements
24245 const auto end_index = static_cast<difference_type>(result.size());
24246 while (i < source.size())
24247 {
24248 // add operations in reverse order to avoid invalid
24249 // indices
24250 result.insert(result.begin() + end_index, object(
24251 {
24252 {"op", "remove"},
24253 {"path", detail::concat(path, '/', std::to_string(i))}
24254 }));
24255 ++i;
24256 }
24257
24258 // add other remaining elements
24259 while (i < target.size())
24260 {
24261 result.push_back(
24262 {
24263 {"op", "add"},
24264 {"path", detail::concat(path, "/-")},
24265 {"value", target[i]}
24266 });
24267 ++i;
24268 }
24269
24270 break;
24271 }
24272
24273 case value_t::object:
24274 {
24275 // first pass: traverse this object's elements
24276 for (auto it = source.cbegin(); it != source.cend(); ++it)
24277 {
24278 // escape the key name to be used in a JSON patch
24279 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24280
24281 if (target.find(it.key()) != target.end())
24282 {
24283 // recursive call to compare object values at key it
24284 auto temp_diff = diff(it.value(), target[it.key()], path_key);
24285 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24286 }
24287 else
24288 {
24289 // found a key that is not in o -> remove it
24290 result.push_back(object(
24291 {
24292 {"op", "remove"}, {"path", path_key}
24293 }));
24294 }
24295 }
24296
24297 // second pass: traverse other object's elements
24298 for (auto it = target.cbegin(); it != target.cend(); ++it)
24299 {
24300 if (source.find(it.key()) == source.end())
24301 {
24302 // found a key that is not in this -> add it
24303 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24304 result.push_back(
24305 {
24306 {"op", "add"}, {"path", path_key},
24307 {"value", it.value()}
24308 });
24309 }
24310 }
24311
24312 break;
24313 }
24314
24315 case value_t::null:
24316 case value_t::string:
24317 case value_t::boolean:
24318 case value_t::number_integer:
24319 case value_t::number_unsigned:
24320 case value_t::number_float:
24321 case value_t::binary:
24322 case value_t::discarded:
24323 default:
24324 {
24325 // both primitive type: replace value
24326 result.push_back(
24327 {
24328 {"op", "replace"}, {"path", path}, {"value", target}
24329 });
24330 break;
24331 }
24332 }
24333
24334 return result;
24335 }
24337
24339 // JSON Merge Patch functions //
24341
24344
24347 void merge_patch(const basic_json& apply_patch)
24348 {
24349 if (apply_patch.is_object())
24350 {
24351 if (!is_object())
24352 {
24353 *this = object();
24354 }
24355 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
24356 {
24357 if (it.value().is_null())
24358 {
24359 erase(it.key());
24360 }
24361 else
24362 {
24363 operator[](it.key()).merge_patch(it.value());
24364 }
24365 }
24366 }
24367 else
24368 {
24369 *this = apply_patch;
24370 }
24371 }
24372
24374};
24375
24380{
24381 return j.dump();
24382}
24383
24384inline namespace literals
24385{
24386inline namespace json_literals
24387{
24388
24392inline nlohmann::json operator "" _json(const char* s, std::size_t n)
24393{
24394 return nlohmann::json::parse(s, s + n);
24395}
24396
24400inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
24401{
24402 return nlohmann::json::json_pointer(std::string(s, n));
24403}
24404
24405} // namespace json_literals
24406} // namespace literals
24408
24410// nonmember support //
24412
24413namespace std // NOLINT(cert-dcl58-cpp)
24414{
24415
24419struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
24420{
24421 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
24422 {
24423 return nlohmann::detail::hash(j);
24424 }
24425};
24426
24427// specialization for std::less<value_t>
24428template<>
24429struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
24430{
24435 bool operator()(::nlohmann::detail::value_t lhs,
24436 ::nlohmann::detail::value_t rhs) const noexcept
24437 {
24438#if JSON_HAS_THREE_WAY_COMPARISON
24439 return std::is_lt(lhs <=> rhs); // *NOPAD*
24440#else
24441 return ::nlohmann::detail::operator<(lhs, rhs);
24442#endif
24443 }
24444};
24445
24446// C++20 prohibit function specialization in the std namespace.
24447#ifndef JSON_HAS_CPP_20
24448
24452inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
24453 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression)
24454 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
24455{
24456 j1.swap(j2);
24457}
24458
24459#endif
24460
24461} // namespace std
24462
24463#if JSON_USE_GLOBAL_UDLS
24464 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24465 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24466#endif
24467
24468// #include <nlohmann/detail/macro_unscope.hpp>
24469// __ _____ _____ _____
24470// __| | __| | | | JSON for Modern C++
24471// | | |__ | | | | | | version 3.11.2
24472// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24473//
24474// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
24475// SPDX-License-Identifier: MIT
24476
24477
24478
24479// restore clang diagnostic settings
24480#if defined(__clang__)
24481 #pragma clang diagnostic pop
24482#endif
24483
24484// clean up
24485#undef JSON_ASSERT
24486#undef JSON_INTERNAL_CATCH
24487#undef JSON_THROW
24488#undef JSON_PRIVATE_UNLESS_TESTED
24489#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
24490#undef NLOHMANN_BASIC_JSON_TPL
24491#undef JSON_EXPLICIT
24492#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
24493#undef JSON_INLINE_VARIABLE
24494#undef JSON_NO_UNIQUE_ADDRESS
24495#undef JSON_DISABLE_ENUM_SERIALIZATION
24496#undef JSON_USE_GLOBAL_UDLS
24497
24498#ifndef JSON_TEST_KEEP_MACROS
24499 #undef JSON_CATCH
24500 #undef JSON_TRY
24501 #undef JSON_HAS_CPP_11
24502 #undef JSON_HAS_CPP_14
24503 #undef JSON_HAS_CPP_17
24504 #undef JSON_HAS_CPP_20
24505 #undef JSON_HAS_FILESYSTEM
24506 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
24507 #undef JSON_HAS_THREE_WAY_COMPARISON
24508 #undef JSON_HAS_RANGES
24509 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
24510#endif
24511
24512// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
24513// __ _____ _____ _____
24514// __| | __| | | | JSON for Modern C++
24515// | | |__ | | | | | | version 3.11.2
24516// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24517//
24518// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
24519// SPDX-License-Identifier: MIT
24520
24521
24522
24523#undef JSON_HEDLEY_ALWAYS_INLINE
24524#undef JSON_HEDLEY_ARM_VERSION
24525#undef JSON_HEDLEY_ARM_VERSION_CHECK
24526#undef JSON_HEDLEY_ARRAY_PARAM
24527#undef JSON_HEDLEY_ASSUME
24528#undef JSON_HEDLEY_BEGIN_C_DECLS
24529#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
24530#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
24531#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
24532#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
24533#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
24534#undef JSON_HEDLEY_CLANG_HAS_FEATURE
24535#undef JSON_HEDLEY_CLANG_HAS_WARNING
24536#undef JSON_HEDLEY_COMPCERT_VERSION
24537#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
24538#undef JSON_HEDLEY_CONCAT
24539#undef JSON_HEDLEY_CONCAT3
24540#undef JSON_HEDLEY_CONCAT3_EX
24541#undef JSON_HEDLEY_CONCAT_EX
24542#undef JSON_HEDLEY_CONST
24543#undef JSON_HEDLEY_CONSTEXPR
24544#undef JSON_HEDLEY_CONST_CAST
24545#undef JSON_HEDLEY_CPP_CAST
24546#undef JSON_HEDLEY_CRAY_VERSION
24547#undef JSON_HEDLEY_CRAY_VERSION_CHECK
24548#undef JSON_HEDLEY_C_DECL
24549#undef JSON_HEDLEY_DEPRECATED
24550#undef JSON_HEDLEY_DEPRECATED_FOR
24551#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
24552#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
24553#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
24554#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
24555#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
24556#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
24557#undef JSON_HEDLEY_DIAGNOSTIC_POP
24558#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
24559#undef JSON_HEDLEY_DMC_VERSION
24560#undef JSON_HEDLEY_DMC_VERSION_CHECK
24561#undef JSON_HEDLEY_EMPTY_BASES
24562#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
24563#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
24564#undef JSON_HEDLEY_END_C_DECLS
24565#undef JSON_HEDLEY_FLAGS
24566#undef JSON_HEDLEY_FLAGS_CAST
24567#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
24568#undef JSON_HEDLEY_GCC_HAS_BUILTIN
24569#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
24570#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
24571#undef JSON_HEDLEY_GCC_HAS_EXTENSION
24572#undef JSON_HEDLEY_GCC_HAS_FEATURE
24573#undef JSON_HEDLEY_GCC_HAS_WARNING
24574#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
24575#undef JSON_HEDLEY_GCC_VERSION
24576#undef JSON_HEDLEY_GCC_VERSION_CHECK
24577#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
24578#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
24579#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
24580#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
24581#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
24582#undef JSON_HEDLEY_GNUC_HAS_FEATURE
24583#undef JSON_HEDLEY_GNUC_HAS_WARNING
24584#undef JSON_HEDLEY_GNUC_VERSION
24585#undef JSON_HEDLEY_GNUC_VERSION_CHECK
24586#undef JSON_HEDLEY_HAS_ATTRIBUTE
24587#undef JSON_HEDLEY_HAS_BUILTIN
24588#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
24589#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
24590#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
24591#undef JSON_HEDLEY_HAS_EXTENSION
24592#undef JSON_HEDLEY_HAS_FEATURE
24593#undef JSON_HEDLEY_HAS_WARNING
24594#undef JSON_HEDLEY_IAR_VERSION
24595#undef JSON_HEDLEY_IAR_VERSION_CHECK
24596#undef JSON_HEDLEY_IBM_VERSION
24597#undef JSON_HEDLEY_IBM_VERSION_CHECK
24598#undef JSON_HEDLEY_IMPORT
24599#undef JSON_HEDLEY_INLINE
24600#undef JSON_HEDLEY_INTEL_CL_VERSION
24601#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
24602#undef JSON_HEDLEY_INTEL_VERSION
24603#undef JSON_HEDLEY_INTEL_VERSION_CHECK
24604#undef JSON_HEDLEY_IS_CONSTANT
24605#undef JSON_HEDLEY_IS_CONSTEXPR_
24606#undef JSON_HEDLEY_LIKELY
24607#undef JSON_HEDLEY_MALLOC
24608#undef JSON_HEDLEY_MCST_LCC_VERSION
24609#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
24610#undef JSON_HEDLEY_MESSAGE
24611#undef JSON_HEDLEY_MSVC_VERSION
24612#undef JSON_HEDLEY_MSVC_VERSION_CHECK
24613#undef JSON_HEDLEY_NEVER_INLINE
24614#undef JSON_HEDLEY_NON_NULL
24615#undef JSON_HEDLEY_NO_ESCAPE
24616#undef JSON_HEDLEY_NO_RETURN
24617#undef JSON_HEDLEY_NO_THROW
24618#undef JSON_HEDLEY_NULL
24619#undef JSON_HEDLEY_PELLES_VERSION
24620#undef JSON_HEDLEY_PELLES_VERSION_CHECK
24621#undef JSON_HEDLEY_PGI_VERSION
24622#undef JSON_HEDLEY_PGI_VERSION_CHECK
24623#undef JSON_HEDLEY_PREDICT
24624#undef JSON_HEDLEY_PRINTF_FORMAT
24625#undef JSON_HEDLEY_PRIVATE
24626#undef JSON_HEDLEY_PUBLIC
24627#undef JSON_HEDLEY_PURE
24628#undef JSON_HEDLEY_REINTERPRET_CAST
24629#undef JSON_HEDLEY_REQUIRE
24630#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
24631#undef JSON_HEDLEY_REQUIRE_MSG
24632#undef JSON_HEDLEY_RESTRICT
24633#undef JSON_HEDLEY_RETURNS_NON_NULL
24634#undef JSON_HEDLEY_SENTINEL
24635#undef JSON_HEDLEY_STATIC_ASSERT
24636#undef JSON_HEDLEY_STATIC_CAST
24637#undef JSON_HEDLEY_STRINGIFY
24638#undef JSON_HEDLEY_STRINGIFY_EX
24639#undef JSON_HEDLEY_SUNPRO_VERSION
24640#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
24641#undef JSON_HEDLEY_TINYC_VERSION
24642#undef JSON_HEDLEY_TINYC_VERSION_CHECK
24643#undef JSON_HEDLEY_TI_ARMCL_VERSION
24644#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
24645#undef JSON_HEDLEY_TI_CL2000_VERSION
24646#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
24647#undef JSON_HEDLEY_TI_CL430_VERSION
24648#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
24649#undef JSON_HEDLEY_TI_CL6X_VERSION
24650#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
24651#undef JSON_HEDLEY_TI_CL7X_VERSION
24652#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
24653#undef JSON_HEDLEY_TI_CLPRU_VERSION
24654#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
24655#undef JSON_HEDLEY_TI_VERSION
24656#undef JSON_HEDLEY_TI_VERSION_CHECK
24657#undef JSON_HEDLEY_UNAVAILABLE
24658#undef JSON_HEDLEY_UNLIKELY
24659#undef JSON_HEDLEY_UNPREDICTABLE
24660#undef JSON_HEDLEY_UNREACHABLE
24661#undef JSON_HEDLEY_UNREACHABLE_RETURN
24662#undef JSON_HEDLEY_VERSION
24663#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
24664#undef JSON_HEDLEY_VERSION_DECODE_MINOR
24665#undef JSON_HEDLEY_VERSION_DECODE_REVISION
24666#undef JSON_HEDLEY_VERSION_ENCODE
24667#undef JSON_HEDLEY_WARNING
24668#undef JSON_HEDLEY_WARN_UNUSED_RESULT
24669#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
24670#undef JSON_HEDLEY_FALL_THROUGH
24671
24672
24673
24674#endif // INCLUDE_NLOHMANN_JSON_HPP_
namespace for Niels Lohmann
Definition json.hpp:19313
constexpr bool is_string() const noexcept
return whether value is a string
Definition json.hpp:20587
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:21821
reference operator[](KeyType &&key)
access specified object element
Definition json.hpp:21389
size_type size() const noexcept
returns the number of elements
Definition json.hpp:22165
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:23601
static std::vector< std::uint8_t > to_bjdata(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition json.hpp:23533
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
get a (pointer) value (explicit)
Definition json.hpp:20960
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22021
reference back()
access the last element
Definition json.hpp:21625
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value from compatible types
Definition json.hpp:20053
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22037
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition json.hpp:24195
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
Definition json.hpp:23380
const_reference front() const
access the first element
Definition json.hpp:21618
constexpr bool is_array() const noexcept
return whether value is an array
Definition json.hpp:20580
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:21569
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:21939
iter_impl< const basic_json > const_iterator
a const iterator for a basic_json container
Definition json.hpp:19445
static void to_bjdata(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition json.hpp:23552
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition json.hpp:19388
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition json.hpp:20552
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition json.hpp:19449
data(size_type cnt, const basic_json &val)
Definition json.hpp:23425
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.hpp:23798
static void to_bjdata(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition json.hpp:23544
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:23843
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition json.hpp:19440
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 &&std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:22683
std::size_t size_type
a type to represent container sizes
Definition json.hpp:19432
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.hpp:20524
const_reference operator[](KeyType &&key) const
access specified object element
Definition json.hpp:21413
const value_type & const_reference
the type of an element const reference
Definition json.hpp:19427
void swap(binary_t &other)
exchanges the values
Definition json.hpp:22760
ReferenceType get_ref()
get a reference value (implicit)
Definition json.hpp:21050
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.hpp:22204
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:22629
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:21061
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:20601
JSON_PRIVATE_UNLESS_TESTED const_reference rhs
Definition json.hpp:22878
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.hpp:22421
void push_back(basic_json &&val)
add an object to an array
Definition json.hpp:22309
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition json.hpp:21358
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:22109
const_reference back() const
access the last element
Definition json.hpp:21634
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:21716
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:22366
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:23698
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:20187
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition json.hpp:22533
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.hpp:23783
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:19456
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
Definition json.hpp:19583
reference at(KeyType &&key)
access specified object element with bounds checking
Definition json.hpp:21221
iterator end() noexcept
returns an iterator to one past the last element
Definition json.hpp:22012
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:20559
void update(const_iterator first, const_iterator last, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:22636
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition json.hpp:23560
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22044
data m_data
Definition json.hpp:23443
void push_back(initializer_list_t init)
add an object to an object
Definition json.hpp:22405
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
Definition json.hpp:20020
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.hpp:20228
ValueType & get_to(ValueType &v) const
Definition json.hpp:21027
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
create a MessagePack serialization of a given JSON value
Definition json.hpp:23499
iterator begin() noexcept
returns an iterator to the first element
Definition json.hpp:21987
JSON_PRIVATE_UNLESS_TESTED const_reference bool inverse
Definition json.hpp:22878
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition json.hpp:21468
const_iterator cend() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22028
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.hpp:23753
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:23885
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition json.hpp:20198
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:20041
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:23585
basic_json flatten() const
return flattened JSON value
Definition json.hpp:23899
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:23713
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition json.hpp:21832
const binary_t & get_binary() const
get a binary value
Definition json.hpp:21132
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition json.hpp:22553
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition json.hpp:23924
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:21521
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
Definition json.hpp:24205
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:23857
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition json.hpp:19559
value_type & reference
the type of an element reference
Definition json.hpp:19425
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition json.hpp:21956
static void to_cbor(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a CBOR serialization of a given JSON value
Definition json.hpp:23469
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
create a BSON serialization of a given JSON value
Definition json.hpp:23576
iterator find(const typename object_t::key_type &key)
find an element in a JSON object
Definition json.hpp:21869
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
Definition json.hpp:20176
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition json.hpp:21259
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.hpp:19464
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:20235
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition json.hpp:21883
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.hpp:23460
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:21646
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition json.hpp:22506
NumberFloatType number_float_t
a type for a number (floating-point)
Definition json.hpp:19579
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:21443
AllocatorType< basic_json > allocator_type
the allocator type
Definition json.hpp:19435
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition json.hpp:19438
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition json.hpp:20488
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.hpp:24347
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition json.hpp:21014
reference operator[](T *key)
Definition json.hpp:21374
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:21155
iterator find(KeyType &&key)
find an element in a JSON object
Definition json.hpp:21899
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition json.hpp:20566
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.hpp:22051
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:23506
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:23871
BooleanType boolean_t
a type for a boolean
Definition json.hpp:19567
detail::value_t value_t
Definition json.hpp:19378
std::less< StringType > default_object_comparator_t
default object key comparator type The actual object key comparator type (object_comparator_t) may be...
Definition json.hpp:19546
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:22397
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition json.hpp:22003
reference operator[](typename object_t::key_type key)
access specified object element
Definition json.hpp:21336
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:20772
~basic_json() noexcept
destructor
Definition json.hpp:20470
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition json.hpp:22072
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition json.hpp:20120
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.hpp:22776
binary_t & get_binary()
get a binary value
Definition json.hpp:21120
const_iterator begin() const noexcept
returns an iterator to the first element
Definition json.hpp:21996
constexpr bool is_number() const noexcept
return whether value is a number
Definition json.hpp:20545
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition json.hpp:22604
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:23644
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:21001
const_reference operator[](T *key) const
Definition json.hpp:21380
data(const value_t v)
Definition json.hpp:23420
reference operator[](size_type idx)
access specified array element
Definition json.hpp:21277
basic_json(const JsonRef &ref)
Definition json.hpp:20357
JSONSerializer< T, SFINAE > json_serializer
Definition json.hpp:19382
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value &&std::is_nothrow_move_assignable< json_base_class_t >::value)
copy assignment
Definition json.hpp:20447
static iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
wrapper to access iterator member functions in range-based for
Definition json.hpp:22084
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:23525
Array get_to(T(&v)[N]) const noexcept(noexcept(JSONSerializer< Array >::from_json(std::declval< const basic_json_t & >(), v)))
Definition json.hpp:21038
NumberIntegerType number_integer_t
a type for a number (integer)
Definition json.hpp:19571
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:20761
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:21239
constexpr bool is_binary() const noexcept
return whether value is a binary array
Definition json.hpp:20594
void swap(object_t &other)
exchanges the values
Definition json.hpp:22728
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.hpp:23908
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition json.hpp:22584
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:20209
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:22102
bool empty() const noexcept
checks whether the container is empty.
Definition json.hpp:22126
void swap(array_t &other)
exchanges the values
Definition json.hpp:22712
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:21839
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:22334
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.hpp:21963
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.hpp:20510
reference emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:22430
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:21544
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.hpp:20220
data() noexcept=default
StringType string_t
a type for a string
Definition json.hpp:19563
friend class ::nlohmann::detail::parser
Definition json.hpp:19323
ObjectType< StringType, basic_json, default_object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
Definition json.hpp:19555
void push_back(const basic_json &val)
add an object to an array
Definition json.hpp:22342
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:21494
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:21201
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.hpp:23768
json_value m_value
the value of the current element
Definition json.hpp:23418
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.hpp:22065
json_sax< basic_json > json_sax_t
SAX interface type, see nlohmann::json_sax.
Definition json.hpp:19392
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition json.hpp:20538
size_type count(const typename object_t::key_type &key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:21929
reference front()
access the first element
Definition json.hpp:21611
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:20517
constexpr bool is_null() const noexcept
return whether value is null
Definition json.hpp:20531
void clear() noexcept
clears the contents
Definition json.hpp:22248
static void to_ubjson(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:23517
JSON_PRIVATE_UNLESS_TESTED const_reference bool static SAX bool sax_parse(InputType &&i, SAX *sax, input_format_t format=input_format_t::json, const bool strict=true, const bool ignore_comments=false)
Definition json.hpp:23304
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:20430
iter_impl< basic_json > iterator
an iterator for a basic_json container
Definition json.hpp:19443
basic_json(const value_t v)
create an empty value with a given type
Definition json.hpp:20033
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:21323
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition json.hpp:19430
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition json.hpp:22526
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition json.hpp:22058
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition json.hpp:19575
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition json.hpp:23365
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:23483
void swap(string_t &other)
exchanges the values
Definition json.hpp:22744
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.hpp:20067
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition json.hpp:19447
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 &&std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:22700
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:21178
detail::actual_object_comparator_t< basic_json > object_comparator_t
object key comparator type
Definition json.hpp:19587
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:20361
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:22374
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:22455
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
create a CBOR serialization of a given JSON value
Definition json.hpp:23476
constexpr bool is_object() const noexcept
return whether value is an object
Definition json.hpp:20573
static void to_msgpack(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a MessagePack serialization of a given JSON value
Definition json.hpp:23492
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:23659
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition json.hpp:22487
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:20247
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition json.hpp:23358
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition json.hpp:21947
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a BSON serialization of a given JSON value
Definition json.hpp:23569
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition json.hpp:21915
::nlohmann::json_pointer< StringType > json_pointer
JSON Pointer, see nlohmann::json_pointer.
Definition json.hpp:19380
an internal type for a backed binary type
Definition json.hpp:5824
bool operator!=(const byte_container_with_subtype &rhs) const
Definition json.hpp:5864
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.hpp:5830
std::uint64_t subtype_type
Definition json.hpp:5827
bool operator==(const byte_container_with_subtype &rhs) const
Definition json.hpp:5858
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:5852
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:5840
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.hpp:5879
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.hpp:5845
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.hpp:5886
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.hpp:5835
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.hpp:5871
void clear_subtype() noexcept
clears the binary subtype
Definition json.hpp:5893
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:9146
binary_reader(const binary_reader &)=delete
binary_reader(binary_reader &&)=default
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.hpp:9162
binary_reader & operator=(const binary_reader &)=delete
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
Definition json.hpp:9183
binary_reader & operator=(binary_reader &&)=default
general exception of the basic_json class
Definition json.hpp:4305
const int id
the id of the exception
Definition json.hpp:4314
static std::string diagnostics(std::nullptr_t)
Definition json.hpp:4325
static std::string name(const std::string &ename, int id_)
Definition json.hpp:4320
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:4308
static std::string diagnostics(const BasicJsonType *leaf_element)
Definition json.hpp:4331
exception indicating errors with iterators
Definition json.hpp:4456
static invalid_iterator create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4459
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition json.hpp:12838
~iter_impl()=default
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:13412
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:12975
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:13357
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:12965
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:13304
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:13339
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:13403
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:13218
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:13512
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.hpp:13259
iter_impl operator++(int) &
post-increment (it++)
Definition json.hpp:13156
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:13366
reference operator[](difference_type n) const
access to successor
Definition json.hpp:13474
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition json.hpp:12868
pointer operator->() const
dereference the iterator
Definition json.hpp:13114
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
Definition json.hpp:13537
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:13445
iter_impl(iter_impl &&) noexcept=default
std::bidirectional_iterator_tag iterator_category
Definition json.hpp:12863
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:13423
reference value() const
return the value of an iterator
Definition json.hpp:13528
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:13348
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition json.hpp:12872
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:13167
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition json.hpp:12866
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:13070
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:13434
iter_impl()=default
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.hpp:12950
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition json.hpp:13295
iter_impl operator--(int) &
post-decrement (it–)
Definition json.hpp:13207
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition json.hpp:12877
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.hpp:12940
void set_end() noexcept
set the iterator past the last value
Definition json.hpp:13031
iteration_proxy_value operator++(int) &
Definition json.hpp:5175
iteration_proxy_value(iteration_proxy_value const &)=default
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.hpp:5184
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.hpp:5190
std::ptrdiff_t difference_type
Definition json.hpp:5121
iteration_proxy_value(IteratorType it, std::size_t array_index_=0) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_default_constructible< string_type >::value)
Definition json.hpp:5142
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:5167
iteration_proxy_value(iteration_proxy_value &&) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_move_constructible< string_type >::value)=default
IteratorType::reference value() const
return value of the iterator
Definition json.hpp:5232
const string_type & key() const
return key of the iterator
Definition json.hpp:5196
iteration_proxy_value & operator=(iteration_proxy_value const &)=default
std::input_iterator_tag iterator_category
Definition json.hpp:5125
typename std::remove_cv< typename std::remove_reference< decltype(std::declval< IteratorType >().key()) >::type >::type string_type
Definition json.hpp:5126
proxy class for the items() function
Definition json.hpp:5240
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.hpp:5265
iteration_proxy(iteration_proxy const &)=default
iteration_proxy(iteration_proxy &&) noexcept=default
iteration_proxy_value< IteratorType > begin() const noexcept
return iterator begin (needed for range-based for)
Definition json.hpp:5259
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:5249
iteration_proxy & operator=(iteration_proxy const &)=default
json_ref(json_ref &&) noexcept=default
json_ref(const value_type &value)
Definition json.hpp:14742
json_ref(value_type &&value)
Definition json.hpp:14738
value_type const & operator*() const
Definition json.hpp:14773
value_type const * operator->() const
Definition json.hpp:14778
json_ref(std::initializer_list< json_ref > init)
Definition json.hpp:14746
json_ref(Args &&... args)
Definition json.hpp:14753
value_type moved_or_copied() const
Definition json.hpp:14764
BasicJsonType value_type
Definition json.hpp:14736
a template for a reverse iterator class
Definition json.hpp:13591
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition json.hpp:13607
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition json.hpp:13619
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.hpp:13613
std::ptrdiff_t difference_type
Definition json.hpp:13593
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.hpp:13631
reference operator[](difference_type n) const
access to successor
Definition json.hpp:13655
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.hpp:13661
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.hpp:13649
typename Base::reference reference
the reference type for the pointed-to element
Definition json.hpp:13597
reference value() const
return the value of an iterator
Definition json.hpp:13668
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.hpp:13604
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.hpp:13625
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.hpp:13595
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.hpp:13643
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.hpp:13600
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.hpp:13637
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:7228
bool start_object(std::size_t=static_cast< std::size_t >(-1))
Definition json.hpp:7268
bool binary(binary_t &)
Definition json.hpp:7263
bool number_integer(number_integer_t)
Definition json.hpp:7243
bool start_array(std::size_t=static_cast< std::size_t >(-1))
Definition json.hpp:7283
bool number_unsigned(number_unsigned_t)
Definition json.hpp:7248
bool string(string_t &)
Definition json.hpp:7258
typename BasicJsonType::binary_t binary_t
Definition json.hpp:7231
bool number_float(number_float_t, const string_t &)
Definition json.hpp:7253
bool parse_error(std::size_t, const std::string &, const detail::exception &)
Definition json.hpp:7293
bool key(string_t &)
Definition json.hpp:7273
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:7227
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:7229
typename BasicJsonType::string_t string_t
Definition json.hpp:7230
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:7106
typename BasicJsonType::string_t string_t
Definition json.hpp:6923
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:6967
constexpr bool is_errored() const
Definition json.hpp:7118
json_sax_dom_callback_parser & operator=(const json_sax_dom_callback_parser &)=delete
json_sax_dom_callback_parser(const json_sax_dom_callback_parser &)=delete
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:6921
typename BasicJsonType::binary_t binary_t
Definition json.hpp:6924
bool start_object(std::size_t len)
Definition json.hpp:6985
bool start_array(std::size_t len)
Definition json.hpp:7056
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:6920
json_sax_dom_callback_parser(json_sax_dom_callback_parser &&)=default
typename BasicJsonType::parse_event_t parse_event_t
Definition json.hpp:6926
typename BasicJsonType::parser_callback_t parser_callback_t
Definition json.hpp:6925
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:6961
json_sax_dom_callback_parser & operator=(json_sax_dom_callback_parser &&)=default
json_sax_dom_callback_parser(BasicJsonType &r, const parser_callback_t cb, const bool allow_exceptions_=true)
Definition json.hpp:6928
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:6922
bool number_integer(number_integer_t val)
Definition json.hpp:6955
SAX implementation to create a JSON value from SAX events.
Definition json.hpp:6735
json_sax_dom_parser(const json_sax_dom_parser &)=delete
json_sax_dom_parser & operator=(json_sax_dom_parser &&)=default
bool string(string_t &val)
Definition json.hpp:6789
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true)
Definition json.hpp:6748
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:6856
typename BasicJsonType::string_t string_t
Definition json.hpp:6740
bool start_object(std::size_t len)
Definition json.hpp:6801
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:6738
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:6777
bool number_integer(number_integer_t val)
Definition json.hpp:6771
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:6737
json_sax_dom_parser & operator=(const json_sax_dom_parser &)=delete
bool binary(binary_t &val)
Definition json.hpp:6795
json_sax_dom_parser(json_sax_dom_parser &&)=default
bool boolean(bool val)
Definition json.hpp:6765
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:6783
constexpr bool is_errored() const
Definition json.hpp:6868
typename BasicJsonType::binary_t binary_t
Definition json.hpp:6741
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:6739
bool start_array(std::size_t len)
Definition json.hpp:6833
bool key(string_t &val)
Definition json.hpp:6813
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
Definition json.hpp:7367
token_type
token types for the parser
Definition json.hpp:7344
lexical analysis
Definition json.hpp:7417
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.hpp:8791
void skip_whitespace()
Definition json.hpp:8805
lexer(InputAdapterType &&adapter, bool ignore_comments_=false) noexcept
Definition json.hpp:7428
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.hpp:8778
std::string get_token_string() const
Definition json.hpp:8753
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.hpp:8717
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.hpp:8745
token_type scan()
Definition json.hpp:8814
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.hpp:8723
typename lexer_base< BasicJsonType >::token_type token_type
Definition json.hpp:7426
lexer(lexer &&)=default
~lexer()=default
lexer & operator=(lexer &&)=default
lexer(const lexer &)=delete
lexer & operator=(lexer &)=delete
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.hpp:8735
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.hpp:8729
exception indicating other library errors
Definition json.hpp:4508
static other_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4511
exception indicating access out of the defined range
Definition json.hpp:4491
static out_of_range create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4494
exception indicating a parse error
Definition json.hpp:4403
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
Definition json.hpp:4415
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4423
const std::size_t byte
byte index of the parse error
Definition json.hpp:4440
std::array< char, 512 > string_buffer
string buffer
Definition json.hpp:18898
std::uint8_t state
Definition json.hpp:18316
std::size_t bytes_after_last_accept
Definition json.hpp:18320
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:17989
JSON_PRIVATE_UNLESS_TESTED const bool ensure_ascii
Definition json.hpp:18314
std::size_t undumped_chars
Definition json.hpp:18321
const char thousands_sep
the locale's thousand separator character
Definition json.hpp:18893
const char decimal_point
the locale's decimal point character
Definition json.hpp:18895
serializer & operator=(const serializer &)=delete
~serializer()=default
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition json.hpp:18906
string_t indent_string
the indentation string
Definition json.hpp:18903
const std::lconv * loc
the locale
Definition json.hpp:18891
serializer & operator=(serializer &&)=delete
std::array< char, 64 > number_buffer
a (hopefully) large enough character buffer
Definition json.hpp:18888
const char indent_char
the indentation character
Definition json.hpp:18901
std::size_t bytes
Definition json.hpp:18317
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition json.hpp:18029
serializer(const serializer &)=delete
serializer(serializer &&)=delete
exception indicating executing a member function with a wrong type
Definition json.hpp:4474
static type_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4477
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition json.hpp:13755
friend json_pointer operator/(const json_pointer &lhs, string_t token)
create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
Definition json.hpp:13850
typename string_t_helper< RefStringType >::type string_t
Definition json.hpp:13777
friend json_pointer operator/(const json_pointer &lhs, std::size_t array_idx)
create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
Definition json.hpp:13857
json_pointer(const string_t &s="")
create JSON pointer
Definition json.hpp:13781
bool empty() const noexcept
return whether pointer points to the root document
Definition json.hpp:13916
friend bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for equality
Definition json.hpp:14650
void pop_back()
remove last reference token
Definition json.hpp:13878
string_t to_string() const
return a string representation of the JSON pointer
Definition json.hpp:13787
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition json.hpp:13835
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:13909
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition json.hpp:13817
friend json_pointer operator/(const json_pointer &lhs, const json_pointer &rhs)
create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
Definition json.hpp:13842
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition json.hpp:13864
friend bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for inequality
Definition json.hpp:14675
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition json.hpp:13827
friend class json_pointer
Definition json.hpp:13761
const string_t & back() const
return last reference token
Definition json.hpp:13890
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition json.hpp:13808
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:13902
friend bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointer for less-than
Definition json.hpp:14700
decltype(get< N >(std::declval< ::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
Definition json.hpp:5313
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
Definition json.hpp:2588
#define JSON_HEDLEY_CONST
Definition json.hpp:1818
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
Definition json.hpp:1102
#define JSON_INLINE_VARIABLE
Definition json.hpp:2491
#define JSON_HEDLEY_WARN_UNUSED_RESULT
Definition json.hpp:1448
#define JSON_PRIVATE_UNLESS_TESTED
Definition json.hpp:2551
#define NLOHMANN_JSON_VERSION_PATCH
Definition json.hpp:70
#define JSON_HEDLEY_LIKELY(expr)
Definition json.hpp:1713
#define JSON_HEDLEY_NON_NULL(...)
Definition json.hpp:1606
#define JSON_INTERNAL_CATCH(exception)
Definition json.hpp:2518
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition json.hpp:24379
#define JSON_HEDLEY_RETURNS_NON_NULL
Definition json.hpp:2047
bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:14650
#define JSON_CATCH(exception)
Definition json.hpp:2517
#define JSON_ASSERT(x)
Definition json.hpp:2544
#define JSON_THROW(exception)
Definition json.hpp:2515
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
Definition json.hpp:77
#define NLOHMANN_JSON_VERSION_MAJOR
Definition json.hpp:68
#define NLOHMANN_BASIC_JSON_TPL
Definition json.hpp:2598
#define JSON_HEDLEY_UNLIKELY(expr)
Definition json.hpp:1714
#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
Definition json.hpp:12053
#define JSON_TRY
Definition json.hpp:2516
#define NLOHMANN_JSON_NAMESPACE_END
Definition json.hpp:144
#define JSON_NO_UNIQUE_ADDRESS
Definition json.hpp:2497
bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:14675
basic_json< nlohmann::ordered_map > ordered_json
specialization that maintains the insertion order of object keys
Definition json.hpp:3417
#define NLOHMANN_JSON_VERSION_MINOR
Definition json.hpp:69
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)
Definition json.hpp:2773
#define NLOHMANN_JSON_NAMESPACE_BEGIN
Definition json.hpp:134
#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
Definition json.hpp:12050
basic_json<> json
default specialization
Definition json.hpp:3408
#define JSON_HEDLEY_DIAGNOSTIC_POP
Definition json.hpp:1103
#define JSON_EXPLICIT
Definition json.hpp:2810
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
Definition json.hpp:1396
#define JSON_HEDLEY_PURE
Definition json.hpp:1787
bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:14700
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)
Definition json.hpp:22801
constexpr bool is_transparent()
Definition json.hpp:4126
constexpr bool is_c_string()
Definition json.hpp:4098
detail namespace with internal helper functions
Definition json.hpp:249
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
Definition json.hpp:5713
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
Definition json.hpp:309
typename make_void< Ts... >::type void_t
Definition json.hpp:255
decltype(std::declval< StringType & >()+=std::declval< Arg && >()) string_can_append_op
Definition json.hpp:4207
OutStringType concat(Args &&... args)
Definition json.hpp:4281
is_detected< string_can_append_iter, StringType, Arg > detect_string_can_append_iter
Definition json.hpp:4216
decltype(T::to_json(std::declval< Args >()...)) to_json_function
Definition json.hpp:3503
constexpr std::array< T, sizeof...(Args)> make_array(Args &&... args)
Definition json.hpp:3209
decltype(std::declval< T >().template get< U >()) get_template_function
Definition json.hpp:3509
typename std::conditional< is_usable_as_key_type< typename BasicJsonType::object_comparator_t, typename BasicJsonType::object_t::key_type, KeyTypeCVRef, RequireTransparentComparator, ExcludeObjectKeyType >::value &&!is_json_iterator_of< BasicJsonType, KeyType >::value, std::true_type, std::false_type >::type is_usable_as_basic_json_key_type
Definition json.hpp:3947
typename T::pointer pointer_t
Definition json.hpp:3494
is_detected< string_can_append_op, StringType, Arg > detect_string_can_append_op
Definition json.hpp:4210
integer_sequence< size_t, Ints... > index_sequence
Definition json.hpp:3124
typename utility_internal::Gen< T, N >::type make_integer_sequence
Definition json.hpp:3170
typename T::value_type value_type_t
Definition json.hpp:3488
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
Definition json.hpp:313
T conditional_static_cast(U value)
Definition json.hpp:3981
is_detected< string_can_append_data, StringType, Arg > detect_string_can_append_data
Definition json.hpp:4222
typename std::enable_if< B, T >::type enable_if_t
Definition json.hpp:3082
is_specialization_of<::nlohmann::json_pointer, uncvref_t< T > > is_json_pointer
Definition json.hpp:3904
typename T::mapped_type mapped_type_t
Definition json.hpp:3482
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.hpp:2958
enable_if_t< is_range< R >::value, result_of_begin< decltype(std::declval< R & >())> > iterator_t
Definition json.hpp:3675
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition json.hpp:5275
conjunction< std::is_integral< Types >... > all_integral
Definition json.hpp:3993
cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:9118
@ store
store tags as binary type
@ error
throw a parse_error exception in case of a tag
typename detected_or< Default, Op, Args... >::type detected_or_t
Definition json.hpp:306
decltype(T::from_json(std::declval< Args >()...)) from_json_function
Definition json.hpp:3506
conjunction< std::is_unsigned< Types >... > all_unsigned
Definition json.hpp:3999
make_integer_sequence< size_t, N > make_index_sequence
Definition json.hpp:3178
std::integral_constant< bool, Value > bool_constant
Definition json.hpp:4088
void concat_into(OutStringType &)
Definition json.hpp:4197
typename T::key_type key_type_t
Definition json.hpp:3485
constexpr bool value_in_range_of(T val)
Definition json.hpp:4082
value_t
the JSON type enumeration
Definition json.hpp:2860
@ null
null value
@ number_integer
number value (signed integer)
@ boolean
boolean value
@ discarded
discarded by the parser callback function
@ binary
binary array (ordered collection of bytes)
@ object
object (unordered set of name/value pairs)
@ string
string value
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
std::integral_constant< bool, all_signed< Types... >::value||all_unsigned< Types... >::value > same_sign
Definition json.hpp:4004
typename detector< nonesuch, void, Op, Args... >::type detected_t
Definition json.hpp:300
typename std::conditional< is_comparable< Comparator, ObjectKeyType, KeyTypeCVRef >::value &&!(ExcludeObjectKeyType &&std::is_same< KeyType, ObjectKeyType >::value) &&(!RequireTransparentComparator||is_detected< detect_is_transparent, Comparator >::value) &&!is_json_pointer< KeyType >::value, std::true_type, std::false_type >::type is_usable_as_key_type
Definition json.hpp:3931
is_c_string< uncvref_t< T > > is_c_string_uncvref
Definition json.hpp:4116
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().begin(), std::declval< const Arg & >().end())) string_can_append_iter
Definition json.hpp:4213
typename T::iterator_category iterator_category_t
Definition json.hpp:3500
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:2889
typename std::conditional< is_detected< detect_erase_with_key_type, typename BasicJsonType::object_t, KeyType >::value, std::true_type, std::false_type >::type has_erase_with_key_type
Definition json.hpp:3959
error_handler_t
how to treat decoding errors
Definition json.hpp:17966
@ strict
throw a type_error exception in case of invalid UTF-8
@ ignore
ignore invalid UTF-8 sequences
@ replace
replace invalid UTF-8 sequences with U+FFFD
std::size_t concat_length()
Definition json.hpp:4166
value_type_t< iterator_traits< iterator_t< T > > > range_value_t
Definition json.hpp:3678
conjunction< std::is_signed< Types >... > all_signed
Definition json.hpp:3996
typename actual_object_comparator< BasicJsonType >::type actual_object_comparator_t
Definition json.hpp:3582
decltype(std::declval< StringType & >().append(std::declval< Arg && >())) string_can_append
Definition json.hpp:4201
void to_json(BasicJsonType &j, T b) noexcept
Definition json.hpp:5575
make_index_sequence< sizeof...(Ts)> index_sequence_for
Definition json.hpp:3186
typename T::difference_type difference_type_t
Definition json.hpp:3491
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition json.hpp:3068
typename T::is_transparent detect_is_transparent
Definition json.hpp:3917
typename std::conditional< std::is_same< T, void >::value, json_default_base, T >::type json_base_class
Definition json.hpp:13709
typename T::reference reference_t
Definition json.hpp:3497
decltype(std::declval< ObjectType & >().erase(std::declval< KeyType >())) detect_erase_with_key_type
Definition json.hpp:3950
typename T::key_compare detect_key_compare
Definition json.hpp:3566
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().data(), std::declval< const Arg & >().size())) string_can_append_data
Definition json.hpp:4219
typename detector< nonesuch, void, Op, Args... >::value_t is_detected
Definition json.hpp:294
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:2977
void int_to_string(string_type &target, std::size_t value)
Definition json.hpp:5112
std::integral_constant< bool,(std::is_signed< OfType >::value &&(sizeof(T)< sizeof(OfType)))||(same_sign< OfType, T >::value &&sizeof(OfType)==sizeof(T)) > never_out_of_range
Definition json.hpp:4009
is_detected< string_can_append, StringType, Arg > detect_string_can_append
Definition json.hpp:4204
Definition json.hpp:5296
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition json.hpp:24452
namespace for Niels Lohmann
Definition json.hpp:5766
static auto to_json(BasicJsonType &j, TargetType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< TargetType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< TargetType >(val)), void())
convert any value type to a JSON value
Definition json.hpp:5790
static auto from_json(BasicJsonType &&j) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))
convert a JSON value to any value type
Definition json.hpp:5780
static auto from_json(BasicJsonType &&j, TargetType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
Definition json.hpp:5770
typename BasicJsonType::object_t object_t
Definition json.hpp:3575
typename BasicJsonType::default_object_comparator_t object_comparator_t
Definition json.hpp:3576
typename std::conditional< has_key_compare< object_t >::value, typename object_t::key_compare, object_comparator_t >::type type
Definition json.hpp:3578
std::false_type value_t
Definition json.hpp:282
Default type
Definition json.hpp:283
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
Definition json.hpp:5500
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
Definition json.hpp:5475
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
Definition json.hpp:5465
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
Definition json.hpp:5487
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
Definition json.hpp:5516
static void construct(BasicJsonType &j, const typename BasicJsonType::binary_t &b)
Definition json.hpp:5404
static void construct(BasicJsonType &j, typename BasicJsonType::binary_t &&b)
Definition json.hpp:5413
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
Definition json.hpp:5358
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
Definition json.hpp:5426
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
Definition json.hpp:5452
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
Definition json.hpp:5439
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
Definition json.hpp:5535
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
Definition json.hpp:5556
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
Definition json.hpp:5545
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
Definition json.hpp:5380
static void construct(BasicJsonType &j, const CompatibleStringType &str)
Definition json.hpp:5391
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
Definition json.hpp:5371
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3528
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3543
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3558
static constexpr std::size_t size() noexcept
Definition json.hpp:3112
an iterator value
Definition json.hpp:12771
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition json.hpp:12775
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition json.hpp:12777
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition json.hpp:12773
static constexpr auto value
Definition json.hpp:3750
ConstructibleStringType laundered_type
Definition json.hpp:3761
static constexpr auto value
Definition json.hpp:3764
static constexpr bool value
Definition json.hpp:3522
static one test(decltype(&C::capacity))
static two test(...)
static constexpr bool value
Definition json.hpp:3671
Default base class of the basic_json class.
Definition json.hpp:13702
nonesuch(nonesuch const &&)=delete
~nonesuch()=delete
void operator=(nonesuch &&)=delete
void operator=(nonesuch const &)=delete
nonesuch(nonesuch const &)=delete
struct to capture the start position of the current token
Definition json.hpp:3023
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:3027
std::size_t lines_read
the number of lines read
Definition json.hpp:3029
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:3025
static JSON_INLINE_VARIABLE constexpr T value
Definition json.hpp:3200
auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward< T >(val)))) -> decltype(to_json(j, std::forward< T >(val)), void())
Definition json.hpp:5735
integer_sequence< T, Ints...,(Ints+SeqSize)..., 2 *SeqSize > type
Definition json.hpp:3142
typename Extend< typename Gen< T, N/2 >::type, N/2, N % 2 >::type type
Definition json.hpp:3151
SAX interface.
Definition json.hpp:6604
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
json_sax()=default
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:6605
typename BasicJsonType::string_t string_t
Definition json.hpp:6608
virtual bool end_array()=0
the end of an array was read
json_sax(const json_sax &)=default
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:6607
virtual bool null()=0
a null value was read
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:6606
json_sax(json_sax &&) noexcept=default
typename BasicJsonType::binary_t binary_t
Definition json.hpp:6609
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:18948
std::vector< std::pair< const Key, T >, Allocator > Container
Definition json.hpp:18951
std::pair< iterator, bool > insert(value_type &&value)
Definition json.hpp:19242
typename Container::value_type value_type
Definition json.hpp:18955
std::equal_to< Key > key_compare
Definition json.hpp:18959
iterator erase(iterator pos)
Definition json.hpp:19120
ordered_map(const Allocator &alloc) noexcept(noexcept(Container(alloc)))
Definition json.hpp:18965
T & operator[](KeyType &&key)
Definition json.hpp:19007
typename Container::iterator iterator
Definition json.hpp:18952
const T & at(KeyType &&key) const
Definition json.hpp:19067
T & at(KeyType &&key)
Definition json.hpp:19039
const T & operator[](KeyType &&key) const
Definition json.hpp:19019
iterator find(const key_type &key)
Definition json.hpp:19204
iterator erase(iterator first, iterator last)
Definition json.hpp:19125
const T & at(const key_type &key) const
Definition json.hpp:19052
const_iterator find(const key_type &key) const
Definition json.hpp:19230
T & operator[](const key_type &key)
Definition json.hpp:19000
size_type erase(KeyType &&key)
Definition json.hpp:19101
typename Container::size_type size_type
Definition json.hpp:18954
ordered_map() noexcept(noexcept(Container()))
Definition json.hpp:18964
void insert(InputIt first, InputIt last)
Definition json.hpp:19265
size_type count(const key_type &key) const
Definition json.hpp:19178
std::pair< iterator, bool > emplace(KeyType &&key, T &&t)
Definition json.hpp:18987
size_type erase(const key_type &key)
Definition json.hpp:19080
ordered_map(std::initializer_list< value_type > init, const Allocator &alloc=Allocator())
Definition json.hpp:18969
std::pair< iterator, bool > insert(const value_type &value)
Definition json.hpp:19247
size_type count(KeyType &&key) const
Definition json.hpp:19192
ordered_map(It first, It last, const Allocator &alloc=Allocator())
Definition json.hpp:18967
typename std::enable_if< std::is_convertible< typename std::iterator_traits< InputIt >::iterator_category, std::input_iterator_tag >::value >::type require_input_iter
Definition json.hpp:19262
const T & operator[](const key_type &key) const
Definition json.hpp:19012
iterator find(KeyType &&key)
Definition json.hpp:19218
T & at(const key_type &key)
Definition json.hpp:19024
typename Container::const_iterator const_iterator
Definition json.hpp:18953
std::pair< iterator, bool > emplace(const key_type &key, T &&t)
Definition json.hpp:18972
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL &j) const
Definition json.hpp:24421
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:24435